codebase-onboarder 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/README.md +196 -47
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +449 -0
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +396 -229
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +400 -162
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +73 -0
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +173 -0
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +184 -95
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +496 -412
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +33 -0
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +235 -138
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +55 -35
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +165 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +60 -0
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -37
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +79 -0
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
package/public/js/api.js CHANGED
@@ -1,228 +1,237 @@
1
1
  // Server round-trips. Thin and honest: JSON in, JSON (or an SSE stream) out,
2
2
  // server error messages surfaced untouched.
3
-
4
3
  // Browser access is an HttpOnly session cookie set by the themed self-hosted
5
4
  // login page. Same-origin fetches include it automatically, and JavaScript never
6
5
  // reads or stores the access key. API clients can still use `Authorization:
7
6
  // Bearer …`; local mode needs no credential at all.
8
-
9
7
  // 0.3.0 briefly stored a raw self-hosted key here. Remove that legacy value on
10
8
  // first load so upgrading also removes the old secret rather than merely ignoring it.
11
- try { localStorage.removeItem('onboarder.accessKey'); } catch { /* storage may be unavailable */ }
12
-
13
- async function postJSON(url, body) {
14
- const res = await fetch(url, {
15
- method: 'POST',
16
- headers: { 'content-type': 'application/json' },
17
- body: JSON.stringify(body),
18
- });
19
- let data = null;
20
- try {
21
- data = await res.json();
22
- } catch {
23
- /* error path handled below with a generic message */
24
- }
25
- if (!res.ok) {
26
- throw new Error(data?.error || `The server said ${res.status}.`);
27
- }
28
- return data;
29
- }
30
-
31
- export function scanOnServer(payload) {
32
- return postJSON('/api/scan', payload);
33
- }
34
-
9
+ try {
10
+ localStorage.removeItem('onboarder.accessKey');
11
+ }
12
+ catch { /* storage may be unavailable */ }
13
+ async function postJSON(url, body, options = {}) {
14
+ const res = await fetch(url, {
15
+ method: 'POST',
16
+ signal: options.signal,
17
+ headers: { 'content-type': 'application/json' },
18
+ body: JSON.stringify(body),
19
+ });
20
+ let data = null;
21
+ try {
22
+ data = await res.json();
23
+ }
24
+ catch {
25
+ /* error path handled below with a generic message */
26
+ }
27
+ if (!res.ok) {
28
+ throw new Error(data?.error || `The server said ${res.status}.`);
29
+ }
30
+ return data;
31
+ }
32
+ export function scanOnServer(payload, options = {}) {
33
+ return postJSON('/api/scan', payload, options);
34
+ }
35
35
  export async function cleanupClone(cloneId) {
36
- try {
37
- await fetch('/api/scan/' + encodeURIComponent(cloneId), { method: 'DELETE' });
38
- } catch {
39
- /* best-effort: the temp dir expires on its own eventually */
40
- }
36
+ try {
37
+ await fetch('/api/scan/' + encodeURIComponent(cloneId), { method: 'DELETE' });
38
+ }
39
+ catch {
40
+ /* best-effort: the temp dir expires on its own eventually */
41
+ }
41
42
  }
42
-
43
43
  export async function fetchFileText(scanId, path) {
44
- const res = await fetch('/api/file?scan=' + encodeURIComponent(scanId) + '&path=' + encodeURIComponent(path));
45
- if (!res.ok) throw new Error('Could not read that file from the server.');
46
- return res.text();
44
+ const res = await fetch('/api/file?scan=' + encodeURIComponent(scanId) + '&path=' + encodeURIComponent(path));
45
+ if (!res.ok)
46
+ throw new Error('Could not read that file from the server.');
47
+ return res.text();
47
48
  }
48
-
49
49
  // Which deep analyzers this machine can run, and how. Server-side scans only —
50
50
  // a browser-picked folder has no scan id and no server-visible root to point a
51
51
  // tool at, and this returns that honestly instead of pretending.
52
52
  export async function fetchToolsStatus() {
53
- try {
54
- const res = await fetch('/api/tools');
55
- if (!res.ok) return null;
56
- const data = await res.json();
57
- return data && data.tools ? data.tools : null;
58
- } catch {
59
- return null; // an unreachable server is just "no deep analysis here"
60
- }
61
- }
62
-
53
+ try {
54
+ const res = await fetch('/api/tools');
55
+ if (!res.ok)
56
+ return null;
57
+ const data = await res.json();
58
+ return data && data.tools ? data.tools : null;
59
+ }
60
+ catch {
61
+ return null; // an unreachable server is just "no deep analysis here"
62
+ }
63
+ }
63
64
  // Run the available analyzers against a live scan. `kinds`/`tools` narrow which
