@rsktash/beads-ui 0.1.51 → 0.10.3

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 (336) hide show
  1. package/README.md +85 -144
  2. package/bin/bd-web +94 -0
  3. package/dist/assets/index-BBVIMXaM.js +73 -0
  4. package/dist/assets/index-SUXI6Mzt.css +1 -0
  5. package/dist/bd-favicon-16.svg +6 -0
  6. package/dist/bd-favicon-32.svg +6 -0
  7. package/dist/bd-logo-512.svg +6 -0
  8. package/dist/favicon.ico +0 -0
  9. package/dist/icon-180.png +0 -0
  10. package/dist/icon-192.png +0 -0
  11. package/dist/icon-512.png +0 -0
  12. package/dist/index.html +8 -5
  13. package/package.json +39 -29
  14. package/server/auth.js +68 -87
  15. package/server/db.js +91 -134
  16. package/server/dsn.js +130 -0
  17. package/server/index.js +151 -87
  18. package/server/queries.js +247 -0
  19. package/server/routes/auth.js +27 -0
  20. package/server/routes/issues.js +120 -0
  21. package/server/routes/stream.js +111 -0
  22. package/server/types.js +83 -0
  23. package/app/protocol.js +0 -216
  24. package/bin/bd-grep +0 -121
  25. package/bin/bd-ui +0 -19
  26. package/dist/assets/abap-DsBKuouk.js +0 -1
  27. package/dist/assets/actionscript-3-D_z4Izcz.js +0 -1
  28. package/dist/assets/ada-727ZlQH0.js +0 -1
  29. package/dist/assets/andromeeda-C3khCPGq.js +0 -1
  30. package/dist/assets/angular-html-LfdN0zeE.js +0 -1
  31. package/dist/assets/angular-ts-CKsD7JZE.js +0 -1
  32. package/dist/assets/apache-Dn00JSTd.js +0 -1
  33. package/dist/assets/apex-COJ4H7py.js +0 -1
  34. package/dist/assets/apl-BBq3IX1j.js +0 -1
  35. package/dist/assets/applescript-Bu5BbsvL.js +0 -1
  36. package/dist/assets/ara-7O62HKoU.js +0 -1
  37. package/dist/assets/asciidoc-BPT9niGB.js +0 -1
  38. package/dist/assets/asm-Dhn9LcZ4.js +0 -1
  39. package/dist/assets/astro-CqkE3fuf.js +0 -1
  40. package/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
  41. package/dist/assets/awk-eg146-Ew.js +0 -1
  42. package/dist/assets/ayu-dark-Cv9koXgw.js +0 -1
  43. package/dist/assets/ballerina-Du268qiB.js +0 -1
  44. package/dist/assets/bat-fje9CFhw.js +0 -1
  45. package/dist/assets/beancount-BwXTMy5W.js +0 -1
  46. package/dist/assets/berry-3xVqZejG.js +0 -1
  47. package/dist/assets/bibtex-xW4inM5L.js +0 -1
  48. package/dist/assets/bicep-DHo0CJ0O.js +0 -1
  49. package/dist/assets/blade-a8OxSdnT.js +0 -1
  50. package/dist/assets/bsl-Dgyn0ogV.js +0 -1
  51. package/dist/assets/c-C3t2pwGQ.js +0 -1
  52. package/dist/assets/cadence-DNquZEk8.js +0 -1
  53. package/dist/assets/cairo--RitsXJZ.js +0 -1
  54. package/dist/assets/catppuccin-frappe-CD_QflpE.js +0 -1
  55. package/dist/assets/catppuccin-latte-DRW-0cLl.js +0 -1
  56. package/dist/assets/catppuccin-macchiato-C-_shW-Y.js +0 -1
  57. package/dist/assets/catppuccin-mocha-LGGdnPYs.js +0 -1
  58. package/dist/assets/clarity-BHOwM8T6.js +0 -1
  59. package/dist/assets/clojure-DxSadP1t.js +0 -1
  60. package/dist/assets/cmake-DbXoA79R.js +0 -1
  61. package/dist/assets/cobol-PTqiYgYu.js +0 -1
  62. package/dist/assets/codeowners-Bp6g37R7.js +0 -1
  63. package/dist/assets/codeql-sacFqUAJ.js +0 -1
  64. package/dist/assets/coffee-dyiR41kL.js +0 -1
  65. package/dist/assets/common-lisp-C7gG9l05.js +0 -1
  66. package/dist/assets/coq-Dsg_Bt_b.js +0 -1
  67. package/dist/assets/cpp-BksuvNSY.js +0 -1
  68. package/dist/assets/crystal-DtDmRg-F.js +0 -1
  69. package/dist/assets/csharp-D9R-vmeu.js +0 -1
  70. package/dist/assets/css-BPhBrDlE.js +0 -1
  71. package/dist/assets/csv-B0qRVHPH.js +0 -1
  72. package/dist/assets/cue-DtFQj3wx.js +0 -1
  73. package/dist/assets/cypher-m2LEI-9-.js +0 -1
  74. package/dist/assets/d-BoXegm-a.js +0 -1
  75. package/dist/assets/dark-plus-C3mMm8J8.js +0 -1
  76. package/dist/assets/dart-B9wLZaAG.js +0 -1
  77. package/dist/assets/dax-ClGRhx96.js +0 -1
  78. package/dist/assets/desktop-DEIpsLCJ.js +0 -1
  79. package/dist/assets/diff-BgYniUM_.js +0 -1
  80. package/dist/assets/docker-COcR7UxN.js +0 -1
  81. package/dist/assets/dotenv-BjQB5zDj.js +0 -1
  82. package/dist/assets/dracula-BzJJZx-M.js +0 -1
  83. package/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
  84. package/dist/assets/dream-maker-C-nORZOA.js +0 -1
  85. package/dist/assets/edge-D5gP-w-T.js +0 -1
  86. package/dist/assets/elixir-CLiX3zqd.js +0 -1
  87. package/dist/assets/elm-CmHSxxaM.js +0 -1
  88. package/dist/assets/emacs-lisp-BX77sIaO.js +0 -1
  89. package/dist/assets/erb-BYTLMnw6.js +0 -1
  90. package/dist/assets/erlang-B-DoSBHF.js +0 -1
  91. package/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
  92. package/dist/assets/everforest-light-C8M2exoo.js +0 -1
  93. package/dist/assets/fennel-bCA53EVm.js +0 -1
  94. package/dist/assets/fish-w-ucz2PV.js +0 -1
  95. package/dist/assets/fluent-Dayu4EKP.js +0 -1
  96. package/dist/assets/fortran-fixed-form-TqA4NnZg.js +0 -1
  97. package/dist/assets/fortran-free-form-DKXYxT9g.js +0 -1
  98. package/dist/assets/fsharp-XplgxFYe.js +0 -1
  99. package/dist/assets/gdresource-BHYsBjWJ.js +0 -1
  100. package/dist/assets/gdscript-DfxzS6Rs.js +0 -1
  101. package/dist/assets/gdshader-SKMF96pI.js +0 -1
  102. package/dist/assets/genie-ajMbGru0.js +0 -1
  103. package/dist/assets/gherkin--30QC5Em.js +0 -1
  104. package/dist/assets/git-commit-i4q6IMui.js +0 -1
  105. package/dist/assets/git-rebase-B-v9cOL2.js +0 -1
  106. package/dist/assets/github-dark-DHJKELXO.js +0 -1
  107. package/dist/assets/github-dark-default-Cuk6v7N8.js +0 -1
  108. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
  109. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
  110. package/dist/assets/github-light-DAi9KRSo.js +0 -1
  111. package/dist/assets/github-light-default-D7oLnXFd.js +0 -1
  112. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
  113. package/dist/assets/gleam-B430Bg39.js +0 -1
  114. package/dist/assets/glimmer-js-D-cwc0-E.js +0 -1
  115. package/dist/assets/glimmer-ts-pgjy16dm.js +0 -1
  116. package/dist/assets/glsl-DBO2IWDn.js +0 -1
  117. package/dist/assets/gnuplot-CM8KxXT1.js +0 -1
  118. package/dist/assets/go-B1SYOhNW.js +0 -1
  119. package/dist/assets/graphql-cDcHW_If.js +0 -1
  120. package/dist/assets/groovy-DkBy-JyN.js +0 -1
  121. package/dist/assets/hack-D1yCygmZ.js +0 -1
  122. package/dist/assets/haml-B2EZWmdv.js +0 -1
  123. package/dist/assets/handlebars-BQGss363.js +0 -1
  124. package/dist/assets/haskell-BILxekzW.js +0 -1
  125. package/dist/assets/haxe-C5wWYbrZ.js +0 -1
  126. package/dist/assets/hcl-HzYwdGDm.js +0 -1
  127. package/dist/assets/hjson-T-Tgc4AT.js +0 -1
  128. package/dist/assets/hlsl-ifBTmRxC.js +0 -1
  129. package/dist/assets/houston-DnULxvSX.js +0 -1
  130. package/dist/assets/html-C2L_23MC.js +0 -1
  131. package/dist/assets/html-derivative-CSfWNPLT.js +0 -1
  132. package/dist/assets/http-FRrOvY1W.js +0 -1
  133. package/dist/assets/hxml-TIA70rKU.js +0 -1
  134. package/dist/assets/hy-BMj5Y0dO.js +0 -1
  135. package/dist/assets/imba-bv_oIlVt.js +0 -1
  136. package/dist/assets/index-CNDeKQGk.js +0 -125
  137. package/dist/assets/index-oO5WB2l2.css +0 -1
  138. package/dist/assets/ini-BjABl1g7.js +0 -1
  139. package/dist/assets/java-xI-RfyKK.js +0 -1
  140. package/dist/assets/javascript-ySlJ1b_l.js +0 -1
  141. package/dist/assets/jinja-DGy0s7-h.js +0 -1
  142. package/dist/assets/jison-BqZprYcd.js +0 -1
  143. package/dist/assets/json-BQoSv7ci.js +0 -1
  144. package/dist/assets/json5-w8dY5SsB.js +0 -1
  145. package/dist/assets/jsonc-TU54ms6u.js +0 -1
  146. package/dist/assets/jsonl-DREVFZK8.js +0 -1
  147. package/dist/assets/jsonnet-BfivnA6A.js +0 -1
  148. package/dist/assets/jssm-P4WzXJd0.js +0 -1
  149. package/dist/assets/jsx-BAng5TT0.js +0 -1
  150. package/dist/assets/julia-BBuGR-5E.js +0 -1
  151. package/dist/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
  152. package/dist/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
  153. package/dist/assets/kanagawa-wave-DWedfzmr.js +0 -1
  154. package/dist/assets/kotlin-B5lbUyaz.js +0 -1
  155. package/dist/assets/kusto-mebxcVVE.js +0 -1
  156. package/dist/assets/laserwave-DUszq2jm.js +0 -1
  157. package/dist/assets/latex-C-cWTeAZ.js +0 -1
  158. package/dist/assets/lean-XBlWyCtg.js +0 -1
  159. package/dist/assets/less-BfCpw3nA.js +0 -1
  160. package/dist/assets/light-plus-B7mTdjB0.js +0 -1
  161. package/dist/assets/liquid-D3W5UaiH.js +0 -1
  162. package/dist/assets/log-Cc5clBb7.js +0 -1
  163. package/dist/assets/logo-IuBKFhSY.js +0 -1
  164. package/dist/assets/lua-CvWAzNxB.js +0 -1
  165. package/dist/assets/luau-Du5NY7AG.js +0 -1
  166. package/dist/assets/make-Bvotw-X0.js +0 -1
  167. package/dist/assets/markdown-UIAJJxZW.js +0 -1
  168. package/dist/assets/marko-z0MBrx5-.js +0 -1
  169. package/dist/assets/material-theme-D5KoaKCx.js +0 -1
  170. package/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
  171. package/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
  172. package/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
  173. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
  174. package/dist/assets/matlab-D9-PGadD.js +0 -1
  175. package/dist/assets/mdc-DB_EDNY_.js +0 -1
  176. package/dist/assets/mdx-sdHcTMYB.js +0 -1
  177. package/dist/assets/mermaid-Ci6OQyBP.js +0 -1
  178. package/dist/assets/min-dark-CafNBF8u.js +0 -1
  179. package/dist/assets/min-light-CTRr51gU.js +0 -1
  180. package/dist/assets/mipsasm-BC5c_5Pe.js +0 -1
  181. package/dist/assets/mojo-Tz6hzZYG.js +0 -1
  182. package/dist/assets/monokai-D4h5O-jR.js +0 -1
  183. package/dist/assets/move-DB_GagMm.js +0 -1
  184. package/dist/assets/narrat-DLbgOhZU.js +0 -1
  185. package/dist/assets/nextflow-B0XVJmRM.js +0 -1
  186. package/dist/assets/nginx-D_VnBJ67.js +0 -1
  187. package/dist/assets/night-owl-C39BiMTA.js +0 -1
  188. package/dist/assets/nim-ZlGxZxc3.js +0 -1
  189. package/dist/assets/nix-shcSOmrb.js +0 -1
  190. package/dist/assets/nord-Ddv68eIx.js +0 -1
  191. package/dist/assets/nushell-D4Tzg5kh.js +0 -1
  192. package/dist/assets/objective-c-Deuh7S70.js +0 -1
  193. package/dist/assets/objective-cpp-BUEGK8hf.js +0 -1
  194. package/dist/assets/ocaml-BNioltXt.js +0 -1
  195. package/dist/assets/one-dark-pro-GBQ2dnAY.js +0 -1
  196. package/dist/assets/one-light-PoHY5YXO.js +0 -1
  197. package/dist/assets/pascal-JqZropPD.js +0 -1
  198. package/dist/assets/perl-CHQXSrWU.js +0 -1
  199. package/dist/assets/php-B5ebYQev.js +0 -1
  200. package/dist/assets/plastic-3e1v2bzS.js +0 -1
  201. package/dist/assets/plsql-LKU2TuZ1.js +0 -1
  202. package/dist/assets/po-BFLt1xDp.js +0 -1
  203. package/dist/assets/poimandres-CS3Unz2-.js +0 -1
  204. package/dist/assets/polar-DKykz6zU.js +0 -1
  205. package/dist/assets/postcss-B3ZDOciz.js +0 -1
  206. package/dist/assets/powerquery-CSHBycmS.js +0 -1
  207. package/dist/assets/powershell-BIEUsx6d.js +0 -1
  208. package/dist/assets/prisma-B48N-Iqd.js +0 -1
  209. package/dist/assets/prolog-BY-TUvya.js +0 -1
  210. package/dist/assets/proto-zocC4JxJ.js +0 -1
  211. package/dist/assets/pug-CM9l7STV.js +0 -1
  212. package/dist/assets/puppet-Cza_XSSt.js +0 -1
  213. package/dist/assets/purescript-Bg-kzb6g.js +0 -1
  214. package/dist/assets/python-DhUJRlN_.js +0 -1
  215. package/dist/assets/qml-D8XfuvdV.js +0 -1
  216. package/dist/assets/qmldir-C8lEn-DE.js +0 -1
  217. package/dist/assets/qss-DhMKtDLN.js +0 -1
  218. package/dist/assets/r-CwjWoCRV.js +0 -1
  219. package/dist/assets/racket-CzouJOBO.js +0 -1
  220. package/dist/assets/raku-B1bQXN8T.js +0 -1
  221. package/dist/assets/razor-CNLDkMZG.js +0 -1
  222. package/dist/assets/red-bN70gL4F.js +0 -1
  223. package/dist/assets/reg-5LuOXUq_.js +0 -1
  224. package/dist/assets/regexp-DWJ3fJO_.js +0 -1
  225. package/dist/assets/rel-DJlmqQ1C.js +0 -1
  226. package/dist/assets/riscv-QhoSD0DR.js +0 -1
  227. package/dist/assets/rose-pine-CmCqftbK.js +0 -1
  228. package/dist/assets/rose-pine-dawn-Ds-gbosJ.js +0 -1
  229. package/dist/assets/rose-pine-moon-CjDtw9vr.js +0 -1
  230. package/dist/assets/rst-4NLicBqY.js +0 -1
  231. package/dist/assets/ruby-DeZ3UC14.js +0 -1
  232. package/dist/assets/rust-Be6lgOlo.js +0 -1
  233. package/dist/assets/sas-BmTFh92c.js +0 -1
  234. package/dist/assets/sass-BJ4Li9vH.js +0 -1
  235. package/dist/assets/scala-DQVVAn-B.js +0 -1
  236. package/dist/assets/scheme-BJGe-b2p.js +0 -1
  237. package/dist/assets/scss-C31hgJw-.js +0 -1
  238. package/dist/assets/sdbl-BLhTXw86.js +0 -1
  239. package/dist/assets/shaderlab-B7qAK45m.js +0 -1
  240. package/dist/assets/shellscript-atvbtKCR.js +0 -1
  241. package/dist/assets/shellsession-C_rIy8kc.js +0 -1
  242. package/dist/assets/slack-dark-BthQWCQV.js +0 -1
  243. package/dist/assets/slack-ochin-DqwNpetd.js +0 -1
  244. package/dist/assets/smalltalk-DkLiglaE.js +0 -1
  245. package/dist/assets/snazzy-light-Bw305WKR.js +0 -1
  246. package/dist/assets/solarized-dark-DXbdFlpD.js +0 -1
  247. package/dist/assets/solarized-light-L9t79GZl.js +0 -1
  248. package/dist/assets/solidity-C1w2a3ep.js +0 -1
  249. package/dist/assets/soy-C-lX7w71.js +0 -1
  250. package/dist/assets/sparql-bYkjHRlG.js +0 -1
  251. package/dist/assets/splunk-Cf8iN4DR.js +0 -1
  252. package/dist/assets/sql-COK4E0Yg.js +0 -1
  253. package/dist/assets/ssh-config-BknIz3MU.js +0 -1
  254. package/dist/assets/stata-DorPZHa4.js +0 -1
  255. package/dist/assets/stylus-BeQkCIfX.js +0 -1
  256. package/dist/assets/svelte-MSaWC3Je.js +0 -1
  257. package/dist/assets/swift-BSxZ-RaX.js +0 -1
  258. package/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
  259. package/dist/assets/system-verilog-C7L56vO4.js +0 -1
  260. package/dist/assets/systemd-CUnW07Te.js +0 -1
  261. package/dist/assets/talonscript-C1XDQQGZ.js +0 -1
  262. package/dist/assets/tasl-CQjiPCtT.js +0 -1
  263. package/dist/assets/tcl-DQ1-QYvQ.js +0 -1
  264. package/dist/assets/templ-dwX3ZSMB.js +0 -1
  265. package/dist/assets/terraform-BbSNqyBO.js +0 -1
  266. package/dist/assets/tex-rYs2v40G.js +0 -1
  267. package/dist/assets/tokyo-night-DBQeEorK.js +0 -1
  268. package/dist/assets/toml-CB2ApiWb.js +0 -1
  269. package/dist/assets/ts-tags-CipyTH0X.js +0 -1
  270. package/dist/assets/tsv-B_m7g4N7.js +0 -1
  271. package/dist/assets/tsx-B6W0miNI.js +0 -1
  272. package/dist/assets/turtle-BMR_PYu6.js +0 -1
  273. package/dist/assets/twig-NC5TFiHP.js +0 -1
  274. package/dist/assets/typescript-Dj6nwHGl.js +0 -1
  275. package/dist/assets/typespec-BpWG_bgh.js +0 -1
  276. package/dist/assets/typst-BVUVsWT6.js +0 -1
  277. package/dist/assets/v-CAQ2eGtk.js +0 -1
  278. package/dist/assets/vala-BFOHcciG.js +0 -1
  279. package/dist/assets/vb-CdO5JTpU.js +0 -1
  280. package/dist/assets/verilog-CJaU5se_.js +0 -1
  281. package/dist/assets/vesper-BEBZ7ncR.js +0 -1
  282. package/dist/assets/vhdl-DYoNaHQp.js +0 -1
  283. package/dist/assets/viml-m4uW47V2.js +0 -1
  284. package/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
  285. package/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
  286. package/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
  287. package/dist/assets/vue-BuYVFjOK.js +0 -1
  288. package/dist/assets/vue-html-xdeiXROB.js +0 -1
  289. package/dist/assets/vyper-nyqBNV6O.js +0 -1
  290. package/dist/assets/wasm-C6j12Q_x.js +0 -1
  291. package/dist/assets/wasm-CG6Dc4jp.js +0 -1
  292. package/dist/assets/wenyan-7A4Fjokl.js +0 -1
  293. package/dist/assets/wgsl-CB0Krxn9.js +0 -1
  294. package/dist/assets/wikitext-DCE3LsBG.js +0 -1
  295. package/dist/assets/wolfram-C3FkfJm5.js +0 -1
  296. package/dist/assets/xml-e3z08dGr.js +0 -1
  297. package/dist/assets/xsl-Dd0NUgwM.js +0 -1
  298. package/dist/assets/yaml-CVw76BM1.js +0 -1
  299. package/dist/assets/zenscript-HnGAYVZD.js +0 -1
  300. package/dist/assets/zig-BVz_zdnA.js +0 -1
  301. package/server/app.js +0 -165
  302. package/server/app.test.js +0 -30
  303. package/server/bd.js +0 -227
  304. package/server/bd.test.js +0 -194
  305. package/server/cli/cli.test.js +0 -207
  306. package/server/cli/commands.integration.test.js +0 -148
  307. package/server/cli/commands.js +0 -285
  308. package/server/cli/commands.unit.test.js +0 -408
  309. package/server/cli/daemon.js +0 -340
  310. package/server/cli/daemon.test.js +0 -31
  311. package/server/cli/index.js +0 -135
  312. package/server/cli/open.js +0 -178
  313. package/server/cli/open.test.js +0 -26
  314. package/server/cli/usage.js +0 -49
  315. package/server/config.js +0 -36
  316. package/server/db.test.js +0 -169
  317. package/server/dolt-pool.js +0 -313
  318. package/server/dolt-queries.js +0 -781
  319. package/server/list-adapters.js +0 -421
  320. package/server/list-adapters.test.js +0 -208
  321. package/server/logging.js +0 -23
  322. package/server/registry-watcher.js +0 -200
  323. package/server/subscriptions.js +0 -299
  324. package/server/subscriptions.test.js +0 -128
  325. package/server/validators.js +0 -124
  326. package/server/watcher.js +0 -139
  327. package/server/watcher.test.js +0 -120
  328. package/server/ws.comments.test.js +0 -262
  329. package/server/ws.delete.test.js +0 -119
  330. package/server/ws.js +0 -1329
  331. package/server/ws.labels.test.js +0 -95
  332. package/server/ws.list-refresh.coalesce.test.js +0 -95
  333. package/server/ws.list-subscriptions.test.js +0 -403
  334. package/server/ws.mutation-window.test.js +0 -147
  335. package/server/ws.mutations.test.js +0 -389
  336. package/server/ws.test.js +0 -52