64
65
  // engines run; `options` carries the per-engine GUI settings, validated against
65
66
  // the registry schema on the server. The report normalizes every finding into
66
67
  // the shape the security view already draws, plus a per-engine pass list so
67
68
  // the UI can say which tool answered and which are missing.
68
69
  export function runAnalysisTools(scanId, options = {}) {
69
- return postJSON('/api/tools/run', {
70
- scanId,
71
- kinds: options.kinds || undefined,
72
- tools: options.tools || undefined,
73
- options: options.options || undefined,
74
- });
75
- }
76
-
70
+ return postJSON('/api/tools/run', {
71
+ scanId,
72
+ kinds: options.kinds || undefined,
73
+ tools: options.tools || undefined,
74
+ options: options.options || undefined,
75
+ });
76
+ }
77
77
  // Install a missing engine, streaming progress events. The server emits SSE
78
78
  // frames shaped like the explain stream, minus the OpenAI envelope:
79
79
  // { type: 'log', line } / { type: 'plan', label } / { type: 'done', ok, … }
80
80
  // `onEvent` gets each one as it arrives; the promise resolves with the final
81
81
  // `done` event (or throws if the request itself failed).
82
82
  export async function streamToolInstall(tool, onEvent) {
83
- const emit = typeof onEvent === 'function' ? onEvent : () => {};
84
- const res = await fetch('/api/tools/install', {
85
- method: 'POST',
86
- headers: { 'content-type': 'application/json' },
87
- body: JSON.stringify({ tool }),
88
- });
89
- if (!res.ok || !res.body) {
90
- let detail = '';
91
- try { detail = (await res.json()).error || ''; } catch { /* generic below */ }
92
- throw new Error(detail || `The server said ${res.status}.`);
93
- }
94
-
95
- const reader = res.body.getReader();
96
- const decoder = new TextDecoder();
97
- let buffer = '';
98
- let done = null;
99
- while (true) {
100
- const { done: ended, value } = await reader.read();
101
- if (ended) break;
102
- buffer += decoder.decode(value, { stream: true });
103
- const frames = buffer.split('\n\n');
104
- buffer = frames.pop();
105
- for (const frame of frames) {
106
- for (const line of frame.split('\n')) {
107
- if (!line.startsWith('data:')) continue;
83
+ const emit = typeof onEvent === 'function' ? onEvent : (..._args) => { };
84
+ const res = await fetch('/api/tools/install', {
85
+ method: 'POST',
86
+ headers: { 'content-type': 'application/json' },
87
+ body: JSON.stringify({ tool }),
88
+ });
89
+ if (!res.ok || !res.body) {
90
+ let detail = '';
108
91
  try {
109
- const event = JSON.parse(line.slice(5).trim());
110
- emit(event);
111
- if (event.type === 'done') done = event;
112
- } catch { /* a partial frame — the next chunk completes it */ }
113
- }
92
+ detail = (await res.json()).error || '';
93
+ }
94
+ catch { /* generic below */ }
95
+ throw new Error(detail || `The server said ${res.status}.`);
114
96
  }
115
- }
116
- return done || { type: 'done', ok: false, error: 'The install stream ended without a verdict.' };
97
+ const reader = res.body.getReader();
98
+ const decoder = new TextDecoder();
99
+ let buffer = '';
100
+ let done = null;
101
+ while (true) {
102
+ const { done: ended, value } = await reader.read();
103
+ if (ended)
104
+ break;
105
+ buffer += decoder.decode(value, { stream: true });
106
+ const frames = buffer.split('\n\n');
107
+ buffer = frames.pop();
108
+ for (const frame of frames) {
109
+ for (const line of frame.split('\n')) {
110
+ if (!line.startsWith('data:'))
111
+ continue;
112
+ try {
113
+ const event = JSON.parse(line.slice(5).trim());
114
+ emit(event);
115
+ if (event.type === 'done')
116
+ done = event;
117
+ }
118
+ catch { /* a partial frame — the next chunk completes it */ }
119
+ }
120
+ }
121
+ }
122
+ return done || { type: 'done', ok: false, error: 'The install stream ended without a verdict.' };
117
123
  }
118
-
119
124
  // The MCP button's three round-trips. The status one is a plain GET like
120
125
  // `/api/tools`; start and stop are POSTs because each one changes a process on
121
126
  // this machine, which is exactly the side effect `postJSON` is here for.
122
127
  export async function fetchMcpStatus() {
123
- try {
124
- const res = await fetch('/api/mcp');
125
- if (!res.ok) return null;
126
- return await res.json();
127
- } catch {
128
- return null; // no server means no button state, not an error to shout about
129
- }
130
- }
131
-
128
+ try {
129
+ const res = await fetch('/api/mcp');
130
+ if (!res.ok)
131
+ return null;
132
+ return await res.json();
133
+ }
134
+ catch {
135
+ return null; // no server means no button state, not an error to shout about
136
+ }
137
+ }
132
138
  export function startMcpServer() {
133
- return postJSON('/api/mcp/start', {});
139
+ return postJSON('/api/mcp/start', {});
134
140
  }
135
-
136
141
  export function stopMcpServer() {
137
- return postJSON('/api/mcp/stop', {});
142
+ return postJSON('/api/mcp/stop', {});
138
143
  }
139
-
140
144
  // The command an agent harness is configured with. Kept separate from the status
141
145
  // fetch because it never changes, so it is read once when the panel opens rather
142
146
  // than on every poll.