package/server/bd.test.js DELETED
@@ -1,194 +0,0 @@
1
- import { spawn as spawnMock } from 'node:child_process';
2
- import { EventEmitter } from 'node:events';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { PassThrough } from 'node:stream';
7
- import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
8
- import { getBdBin, getGitUserName, runBd, runBdJson } from './bd.js';
9
-
10
- // Mock child_process.spawn before importing the module under test
11
- vi.mock('node:child_process', () => ({ spawn: vi.fn() }));
12
-
13
- /**
14
- * @param {string} stdoutText
15
- * @param {string} stderrText
16
- * @param {number} code
17
- */
18
- function makeFakeProc(stdoutText, stderrText, code) {
19
- const cp = /** @type {any} */ (new EventEmitter());
20
- const out = new PassThrough();
21
- const err = new PassThrough();
22
- cp.stdout = out;
23
- cp.stderr = err;
24
- // Simulate async emission
25
- setTimeout(() => {
26
- if (stdoutText) {
27
- out.write(stdoutText);
28
- }
29
- out.end();
30
- if (stderrText) {
31
- err.write(stderrText);
32
- }
33
- err.end();
34
- cp.emit('close', code);
35
- }, 0);
36
- return cp;
37
- }
38
-
39
- const mockedSpawn = /** @type {import('vitest').Mock} */ (spawnMock);
40
- /** @type {string[]} */
41
- const temp_dirs = [];
42
-
43
- function make_temp_dir() {
44
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bdui-bd-'));
45
- temp_dirs.push(dir);
46
- return dir;
47
- }
48
-
49
- beforeEach(() => {
50
- mockedSpawn.mockReset();
51
- });
52
-
53
- afterEach(() => {
54
- for (const dir of temp_dirs.splice(0)) {
55
- try {
56
- fs.rmSync(dir, { recursive: true, force: true });
57
- } catch {
58
- // ignore cleanup errors
59
- }
60
- }
61
- });
62
-
63
- describe('getBdBin', () => {
64
- test('returns env BD_BIN when set', () => {
65
- const prev = process.env.BD_BIN;
66
- process.env.BD_BIN = '/custom/bd';
67
- expect(getBdBin()).toBe('/custom/bd');
68
- if (prev) {
69
- process.env.BD_BIN = prev;
70
- } else {
71
- delete process.env.BD_BIN;
72
- }
73
- });
74
- });
75
-
76
- describe('runBd', () => {
77
- test('prepends --sandbox by default', async () => {
78
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
79
- await runBd(['list', '--json']);
80
-
81
- const args = mockedSpawn.mock.calls[0][1];
82
- expect(args[0]).toBe('--sandbox');
83
- expect(args.slice(1)).toEqual(['list', '--json']);
84
- });
85
-
86
- test('does not duplicate --sandbox when caller already provides it', async () => {
87
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
88
- await runBd(['--sandbox', 'list', '--json']);
89
-
90
- const args = mockedSpawn.mock.calls[0][1];
91
- expect(args).toEqual(['--sandbox', 'list', '--json']);
92
- });
93
-
94
- test('allows disabling default sandbox via BDUI_BD_SANDBOX', async () => {
95
- const prev = process.env.BDUI_BD_SANDBOX;
96
- process.env.BDUI_BD_SANDBOX = '0';
97
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
98
-
99
- await runBd(['list', '--json']);
100
-
101
- const args = mockedSpawn.mock.calls[0][1];
102
- expect(args).toEqual(['list', '--json']);
103
-
104
- if (prev === undefined) {
105
- delete process.env.BDUI_BD_SANDBOX;
106
- } else {
107
- process.env.BDUI_BD_SANDBOX = prev;
108
- }
109
- });
110
-
111
- test('returns stdout/stderr and exit code', async () => {
112
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
113
- const res = await runBd(['--version']);
114
- expect(res.code).toBe(0);
115
- expect(res.stdout).toContain('ok');
116
- });
117
-
118
- test('non-zero exit propagates code and stderr', async () => {
119
- mockedSpawn.mockReturnValueOnce(makeFakeProc('', 'boom', 1));
120
- const res = await runBd(['list']);
121
- expect(res.code).toBe(1);
122
- expect(res.stderr).toContain('boom');
123
- });
124
-
125
- test('sets BEADS_DB for workspace-local SQLite db', async () => {
126
- const root = make_temp_dir();
127
- const beads_dir = path.join(root, '.beads');
128
- fs.mkdirSync(beads_dir, { recursive: true });
129
- const workspace_db = path.join(beads_dir, 'ui.db');
130
- fs.writeFileSync(workspace_db, '');
131
-
132
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
133
- await runBd(['list'], { cwd: root, env: {} });
134
-
135
- const options = mockedSpawn.mock.calls[0][2];
136
- expect(options.env.BEADS_DB).toBe(workspace_db);
137
- });
138
-
139
- test('does not force BEADS_DB when workspace has no local SQLite db', async () => {
140
- const root = make_temp_dir();
141
-
142
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
143
- await runBd(['list'], { cwd: root, env: {} });
144
-
145
- const options = mockedSpawn.mock.calls[0][2];
146
- expect(options.env.BEADS_DB).toBeUndefined();
147
- });
148
-
149
- test('preserves explicit BEADS_DB from caller env', async () => {
150
- mockedSpawn.mockReturnValueOnce(makeFakeProc('ok', '', 0));
151
- await runBd(['list'], { env: { BEADS_DB: '/custom/workspace.db' } });
152
-
153
- const options = mockedSpawn.mock.calls[0][2];
154
- expect(options.env.BEADS_DB).toBe('/custom/workspace.db');
155
- });
156
- });
157
-
158
- describe('runBdJson', () => {
159
- test('parses valid JSON output', async () => {
160
- const json = JSON.stringify([{ id: 'UI-1' }]);
161
- mockedSpawn.mockReturnValueOnce(makeFakeProc(json, '', 0));
162
- const res = await runBdJson(['list', '--json']);
163
- expect(res.code).toBe(0);
164
- expect(Array.isArray(res.stdoutJson)).toBe(true);
165
- });
166
-
167
- test('invalid JSON yields stderr message with code 0', async () => {
168
- mockedSpawn.mockReturnValueOnce(makeFakeProc('not-json', '', 0));
169
- const res = await runBdJson(['list', '--json']);
170
- expect(res.code).toBe(0);
171
- expect(res.stderr).toContain('Invalid JSON');
172
- });
173
-
174
- test('non-zero exit returns code and stderr', async () => {
175
- mockedSpawn.mockReturnValueOnce(makeFakeProc('', 'oops', 2));
176
- const res = await runBdJson(['list', '--json']);
177
- expect(res.code).toBe(2);
178
- expect(res.stderr).toContain('oops');
179
- });
180
- });
181
-
182
- describe('getGitUserName', () => {
183
- test('returns git user name on success', async () => {
184
- mockedSpawn.mockReturnValueOnce(makeFakeProc('Alice Smith\n', '', 0));
185
- const name = await getGitUserName();
186
- expect(name).toBe('Alice Smith');
187
- });
188
-
189
- test('returns empty string on failure', async () => {
190
- mockedSpawn.mockReturnValueOnce(makeFakeProc('', 'error', 1));
191
- const name = await getGitUserName();
192
- expect(name).toBe('');
193
- });
194
- });
@@ -1,207 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { beforeEach, describe, expect, test, vi } from 'vitest';
3
- import * as logging from '../logging.js';
4
- import * as commands from './commands.js';
5
- import { main, parseArgs } from './index.js';
6
-
7
- vi.mock('node:fs/promises', () => ({
8
- readFile: vi.fn()
9
- }));
10
-
11
- vi.mock('../logging.js', () => ({
12
- enableAllDebug: vi.fn(),
13
- debug: () => () => {}
14
- }));
15
-
16
- vi.mock('./commands.js', () => ({
17
- handleStart: vi.fn().mockResolvedValue(0),
18
- handleStop: vi.fn().mockResolvedValue(0),
19
- handleRestart: vi.fn().mockResolvedValue(0)
20
- }));
21
-
22
- /** @type {import('vitest').MockInstance} */
23
- let write_mock;
24
- /** @type {import('vitest').MockInstance} */
25
- let read_file_mock;
26
-
27
- beforeEach(() => {
28
- write_mock = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
29
- read_file_mock = vi.mocked(readFile);
30
- read_file_mock.mockResolvedValue(JSON.stringify({ version: '1.2.3' }));
31
- });
32
-
33
- describe('parseArgs', () => {
34
- test('returns help flag when -h or --help present', () => {
35
- const r1 = parseArgs(['-h']);
36
- const r2 = parseArgs(['--help']);
37
-
38
- expect(r1.flags.includes('help')).toBe(true);
39
- expect(r2.flags.includes('help')).toBe(true);
40
- });
41
-
42
- test('returns command token when valid', () => {
43
- expect(parseArgs(['start']).command).toBe('start');
44
- expect(parseArgs(['stop']).command).toBe('stop');
45
- expect(parseArgs(['restart']).command).toBe('restart');
46
- });
47
-
48
- test('recognizes --debug and -d flags', () => {
49
- const r1 = parseArgs(['--debug']);
50
- const r2 = parseArgs(['-d']);
51
-
52
- expect(r1.flags.includes('debug')).toBe(true);
53
- expect(r2.flags.includes('debug')).toBe(true);
54
- });
55
- test('recognizes --open flag', () => {
56
- const r = parseArgs(['start', '--open']);
57
-
58
- expect(r.flags.includes('open')).toBe(true);
59
- });
60
-
61
- test('recognizes -v and --version flags', () => {
62
- const r1 = parseArgs(['-v']);
63
- const r2 = parseArgs(['--version']);
64
-
65
- expect(r1.flags.includes('version')).toBe(true);
66
- expect(r2.flags.includes('version')).toBe(true);
67
- });
68
-
69
- test('parses --host option', () => {
70
- const r = parseArgs(['start', '--host', '0.0.0.0']);
71
-
72
- expect(r.options.host).toBe('0.0.0.0');
73
- });
74
-
75
- test('parses --port option', () => {
76
- const r = parseArgs(['start', '--port', '8080']);
77
-
78
- expect(r.options.port).toBe(8080);
79
- });
80
-
81
- test('ignores invalid --port value', () => {
82
- const r = parseArgs(['start', '--port', 'abc']);
83
-
84
- expect(r.options.port).toBeUndefined();
85
- });
86
- });
87
-
88
- describe('main', () => {
89
- test('prints usage and exits 0 on --help', async () => {
90
- const code = await main(['--help']);
91
-
92
- expect(code).toBe(0);
93
- expect(write_mock).toHaveBeenCalled();
94
- });
95
-
96
- test('prints version and exits 0 on --version', async () => {
97
- const code = await main(['--version']);
98
-
99
- expect(code).toBe(0);
100
- expect(write_mock).toHaveBeenCalled();
101
- const output = write_mock.mock.calls.map((c) => String(c[0])).join('');
102
- expect(output.trim()).toBe('1.2.3');
103
- });
104
-
105
- test('enables debug when --debug passed', async () => {
106
- const spy = vi.spyOn(logging, 'enableAllDebug');
107
-
108
- await main(['--debug', '--help']);
109
-
110
- expect(spy).toHaveBeenCalledTimes(1);
111
- });
112
-
113
- test('prints usage and exits 1 on no command', async () => {
114
- const code = await main([]);
115
-
116
- expect(code).toBe(1);
117
- expect(write_mock).toHaveBeenCalled();
118
- });
119
-
120
- test('dispatches to start handler', async () => {
121
- const code = await main(['start']);
122
-
123
- expect(code).toBe(0);
124
- expect(commands.handleStart).toHaveBeenCalledTimes(1);
125
- });
126
-
127
- test('propagates --open to start handler', async () => {
128
- await main(['start', '--open']);
129
-
130
- expect(commands.handleStart).toHaveBeenCalledWith({
131
- open: true,
132
- is_debug: false,
133
- host: undefined,
134
- port: undefined
135
- });
136
- });
137
-
138
- test('propagates --host and --port to start handler', async () => {
139
- await main(['start', '--host', '0.0.0.0', '--port', '8080']);
140
-
141
- expect(commands.handleStart).toHaveBeenCalledWith({
142
- open: false,
143
- is_debug: false,
144
- host: '0.0.0.0',
145
- port: 8080
146
- });
147
- });
148
-
149
- test('help lists --open', async () => {
150
- const write_spy = write_mock;
151
- write_spy.mockClear();
152
-
153
- await main(['--help']);
154
-
155
- const output = write_spy.mock.calls.map((c) => String(c[0])).join('');
156
- expect(output.includes('--open')).toBe(true);
157
- });
158
-
159
- test('dispatches to stop handler', async () => {
160
- const code = await main(['stop']);
161
-
162
- expect(code).toBe(0);
163
- expect(commands.handleStop).toHaveBeenCalledTimes(1);
164
- });
165
-
166
- test('dispatches to restart handler', async () => {
167
- const code = await main(['restart']);
168
-
169
- expect(code).toBe(0);
170
- expect(commands.handleRestart).toHaveBeenCalledTimes(1);
171
- expect(commands.handleRestart).toHaveBeenCalledWith({
172
- open: false,
173
- is_debug: false,
174
- host: undefined,
175
- port: undefined
176
- });
177
- });
178
-
179
- test('propagates --open to restart handler', async () => {
180
- await main(['restart', '--open']);
181
-
182
- expect(commands.handleRestart).toHaveBeenCalledWith({
183
- open: true,
184
- is_debug: false,
185
- host: undefined,
186
- port: undefined
187
- });
188
- });
189
-
190
- test('propagates --host and --port to restart handler', async () => {
191
- await main(['restart', '--host', '0.0.0.0', '--port', '9000']);
192
-
193
- expect(commands.handleRestart).toHaveBeenCalledWith({
194
- open: false,
195
- is_debug: false,
196
- host: '0.0.0.0',
197
- port: 9000
198
- });
199
- });
200
-
201
- test('unknown command prints usage and exits 1', async () => {
202
- const code = await main(['unknown']);
203
-
204
- expect(code).toBe(1);
205
- expect(write_mock).toHaveBeenCalled();
206
- });
207
- });
@@ -1,148 +0,0 @@
1
- import fs from 'node:fs';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import {
5
- afterAll,
6
- afterEach,
7
- beforeAll,
8
- describe,
9
- expect,
10
- test,
11
- vi
12
- } from 'vitest';
13
- import { handleRestart, handleStart, handleStop } from './commands.js';
14
- import * as daemon from './daemon.js';
15
-
16
- // Mock browser open + readiness wait to avoid external effects and flakiness
17
- vi.mock('./open.js', () => ({
18
- openUrl: async () => true,
19
- waitForServer: async () => {},
20
- registerWorkspaceWithServer: async () => true
21
- }));
22
-
23
- // Mock db resolution to avoid file system dependencies
24
- vi.mock('../db.js', () => ({
25
- resolveDbPath: () => ({
26
- path: '/mock/test.db',
27
- source: 'nearest',
28
- exists: true
29
- }),
30
- resolveWorkspaceDatabase: () => ({
31
- path: '/mock/test.db',
32
- source: 'nearest',
33
- exists: true
34
- })
35
- }));
36
-
37
- /** @type {string} */
38
- let tmp_runtime_dir;
39
- /** @type {Record<string, string | undefined>} */
40
- let prev_env;
41
-
42
- beforeAll(() => {
43
- // Snapshot selected env vars to restore later
44
- prev_env = {
45
- BDUI_RUNTIME_DIR: process.env.BDUI_RUNTIME_DIR,
46
- PORT: process.env.PORT
47
- };
48
-
49
- tmp_runtime_dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bdui-it-'));
50
- process.env.BDUI_RUNTIME_DIR = tmp_runtime_dir;
51
- // Use port 0 so OS assigns an ephemeral port; URL printing still occurs
52
- process.env.PORT = '0';
53
- vi.spyOn(console, 'log').mockImplementation(() => {});
54
- });
55
-
56
- afterEach(async () => {
57
- // Ensure no stray daemon is left between tests
58
- const pid = daemon.readPidFile();
59
- if (pid && daemon.isProcessRunning(pid)) {
60
- await daemon.terminateProcess(pid, 2000);
61
- }
62
- daemon.removePidFile();
63
- });
64
-
65
- afterAll(() => {
66
- // Restore env
67
- if (prev_env.BDUI_RUNTIME_DIR === undefined) {
68
- delete process.env.BDUI_RUNTIME_DIR;
69
- } else {
70
- process.env.BDUI_RUNTIME_DIR = prev_env.BDUI_RUNTIME_DIR;
71
- }
72
-
73
- if (prev_env.PORT === undefined) {
74
- delete process.env.PORT;
75
- } else {
76
- process.env.PORT = prev_env.PORT;
77
- }
78
-
79
- try {
80
- fs.rmSync(tmp_runtime_dir, { recursive: true, force: true });
81
- } catch {
82
- // ignore
83
- }
84
- });
85
-
86
- describe('commands integration', () => {
87
- test('start then stop returns 0 and manages PID file', async () => {
88
- // setup
89
- vi.spyOn(daemon, 'printServerUrl').mockImplementation(() => {});
90
-
91
- // execution
92
- const start_code = await handleStart({ open: false });
93
-
94
- // assertion
95
- expect(start_code).toBe(0);
96
- const pid_after_start = daemon.readPidFile();
97
- expect(typeof pid_after_start).toBe('number');
98
- expect(Number(pid_after_start)).toBeGreaterThan(0);
99
-
100
- // execution
101
- const stop_code = await handleStop();
102
-
103
- // assertion
104
- expect(stop_code).toBe(0);
105
- const pid_after_stop = daemon.readPidFile();
106
- expect(pid_after_stop).toBeNull();
107
- });
108
-
109
- test('stop returns 2 when not running', async () => {
110
- // execution
111
- const code = await handleStop();
112
-
113
- // assertion
114
- expect(code).toBe(2);
115
- });
116
-
117
- test('start is idempotent when already running', async () => {
118
- // setup
119
- await handleStart({ open: false });
120
- const start_spy = vi.spyOn(daemon, 'startDaemon');
121
-
122
- // execution
123
- const code = await handleStart({ open: false });
124
-
125
- // assertion
126
- expect(code).toBe(0);
127
- expect(start_spy).not.toHaveBeenCalled();
128
-
129
- // cleanup
130
- await handleStop();
131
- });
132
-
133
- test('restart stops (when needed) and starts', async () => {
134
- // setup
135
- vi.spyOn(daemon, 'printServerUrl').mockImplementation(() => {});
136
-
137
- // execution
138
- const code = await handleRestart();
139
-
140
- // assertion
141
- expect(code).toBe(0);
142
- const pid = daemon.readPidFile();
143
- expect(typeof pid).toBe('number');
144
-
145
- // cleanup
146
- await handleStop();
147
- });
148
- });