143
147
  export async function fetchMcpCommand() {
144
- try {
145
- const res = await fetch('/api/mcp/command');
146
- if (!res.ok) return null;
147
- return await res.json();
148
- } catch {
149
- return null;
150
- }
151
- }
152
-
148
+ try {
149
+ const res = await fetch('/api/mcp/command');
150
+ if (!res.ok)
151
+ return null;
152
+ return await res.json();
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
153
158
  // Streams an OpenAI-compatible chat completion through the local proxy.
154
159
  // Yields text deltas as they arrive; throws with the provider's message on
155
160
  // a non-200 from upstream.
156
- export async function* streamExplain({ baseUrl, apiKey, model, messages, maxTokens = 1200, providerOptions = {} }) {
157
- const res = await fetch('/api/explain', {
158
- method: 'POST',
159
- headers: { 'content-type': 'application/json' },
160
- body: JSON.stringify({ baseUrl, apiKey, model, messages, stream: true, max_tokens: maxTokens, ...providerOptions }),
161
- });
162
-
163
- if (!res.ok) {
164
- let detail = '';
165
- try {
166
- const data = await res.json();
167
- detail = data.detail || data.error || '';
168
- } catch {
169
- /* keep the generic line */
170
- }
171
- throw new Error(detail || `The provider said ${res.status}.`);
172
- }
173
-
174
- const reader = res.body.getReader();
175
- const decoder = new TextDecoder();
176
- let buffer = '';
177
- while (true) {
178
- const { done, value } = await reader.read();
179
- if (done) break;
180
- buffer += decoder.decode(value, { stream: true });
181
- const frames = buffer.split('\n\n');
182
- buffer = frames.pop();
183
- for (const frame of frames) {
184
- for (const line of frame.split('\n')) {
185
- if (!line.startsWith('data:')) continue;
186
- const payload = line.slice(5).trim();
187
- if (payload === '[DONE]') return;
161
+ export async function* streamExplain({ baseUrl, apiKey, model, messages, maxTokens = 1200, providerOptions = {}, signal = undefined }) {
162
+ const res = await fetch('/api/explain', {
163
+ signal,
164
+ method: 'POST',
165
+ headers: { 'content-type': 'application/json' },
166
+ body: JSON.stringify({ baseUrl, apiKey, model, messages, stream: true, max_tokens: maxTokens, ...providerOptions }),
167
+ });
168
+ if (!res.ok) {
169
+ let detail = '';
188
170
  try {
189
- const json = JSON.parse(payload);
190
- const delta = json.choices?.[0]?.delta?.content;
191
- if (delta) yield delta;
192
- } catch {
193
- /* a partial JSON frame — the next chunk completes it */
171
+ const data = await res.json();
172
+ detail = data.detail || data.error || '';
173
+ }
174
+ catch {
175
+ /* keep the generic line */
176
+ }
177
+ throw new Error(detail || `The provider said ${res.status}.`);
178
+ }
179
+ const reader = res.body.getReader();
180
+ const decoder = new TextDecoder();
181
+ let buffer = '';
182
+ while (true) {
183
+ const { done, value } = await reader.read();
184
+ if (done)
185
+ break;
186
+ buffer += decoder.decode(value, { stream: true });
187
+ const frames = buffer.split('\n\n');
188
+ buffer = frames.pop();
189
+ for (const frame of frames) {
190
+ for (const line of frame.split('\n')) {
191
+ if (!line.startsWith('data:'))
192
+ continue;
193
+ const payload = line.slice(5).trim();
194
+ if (payload === '[DONE]')
195
+ return;
196
+ try {
197
+ const json = JSON.parse(payload);
198
+ const delta = json.choices?.[0]?.delta?.content;
199
+ if (delta)
200
+ yield delta;
201
+ }
202
+ catch {
203
+ /* a partial JSON frame — the next chunk completes it */
204
+ }
205
+ }
194
206
  }
195
- }
196
207
  }
197
- }
198
208
  }
199
-
200
209
  // The Server drawer's three round-trips. The read is a GET that comes back
201
210
  // with the secret masked; writes go through PUT with only the changed keys;
202
211
  // rotation is a POST because it mints a new key on the server — the one and
203
212
  // only time a key ever crosses the wire in the clear.
204
213
  export async function fetchServerSettings() {
205
- const res = await fetch('/api/settings');
206
- const data = await res.json().catch(() => null);
207
- if (!res.ok) throw new Error(data?.error || `The server said ${res.status}.`);
208
- return data;
214
+ const res = await fetch('/api/settings');
215
+ const data = await res.json().catch(() => null);
216
+ if (!res.ok)
217
+ throw new Error(data?.error || `The server said ${res.status}.`);
218
+ return data;
209
219
  }
210
-
211
220
  export async function updateServerSettings(patch) {
212
- const res = await fetch('/api/settings', {
213
- method: 'PUT',
214
- headers: { 'content-type': 'application/json' },
215
- body: JSON.stringify(patch),
216
- });
217
- const data = await res.json().catch(() => null);
218
- if (!res.ok) throw new Error(data?.error || `The server said ${res.status}.`);
219
- return data;
220
- }
221
-
221
+ const res = await fetch('/api/settings', {
222
+ method: 'PUT',
223
+ headers: { 'content-type': 'application/json' },
224
+ body: JSON.stringify(patch),
225
+ });
226
+ const data = await res.json().catch(() => null);
227
+ if (!res.ok)
228
+ throw new Error(data?.error || `The server said ${res.status}.`);
229
+ return data;
230
+ }
222
231
  export function rotateServerAccessKey() {
223
- return postJSON('/api/settings/access-key', {});
232
+ return postJSON('/api/settings/access-key', {});
224
233
  }
225
-
226
234
  export function logoutRemoteSession() {
227
- return postJSON('/api/auth/logout', {});
235
+ return postJSON('/api/auth/logout', {});
228
236
  }
237
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/public/js/api.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ScanRequest } from '../../shared/contracts.js';\n// Server round-trips. Thin and honest: JSON in, JSON (or an SSE stream) out,\n// server error messages surfaced untouched.\n\n// Browser access is an HttpOnly session cookie set by the themed self-hosted\n// login page. Same-origin fetches include it automatically, and JavaScript never\n// reads or stores the access key. API clients can still use `Authorization:\n// Bearer …`; local mode needs no credential at all.\n\n// 0.3.0 briefly stored a raw self-hosted key here. Remove that legacy value on\n// first load so upgrading also removes the old secret rather than merely ignoring it.\ntry { localStorage.removeItem('onboarder.accessKey'); } catch { /* storage may be unavailable */ }\n\nasync function postJSON(url: string, body: unknown, options: { signal?: AbortSignal } = {}) {\n const res = await fetch(url, {\n method: 'POST',\n signal: options.signal,\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n let data = null;\n try {\n data = await res.json();\n } catch {\n /* error path handled below with a generic message */\n }\n if (!res.ok) {\n throw new Error(data?.error || `The server said ${res.status}.`);\n }\n return data;\n}\n\nexport function scanOnServer(payload: ScanRequest, options: { signal?: AbortSignal } = {}) {\n return postJSON('/api/scan', payload, options);\n}\n\nexport async function cleanupClone(cloneId) {\n try {\n await fetch('/api/scan/' + encodeURIComponent(cloneId), { method: 'DELETE' });\n } catch {\n /* best-effort: the temp dir expires on its own eventually */\n }\n}\n\nexport async function fetchFileText(scanId, path) {\n const res = await fetch('/api/file?scan=' + encodeURIComponent(scanId) + '&path=' + encodeURIComponent(path));\n if (!res.ok) throw new Error('Could not read that file from the server.');\n return res.text();\n}\n\n// Which deep analyzers this machine can run, and how. Server-side scans only —\n// a browser-picked folder has no scan id and no server-visible root to point a\n// tool at, and this returns that honestly instead of pretending.\nexport async function fetchToolsStatus() {\n try {\n const res = await fetch('/api/tools');\n if (!res.ok) return null;\n const data = await res.json();\n return data && data.tools ? data.tools : null;\n } catch {\n return null; // an unreachable server is just \"no deep analysis here\"\n }\n}\n\n// Run the available analyzers against a live scan. `kinds`/`tools` narrow which\n// engines run; `options` carries the per-engine GUI settings, validated against\n// the registry schema on the server. The report normalizes every finding into\n// the shape the security view already draws, plus a per-engine pass list so\n// the UI can say which tool answered and which are missing.\nexport function runAnalysisTools(scanId, options: Record<string, any> = {}) {\n return postJSON('/api/tools/run', {\n scanId,\n kinds: options.kinds || undefined,\n tools: options.tools || undefined,\n options: options.options || undefined,\n });\n}\n\n// Install a missing engine, streaming progress events. The server emits SSE\n// frames shaped like the explain stream, minus the OpenAI envelope:\n// { type: 'log', line } / { type: 'plan', label } / { type: 'done', ok, … }\n// `onEvent` gets each one as it arrives; the promise resolves with the final\n// `done` event (or throws if the request itself failed).\nexport async function streamToolInstall(tool, onEvent) {\n const emit = typeof onEvent === 'function' ? onEvent : (..._args: unknown[]) => {};\n const res = await fetch('/api/tools/install', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ tool }),\n });\n if (!res.ok || !res.body) {\n let detail = '';\n try { detail = (await res.json()).error || ''; } catch { /* generic below */ }\n throw new Error(detail || `The server said ${res.status}.`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let done = null;\n while (true) {\n const { done: ended, value } = await reader.read();\n if (ended) break;\n buffer += decoder.decode(value, { stream: true });\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop();\n for (const frame of frames) {\n for (const line of frame.split('\\n')) {\n if (!line.startsWith('data:')) continue;\n try {\n const event = JSON.parse(line.slice(5).trim());\n emit(event);\n if (event.type === 'done') done = event;\n } catch { /* a partial frame — the next chunk completes it */ }\n }\n }\n }\n return done || { type: 'done', ok: false, error: 'The install stream ended without a verdict.' };\n}\n\n// The MCP button's three round-trips. The status one is a plain GET like\n// `/api/tools`; start and stop are POSTs because each one changes a process on\n// this machine, which is exactly the side effect `postJSON` is here for.\nexport async function fetchMcpStatus() {\n try {\n const res = await fetch('/api/mcp');\n if (!res.ok) return null;\n return await res.json();\n } catch {\n return null; // no server means no button state, not an error to shout about\n }\n}\n\nexport function startMcpServer() {\n return postJSON('/api/mcp/start', {});\n}\n\nexport function stopMcpServer() {\n return postJSON('/api/mcp/stop', {});\n}\n\n// The command an agent harness is configured with. Kept separate from the status\n// fetch because it never changes, so it is read once when the panel opens rather\n// than on every poll.\nexport async function fetchMcpCommand() {\n try {\n const res = await fetch('/api/mcp/command');\n if (!res.ok) return null;\n return await res.json();\n } catch {\n return null;\n }\n}\n\n// Streams an OpenAI-compatible chat completion through the local proxy.\n// Yields text deltas as they arrive; throws with the provider's message on\n// a non-200 from upstream.\nexport async function* streamExplain({ baseUrl, apiKey, model, messages, maxTokens = 1200, providerOptions = {}, signal = undefined as AbortSignal | undefined }) {\n const res = await fetch('/api/explain', {\n signal,\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ baseUrl, apiKey, model, messages, stream: true, max_tokens: maxTokens, ...providerOptions }),\n });\n\n if (!res.ok) {\n let detail = '';\n try {\n const data = await res.json();\n detail = data.detail || data.error || '';\n } catch {\n /* keep the generic line */\n }\n throw new Error(detail || `The provider said ${res.status}.`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop();\n for (const frame of frames) {\n for (const line of frame.split('\\n')) {\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (payload === '[DONE]') return;\n try {\n const json = JSON.parse(payload);\n const delta = json.choices?.[0]?.delta?.content;\n if (delta) yield delta;\n } catch {\n /* a partial JSON frame — the next chunk completes it */\n }\n }\n }\n }\n}\n\n// The Server drawer's three round-trips. The read is a GET that comes back\n// with the secret masked; writes go through PUT with only the changed keys;\n// rotation is a POST because it mints a new key on the server — the one and\n// only time a key ever crosses the wire in the clear.\nexport async function fetchServerSettings() {\n const res = await fetch('/api/settings');\n const data = await res.json().catch(() => null);\n if (!res.ok) throw new Error(data?.error || `The server said ${res.status}.`);\n return data;\n}\n\nexport async function updateServerSettings(patch) {\n const res = await fetch('/api/settings', {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n });\n const data = await res.json().catch(() => null);\n if (!res.ok) throw new Error(data?.error || `The server said ${res.status}.`);\n return data;\n}\n\nexport function rotateServerAccessKey() {\n return postJSON('/api/settings/access-key', {});\n}\n\nexport function logoutRemoteSession() {\n return postJSON('/api/auth/logout', {});\n}\n"]}
@@ -0,0 +1,6 @@
1
+ export declare function initAtlas(options: any): void;
2
+ export declare function renderAtlasList(): void;
3
+ export declare function openCardDiagram(): {
4
+ source: string;
5
+ nodes: {};
6
+ };
@@ -9,90 +9,82 @@
9
9
  //
10
10
  // Deciding what is in the list and drawing one card are both pure, and live in
11
11
  // shared/diagram/atlas.js with tests. What is left here is the DOM.
12
-
13
12
  import { atlasSpecs, atlasDiagram, filterAtlasItems } from '/shared/diagram/atlas.js';
14
13
  import { escapeHtml } from './html.js';
15
14
  import { state, focusFile, focusFolder, clearFocus } from './state.js';
16
-
17
- let host = null; // #canvasContent — the pannable layer inside the canvas
18
- let canvas = null; // #canvas — the viewport, which is what fixes the list's size
15
+ let host = null; // #canvasContent — the pannable layer inside the canvas
16
+ let canvas = null; // #canvas — the viewport, which is what fixes the list's size
19
17
  let hooks = {
20
- onSyncInspector: () => {},
21
- onRender: () => {},
22
- onHome: () => {},
18
+ onSyncInspector: (..._args) => { },
19
+ onRender: (..._args) => { },
20
+ onHome: (..._args) => { },
23
21
  };
24
-
25
22
  export function initAtlas(options) {
26
- host = options.host;
27
- canvas = options.canvas;
28
- hooks = { ...hooks, ...options };
23
+ host = options.host;
24
+ canvas = options.canvas;
25
+ hooks = { ...hooks, ...options };
29
26
  }
30
-
31
27
  // Built once per repo and kept: the catalogue is a function of the scan, and the
32
28
  // scan does not change while it is loaded. `unloadRepo` resets the flag.
33
29
  function specs() {
34
- if (!state.atlas.built) {
35
- const { scan, facts, manifest, patterns } = state;
36
- state.atlas = { built: true, items: atlasSpecs(scan, facts, manifest, patterns) };
37
- }
38
- return state.atlas.items;
30
+ if (!state.atlas.built) {
31
+ const { scan, facts, manifest, patterns } = state;
32
+ state.atlas = { built: true, items: atlasSpecs(scan, facts, manifest, patterns) };
33
+ }
34
+ return state.atlas.items;
39
35
  }
40
-
41
36
  export function renderAtlasList() {
42
- const items = filterAtlasItems(specs(), state.filters);
43
- host.classList.add('atlas-mode');
44
- hooks.onHome(); // the list is a document — never inherit a diagram's zoom
45
-
46
- const list = document.createElement('div');
47
- list.className = 'atlas-list';
48
- // Exact viewport fit, because the list scrolls itself rather than being panned.
49
- list.style.width = canvas.clientWidth + 'px';
50
- list.style.height = canvas.clientHeight + 'px';
51
-
52
- const head = document.createElement('p');
53
- head.className = 'atlas-head';
54
- head.textContent = `${items.length} maps, drawn from the import graph — no AI involved. `
55
- + `Open one; if it doesn't satisfy you, the AI draft button redraws it.`;
56
- list.appendChild(head);
57
-
58
- const grid = document.createElement('div');
59
- grid.className = 'atlas-grid';
60
- for (const it of items) {
61
- const card = document.createElement('div');
62
- card.className = 'atlas-card';
63
- card.innerHTML = `
37
+ const items = filterAtlasItems(specs(), state.filters);
38
+ host.classList.add('atlas-mode');
39
+ hooks.onHome(); // the list is a document — never inherit a diagram's zoom
40
+ const list = document.createElement('div');
41
+ list.className = 'atlas-list';
42
+ // Exact viewport fit, because the list scrolls itself rather than being panned.
43
+ list.style.width = canvas.clientWidth + 'px';
44
+ list.style.height = canvas.clientHeight + 'px';
45
+ const head = document.createElement('p');
46
+ head.className = 'atlas-head';
47
+ head.textContent = `${items.length} maps, drawn from the import graph — no AI involved. `
48
+ + `Open one; if it doesn't satisfy you, the AI draft button redraws it.`;
49
+ list.appendChild(head);
50
+ const grid = document.createElement('div');
51
+ grid.className = 'atlas-grid';
52
+ for (const it of items) {
53
+ const card = document.createElement('div');
54
+ card.className = 'atlas-card';
55
+ card.innerHTML = `
64
56
  <div class="atlas-card-top">
65
57
  <span class="atlas-kind is-${escapeHtml(it.kind)}">${escapeHtml(it.kind)}</span>
66
58
  <span class="atlas-title" title="${escapeHtml(it.path || it.title)}">${escapeHtml(it.title)}</span>
67
59
  </div>
68
60
  <div class="atlas-sub">${escapeHtml(it.sub)}</div>
69
61
  `;
70
- card.addEventListener('click', () => openAtlasItem(it));
71
- grid.appendChild(card);
72
- }
73
- list.appendChild(grid);
74
-
75
- host.innerHTML = '';
76
- host.appendChild(list);
62
+ card.addEventListener('click', () => openAtlasItem(it));
63
+ grid.appendChild(card);
64
+ }
65
+ list.appendChild(grid);
66
+ host.innerHTML = '';
67
+ host.appendChild(list);
77
68
  }
78
-
79
69
  // Opening a card points the rest of the app at the same subject, so the sidebar,
80
70
  // the inspector and the breadcrumbs agree with the picture on the canvas.
81
71
  function openAtlasItem(item) {
82
- state.atlasOpen = item;
83
- if (item.kind === 'file') focusFile(item.path);
84
- else if (item.kind === 'folder') focusFolder(item.path);
85
- else clearFocus();
86
-
87
- hooks.onSyncInspector();
88
- hooks.onRender();
72
+ state.atlasOpen = item;
73
+ if (item.kind === 'file')
74
+ focusFile(item.path);
75
+ else if (item.kind === 'folder')
76
+ focusFolder(item.path);
77
+ else
78
+ clearFocus();
79
+ hooks.onSyncInspector();
80
+ hooks.onRender();
89
81
  }
90
-
91
82
  // The diagram for whichever card is open, drawn fresh on each canvas render.
92
83
  // Fresh matters: a Mermaid source carries its own palette, so a cached one keeps
93
84
  // the theme it was born under. The old atlas stored the source on the item and
94
85
  // an opened card stayed light after switching to dark.
95
86
  export function openCardDiagram() {
96
- const { scan, facts, manifest, patterns } = state;
97
- return atlasDiagram(state.atlasOpen, { scan, facts, manifest, patterns });
87
+ const { scan, facts, manifest, patterns } = state;
88
+ return atlasDiagram(state.atlasOpen, { scan, facts, manifest, patterns });
98
89
  }
90
+ //# sourceMappingURL=atlas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atlas.js","sourceRoot":"","sources":["../../src/public/js/atlas.ts"],"names":[],"mappings":"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","sourcesContent":["// The atlas view: a scrollable catalogue of every map, and the card that opens.\n//\n// Two things make this view unlike the others. It is a document rather than a\n// diagram, so it opts out of the canvas's pan and zoom (`atlas-mode`, which\n// diagramPane.js checks before it swallows a drag or a wheel). And a card, once\n// opened, *becomes* another view: the canvas draws the card's diagram and the AI\n// draft button borrows that view's fact sheet. Which is why `atlasOpen` holds\n// the whole item and not just an index.\n//\n// Deciding what is in the list and drawing one card are both pure, and live in\n// shared/diagram/atlas.js with tests. What is left here is the DOM.\n\nimport { atlasSpecs, atlasDiagram, filterAtlasItems } from '/shared/diagram/atlas.js';\nimport { escapeHtml } from './html.js';\nimport { state, focusFile, focusFolder, clearFocus } from './state.js';\n\nlet host = null; // #canvasContent — the pannable layer inside the canvas\nlet canvas = null; // #canvas — the viewport, which is what fixes the list's size\nlet hooks = {\n onSyncInspector: (..._args: unknown[]) => {},\n onRender: (..._args: unknown[]) => {},\n onHome: (..._args: unknown[]) => {},\n};\n\nexport function initAtlas(options) {\n host = options.host;\n canvas = options.canvas;\n hooks = { ...hooks, ...options };\n}\n\n// Built once per repo and kept: the catalogue is a function of the scan, and the\n// scan does not change while it is loaded. `unloadRepo` resets the flag.\nfunction specs() {\n if (!state.atlas.built) {\n const { scan, facts, manifest, patterns } = state;\n state.atlas = { built: true, items: atlasSpecs(scan, facts, manifest, patterns) };\n }\n return state.atlas.items;\n}\n\nexport function renderAtlasList() {\n const items = filterAtlasItems(specs(), state.filters);\n host.classList.add('atlas-mode');\n hooks.onHome(); // the list is a document — never inherit a diagram's zoom\n\n const list = document.createElement('div');\n list.className = 'atlas-list';\n // Exact viewport fit, because the list scrolls itself rather than being panned.\n list.style.width = canvas.clientWidth + 'px';\n list.style.height = canvas.clientHeight + 'px';\n\n const head = document.createElement('p');\n head.className = 'atlas-head';\n head.textContent = `${items.length} maps, drawn from the import graph — no AI involved. `\n + `Open one; if it doesn't satisfy you, the AI draft button redraws it.`;\n list.appendChild(head);\n\n const grid = document.createElement('div');\n grid.className = 'atlas-grid';\n for (const it of items) {\n const card = document.createElement('div');\n card.className = 'atlas-card';\n card.innerHTML = `\n <div class=\"atlas-card-top\">\n <span class=\"atlas-kind is-${escapeHtml(it.kind)}\">${escapeHtml(it.kind)}</span>\n <span class=\"atlas-title\" title=\"${escapeHtml(it.path || it.title)}\">${escapeHtml(it.title)}</span>\n </div>\n <div class=\"atlas-sub\">${escapeHtml(it.sub)}</div>\n `;\n card.addEventListener('click', () => openAtlasItem(it));\n grid.appendChild(card);\n }\n list.appendChild(grid);\n\n host.innerHTML = '';\n host.appendChild(list);\n}\n\n// Opening a card points the rest of the app at the same subject, so the sidebar,\n// the inspector and the breadcrumbs agree with the picture on the canvas.\nfunction openAtlasItem(item) {\n state.atlasOpen = item;\n if (item.kind === 'file') focusFile(item.path);\n else if (item.kind === 'folder') focusFolder(item.path);\n else clearFocus();\n\n hooks.onSyncInspector();\n hooks.onRender();\n}\n\n// The diagram for whichever card is open, drawn fresh on each canvas render.\n// Fresh matters: a Mermaid source carries its own palette, so a cached one keeps\n// the theme it was born under. The old atlas stored the source on the item and\n// an opened card stayed light after switching to dark.\nexport function openCardDiagram() {\n const { scan, facts, manifest, patterns } = state;\n return atlasDiagram(state.atlasOpen, { scan, facts, manifest, patterns });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function initBlameView(container: any): (blameData: any, options?: Record<string, any>) => void;
2
+ export declare function fetchBlame(scanId: any, path: any): Promise<any>;