@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
@@ -1,421 +0,0 @@
1
- import { runBdJson } from './bd.js';
2
- import {
3
- isDoltPoolReady,
4
- enrichListItems,
5
- queryAllIssues,
6
- queryBlockedIssues,
7
- queryEpics,
8
- queryIssueDetail,
9
- queryIssuesByStatus,
10
- queryReadyIssues,
11
- querySearchIssues
12
- } from './dolt-queries.js';
13
- import { debug } from './logging.js';
14
-
15
- const log = debug('list-adapters');
16
-
17
- /**
18
- * Build concrete `bd` CLI args for a subscription type + params.
19
- * Always includes `--json` for parseable output.
20
- *
21
- * @param {{ type: string, params?: Record<string, string | number | boolean> }} spec
22
- * @returns {string[]}
23
- */
24
- export function mapSubscriptionToBdArgs(spec) {
25
- const t = String(spec.type);
26
- switch (t) {
27
- case 'all-issues': {
28
- return ['list', '--json', '--tree=false', '--all'];
29
- }
30
- case 'epics': {
31
- return ['list', '--json', '--tree=false', '--type=epic', '--all'];
32
- }
33
- case 'blocked-issues': {
34
- return ['blocked', '--json'];
35
- }
36
- case 'ready-issues': {
37
- return ['ready', '--limit', '1000', '--json'];
38
- }
39
- case 'in-progress-issues': {
40
- return ['list', '--json', '--tree=false', '--status', 'in_progress'];
41
- }
42
- case 'closed-issues': {
43
- return [
44
- 'list',
45
- '--json',
46
- '--tree=false',
47
- '--status',
48
- 'closed',
49
- '--limit',
50
- '1000'
51
- ];
52
- }
53
- case 'search-issues': {
54
- const p = spec.params || {};
55
- const q = String(p.q || '').trim();
56
- const args = ['list', '--json', '--tree=false', '--all'];
57
- // bd CLI doesn't support FULLTEXT — use list with status/type flags
58
- if (p.status && p.status !== 'all') args.push('--status', String(p.status));
59
- if (p.type && p.type !== 'all') args.push('--type', String(p.type));
60
- // When there's a query term, use `bd search` (limited but best we can do via CLI)
61
- if (q.length > 0) return ['search', q, '--json'];
62
- return args;
63
- }
64
- case 'issue-detail': {
65
- const p = spec.params || {};
66
- const id = String(p.id || '').trim();
67
- if (id.length === 0) {
68
- throw badRequest('Missing param: params.id');
69
- }
70
- return ['show', id, '--json'];
71
- }
72
- default: {
73
- throw badRequest(`Unknown subscription type: ${t}`);
74
- }
75
- }
76
- }
77
-
78
- /**
79
- * Normalize bd list output to minimal Issue shape used by the registry.
80
- * - Ensures `id` is a string.
81
- * - Coerces timestamps to numbers.
82
- * - `closed_at` defaults to null when missing or invalid.
83
- *
84
- * @param {unknown} value
85
- * @returns {Array<{ id: string, created_at: number, updated_at: number, closed_at: number | null } & Record<string, unknown>>}
86
- */
87
- export function normalizeIssueList(value) {
88
- if (!Array.isArray(value)) {
89
- return [];
90
- }
91
- /** @type {Array<{ id: string, created_at: number, updated_at: number, closed_at: number | null } & Record<string, unknown>>} */
92
- const out = [];
93
- for (const it of value) {
94
- const id = String(it.id ?? '');
95
- if (id.length === 0) {
96
- continue;
97
- }
98
- const created_at = parseTimestamp(/** @type {any} */ (it).created_at);
99
- const updated_at = parseTimestamp(it.updated_at);
100
- const closed_raw = it.closed_at;
101
- /** @type {number | null} */
102
- let closed_at = null;
103
- if (closed_raw !== undefined && closed_raw !== null) {
104
- const n = parseTimestamp(closed_raw);
105
- closed_at = Number.isFinite(n) ? n : null;
106
- }
107
- out.push({
108
- ...it,
109
- id,
110
- created_at: Number.isFinite(created_at) ? created_at : 0,
111
- updated_at: Number.isFinite(updated_at) ? updated_at : 0,
112
- closed_at
113
- });
114
- }
115
- return out;
116
- }
117
-
118
- /**
119
- * @typedef {Object} FetchListResultSuccess
120
- * @property {true} ok
121
- * @property {Array<{ id: string, updated_at: number, closed_at: number | null } & Record<string, unknown>>} items
122
- * @property {number} [total] - Total count for paginated queries
123
- */
124
-
125
- /**
126
- * @typedef {Object} FetchListResultFailure
127
- * @property {false} ok
128
- * @property {{ code: string, message: string, details?: Record<string, unknown> }} error
129
- */
130
-
131
- /**
132
- * Execute the mapped `bd` command for a subscription spec and return normalized items.
133
- * Errors do not throw; they are surfaced as a structured object.
134
- *
135
- * @param {{ type: string, params?: Record<string, string | number | boolean> }} spec
136
- * @param {{ cwd?: string }} [options] - Optional working directory for bd command
137
- * @returns {Promise<FetchListResultSuccess | FetchListResultFailure>}
138
- */
139
- export async function fetchListForSubscription(spec, options = {}) {
140
- /** @type {FetchListResultSuccess | FetchListResultFailure} */
141
- let result;
142
-
143
- if (isDoltPoolReady()) {
144
- log('using SQL fast path for %s', spec.type);
145
- try {
146
- result = await fetchViaSQL(spec);
147
- } catch (err) {
148
- log('SQL fast path failed for %s: %o', spec.type, err);
149
- // Don't fall back to bd CLI — sql-server holds the lock
150
- return {
151
- ok: false,
152
- error: {
153
- code: 'db_error',
154
- message: (err && /** @type {any} */ (err).message) || 'SQL query failed'
155
- }
156
- };
157
- }
158
- } else {
159
- log('using bd CLI fallback for %s', spec.type);
160
- result = await fetchViaBdCli(spec, options);
161
- }
162
-
163
- // Enrich items regardless of which path produced them
164
- if (result.ok && result.items.length > 0) {
165
- try {
166
- result = { ...result, items: await enrichListItems(result.items) };
167
- } catch (err) {
168
- log('enrichListItems failed for %s: %o', spec.type, err);
169
- }
170
- }
171
-
172
- return result;
173
- }
174
-
175
- /**
176
- * Hydrate parent context for a single detail item.
177
- * `bd show --json` can include the parent id without the parent's display fields.
178
- *
179
- * @param {Record<string, unknown>} item
180
- * @param {{ cwd?: string }} [options]
181
- * @returns {Promise<Record<string, unknown>>}
182
- */
183
- export async function enrichIssueDetailParentContext(item, options = {}) {
184
- const parentIdRaw = item.parent_id ?? item.parent;
185
- const parentId =
186
- typeof parentIdRaw === 'string'
187
- ? parentIdRaw.trim()
188
- : parentIdRaw === undefined || parentIdRaw === null
189
- ? ''
190
- : String(parentIdRaw).trim();
191
-
192
- if (parentId.length === 0) {
193
- return item;
194
- }
195
-
196
- const enriched = {
197
- ...item,
198
- parent_id: parentId,
199
- parent: parentId
200
- };
201
-
202
- if (
203
- typeof enriched.parent_title === 'string' &&
204
- typeof enriched.parent_status === 'string' &&
205
- typeof enriched.parent_type === 'string'
206
- ) {
207
- return enriched;
208
- }
209
-
210
- const res = await runBdJson(['show', parentId, '--json'], { cwd: options.cwd });
211
- if (
212
- !res ||
213
- res.code !== 0 ||
214
- !res.stdoutJson ||
215
- typeof res.stdoutJson !== 'object'
216
- ) {
217
- return enriched;
218
- }
219
-
220
- // bd show --json may return an array or a single object
221
- const parent = /** @type {Record<string, unknown>} */ (
222
- Array.isArray(res.stdoutJson) ? res.stdoutJson[0] : res.stdoutJson
223
- );
224
- if (!parent) return enriched;
225
- if (typeof parent.title === 'string') {
226
- enriched.parent_title = parent.title;
227
- }
228
- if (typeof parent.status === 'string') {
229
- enriched.parent_status = parent.status;
230
- }
231
- if (typeof parent.issue_type === 'string') {
232
- enriched.parent_type = parent.issue_type;
233
- }
234
- return enriched;
235
- }
236
-
237
- /**
238
- * @param {{ type: string, params?: Record<string, string | number | boolean> }} spec
239
- * @returns {Promise<FetchListResultSuccess | FetchListResultFailure>}
240
- */
241
- async function fetchViaSQL(spec) {
242
- const t = String(spec.type);
243
- const p = spec.params || {};
244
- const pagination = {
245
- limit: typeof p.limit === 'number' ? p.limit : 0,
246
- offset: typeof p.offset === 'number' ? p.offset : 0
247
- };
248
-
249
- /**
250
- * @param {{ ok: true, items: any[], total: number }} res
251
- * @returns {FetchListResultSuccess}
252
- */
253
- const withTotal = (res) => {
254
- const items = normalizeIssueList(res.items);
255
- return { ok: true, items, total: res.total };
256
- };
257
-
258
- /** @param {() => Promise<any>} queryFn */
259
- const run = async (queryFn) => {
260
- const res = await queryFn();
261
- if (!res.ok) return { ok: false, error: res.error };
262
- return withTotal(res);
263
- };
264
-
265
- switch (t) {
266
- case 'all-issues':
267
- return run(() => queryAllIssues(pagination));
268
- case 'epics':
269
- return run(() => queryEpics(pagination));
270
- case 'blocked-issues':
271
- return run(() => queryBlockedIssues(pagination));
272
- case 'ready-issues':
273
- return run(() => queryReadyIssues(pagination));
274
- case 'in-progress-issues':
275
- return run(() => queryIssuesByStatus('in_progress', pagination));
276
- case 'closed-issues':
277
- return run(() => queryIssuesByStatus('closed', pagination.limit ? pagination : { limit: 1000, offset: 0 }));
278
- case 'search-issues': {
279
- const q = String(p.q || '').trim();
280
- const status = typeof p.status === 'string' ? p.status : undefined;
281
- const type = typeof p.type === 'string' ? p.type : undefined;
282
- // Always use querySearchIssues — it handles empty q with status/type filters
283
- return run(() => querySearchIssues(q, { ...pagination, status, type }));
284
- }
285
- case 'issue-detail': {
286
- const id = String(p.id || '').trim();
287
- if (id.length === 0) {
288
- return { ok: false, error: { code: 'bad_request', message: 'Missing param: params.id' } };
289
- }
290
- const res = await queryIssueDetail(id);
291
- if (!res.ok) return { ok: false, error: res.error };
292
- return { ok: true, items: normalizeIssueList([res.item]), total: 1 };
293
- }
294
- default:
295
- return { ok: false, error: { code: 'bad_request', message: `Unknown subscription type: ${t}` } };
296
- }
297
- }
298
-
299
- /**
300
- * Slow fallback: spawn bd CLI subprocess.
301
- *
302
- * @param {{ type: string, params?: Record<string, string | number | boolean> }} spec
303
- * @param {{ cwd?: string }} options
304
- * @returns {Promise<FetchListResultSuccess | FetchListResultFailure>}
305
- */
306
- async function fetchViaBdCli(spec, options) {
307
- /** @type {string[]} */
308
- let args;
309
- try {
310
- args = mapSubscriptionToBdArgs(spec);
311
- } catch (err) {
312
- // Surface bad requests (e.g., missing params)
313
- log('mapSubscriptionToBdArgs failed for %o: %o', spec, err);
314
- const e = toErrorObject(err);
315
- return { ok: false, error: e };
316
- }
317
-
318
- try {
319
- const res = await runBdJson(args, { cwd: options.cwd });
320
- if (!res || res.code !== 0 || !('stdoutJson' in res)) {
321
- log(
322
- 'bd failed for %o (args=%o) code=%s stderr=%s',
323
- spec,
324
- args,
325
- res?.code,
326
- res?.stderr || ''
327
- );
328
- return {
329
- ok: false,
330
- error: {
331
- code: 'bd_error',
332
- message: String(res?.stderr || 'bd failed'),
333
- details: { exit_code: res?.code ?? -1 }
334
- }
335
- };
336
- }
337
- // bd show may return a single object; normalize to an array first
338
- let raw = Array.isArray(res.stdoutJson)
339
- ? res.stdoutJson
340
- : res.stdoutJson && typeof res.stdoutJson === 'object'
341
- ? [res.stdoutJson]
342
- : [];
343
-
344
- let items = normalizeIssueList(raw);
345
- if (String(spec.type) === 'issue-detail') {
346
- items = await Promise.all(
347
- items.map(async (item) => {
348
- const enriched = await enrichIssueDetailParentContext(item, options);
349
- const cRes = await runBdJson(['comments', String(item.id), '--json'], { cwd: options.cwd });
350
- if (cRes && cRes.code === 0 && Array.isArray(cRes.stdoutJson)) {
351
- enriched.comments = cRes.stdoutJson;
352
- enriched.comment_count = cRes.stdoutJson.length;
353
- }
354
- return enriched;
355
- })
356
- );
357
- }
358
- return { ok: true, items };
359
- } catch (err) {
360
- log('bd invocation failed for %o (args=%o): %o', spec, args, err);
361
- return {
362
- ok: false,
363
- error: {
364
- code: 'bd_error',
365
- message:
366
- (err && /** @type {any} */ (err).message) || 'bd invocation failed'
367
- }
368
- };
369
- }
370
- }
371
-
372
- /**
373
- * Create a `bad_request` error object.
374
- *
375
- * @param {string} message
376
- */
377
- function badRequest(message) {
378
- const e = new Error(message);
379
- // @ts-expect-error add code
380
- e.code = 'bad_request';
381
- return e;
382
- }
383
-
384
- /**
385
- * Normalize arbitrary thrown values to a structured error object.
386
- *
387
- * @param {unknown} err
388
- * @returns {FetchListResultFailure['error']}
389
- */
390
- function toErrorObject(err) {
391
- if (err && typeof err === 'object') {
392
- const any = /** @type {{ code?: unknown, message?: unknown }} */ (err);
393
- const code = typeof any.code === 'string' ? any.code : 'bad_request';
394
- const message =
395
- typeof any.message === 'string' ? any.message : 'Request error';
396
- return { code, message };
397
- }
398
- return { code: 'bad_request', message: 'Request error' };
399
- }
400
-
401
- /**
402
- * Parse a bd timestamp string to epoch ms using Date.parse.
403
- * Falls back to numeric coercion when parsing fails.
404
- *
405
- * @param {unknown} v
406
- * @returns {number}
407
- */
408
- function parseTimestamp(v) {
409
- if (typeof v === 'string') {
410
- const ms = Date.parse(v);
411
- if (Number.isFinite(ms)) {
412
- return ms;
413
- }
414
- const n = Number(v);
415
- return Number.isFinite(n) ? n : 0;
416
- }
417
- if (typeof v === 'number') {
418
- return Number.isFinite(v) ? v : 0;
419
- }
420
- return 0;
421
- }
@@ -1,208 +0,0 @@
1
- import { beforeEach, describe, expect, test, vi } from 'vitest';
2
- import { runBdJson } from './bd.js';
3
- import {
4
- fetchListForSubscription,
5
- mapSubscriptionToBdArgs
6
- } from './list-adapters.js';
7
-
8
- vi.mock('./bd.js', () => ({ runBdJson: vi.fn() }));
9
-
10
- describe('list adapters for subscription types', () => {
11
- beforeEach(() => {
12
- /** @type {import('vitest').Mock} */ (runBdJson).mockReset();
13
- });
14
-
15
- test('mapSubscriptionToBdArgs returns args for all-issues', () => {
16
- const args = mapSubscriptionToBdArgs({ type: 'all-issues' });
17
- expect(args).toEqual(['list', '--json', '--tree=false', '--all']);
18
- });
19
-
20
- test('mapSubscriptionToBdArgs returns args for epics', () => {
21
- const args = mapSubscriptionToBdArgs({ type: 'epics' });
22
- expect(args).toEqual(['list', '--json', '--tree=false', '--type=epic', '--all']);
23
- });
24
-
25
- test('mapSubscriptionToBdArgs returns args for blocked-issues', () => {
26
- const args = mapSubscriptionToBdArgs({ type: 'blocked-issues' });
27
- // We choose dedicated subcommand mapping for blocked
28
- expect(args).toEqual(['blocked', '--json']);
29
- });
30
-
31
- test('mapSubscriptionToBdArgs returns args for ready-issues', () => {
32
- const args = mapSubscriptionToBdArgs({ type: 'ready-issues' });
33
- expect(args).toEqual(['ready', '--limit', '1000', '--json']);
34
- });
35
-
36
- test('mapSubscriptionToBdArgs returns args for in-progress-issues', () => {
37
- const args = mapSubscriptionToBdArgs({ type: 'in-progress-issues' });
38
- expect(args).toEqual([
39
- 'list',
40
- '--json',
41
- '--tree=false',
42
- '--status',
43
- 'in_progress'
44
- ]);
45
- });
46
-
47
- test('mapSubscriptionToBdArgs returns args for closed-issues', () => {
48
- const args = mapSubscriptionToBdArgs({ type: 'closed-issues' });
49
- expect(args).toEqual([
50
- 'list',
51
- '--json',
52
- '--tree=false',
53
- '--status',
54
- 'closed',
55
- '--limit',
56
- '1000'
57
- ]);
58
- });
59
-
60
- test('mapSubscriptionToBdArgs returns args for issue-detail', () => {
61
- const args = mapSubscriptionToBdArgs({
62
- type: 'issue-detail',
63
- params: { id: 'UI-123' }
64
- });
65
- expect(args).toEqual(['show', 'UI-123', '--json']);
66
- });
67
-
68
- test('fetchListForSubscription returns normalized items (Date.parse)', async () => {
69
- /** @type {import('vitest').Mock} */ (runBdJson).mockResolvedValue({
70
- code: 0,
71
- stdoutJson: [
72
- {
73
- id: 'A-1',
74
- updated_at: '2024-01-01T00:00:00.000Z',
75
- closed_at: null,
76
- extra: 'x'
77
- },
78
- {
79
- id: 'A-2',
80
- updated_at: '2024-01-01T00:00:01.000Z',
81
- closed_at: '2024-01-01T00:00:05.000Z'
82
- },
83
- { id: 3, updated_at: 'not-a-date' }
84
- ]
85
- });
86
- const res = await fetchListForSubscription({ type: 'all-issues' });
87
- expect(res.ok).toBe(true);
88
- if (res.ok) {
89
- expect(res.items.length).toBe(3);
90
- expect(res.items[0]).toMatchObject({
91
- id: 'A-1',
92
- updated_at: Date.parse('2024-01-01T00:00:00.000Z'),
93
- closed_at: null
94
- });
95
- expect(res.items[1]).toMatchObject({
96
- id: 'A-2',
97
- updated_at: Date.parse('2024-01-01T00:00:01.000Z'),
98
- closed_at: Date.parse('2024-01-01T00:00:05.000Z')
99
- });
100
- // id coerced to string, closed_at defaults to null
101
- expect(res.items[2]).toMatchObject({
102
- id: '3',
103
- updated_at: 0,
104
- closed_at: null
105
- });
106
- }
107
- });
108
-
109
- test('issue-detail via bd fallback hydrates parent context', async () => {
110
- /** @type {import('vitest').Mock} */ (runBdJson)
111
- .mockResolvedValueOnce({
112
- code: 0,
113
- stdoutJson: {
114
- id: 'UI-1',
115
- title: 'Child issue',
116
- parent: 'EP-1',
117
- created_at: '2024-01-01T00:00:00.000Z',
118
- updated_at: '2024-01-01T00:00:01.000Z'
119
- }
120
- })
121
- .mockResolvedValueOnce({
122
- code: 0,
123
- stdoutJson: {
124
- id: 'EP-1',
125
- title: 'Parent epic',
126
- status: 'in_progress',
127
- issue_type: 'epic'
128
- }
129
- });
130
-
131
- const res = await fetchListForSubscription({
132
- type: 'issue-detail',
133
- params: { id: 'UI-1' }
134
- });
135
-
136
- expect(res.ok).toBe(true);
137
- if (res.ok) {
138
- expect(res.items).toHaveLength(1);
139
- expect(res.items[0]).toMatchObject({
140
- id: 'UI-1',
141
- parent: 'EP-1',
142
- parent_id: 'EP-1',
143
- parent_title: 'Parent epic',
144
- parent_status: 'in_progress',
145
- parent_type: 'epic'
146
- });
147
- }
148
- });
149
-
150
- test('epics subscription returns flat issue list', async () => {
151
- // bd list --type=epic --all returns flat issue objects (no nested .epic key)
152
- /** @type {import('vitest').Mock} */ (runBdJson).mockResolvedValue({
153
- code: 0,
154
- stdoutJson: [
155
- {
156
- id: 'E-1',
157
- status: 'open',
158
- issue_type: 'epic',
159
- created_at: '2024-01-01T00:00:00.000Z',
160
- updated_at: '2024-01-01T00:00:00.000Z',
161
- closed_at: null
162
- },
163
- {
164
- id: 'E-2',
165
- status: 'closed',
166
- issue_type: 'epic',
167
- created_at: '2024-01-01T00:00:00.000Z',
168
- updated_at: '2024-02-01T00:00:00.000Z',
169
- closed_at: '2024-02-01T00:00:00.000Z'
170
- }
171
- ]
172
- });
173
-
174
- const res = await fetchListForSubscription({ type: 'epics' });
175
-
176
- expect(res.ok).toBe(true);
177
- if (res.ok) {
178
- expect(res.items).toHaveLength(2);
179
- expect(res.items[0]).toMatchObject({ id: 'E-1', status: 'open' });
180
- expect(res.items[1]).toMatchObject({ id: 'E-2', status: 'closed' });
181
- }
182
- });
183
-
184
- test('fetchListForSubscription surfaces bd error', async () => {
185
- /** @type {import('vitest').Mock} */ (runBdJson).mockResolvedValue({
186
- code: 2,
187
- stderr: 'boom'
188
- });
189
- const res = await fetchListForSubscription({ type: 'all-issues' });
190
- expect(res.ok).toBe(false);
191
- if (!res.ok) {
192
- expect(res.error.code).toBe('bd_error');
193
- expect(res.error.message).toContain('boom');
194
- expect(res.error.details && res.error.details.exit_code).toBe(2);
195
- }
196
- });
197
-
198
- test('fetchListForSubscription returns error for unknown type', async () => {
199
- const res = await fetchListForSubscription(
200
- /** @type {any} */ ({ type: 'unknown' })
201
- );
202
- expect(res.ok).toBe(false);
203
- if (!res.ok) {
204
- expect(res.error.code).toBe('bad_request');
205
- expect(res.error.message).toMatch(/Unknown subscription type/);
206
- }
207
- });
208
- });
package/server/logging.js DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * Debug logger helper for Node server/CLI.
3
- */
4
- import createDebug from 'debug';
5
-
6
- /**
7
- * Create a namespaced logger for Node runtime.
8
- *
9
- * @param {string} ns - Module namespace suffix (e.g., 'ws', 'watcher').
10
- */
11
- export function debug(ns) {
12
- return createDebug(`beads-ui:${ns}`);
13
- }
14
-
15
- /**
16
- * Enable all `beads-ui:*` debug logs at runtime for Node/CLI.
17
- * Safe to call multiple times.
18
- */
19
- export function enableAllDebug() {
20
- // `debug` exposes a global enable/disable API.
21
- // Enabling after loggers are created updates their `.enabled` state.
22
- createDebug.enable(process.env.DEBUG || 'beads-ui:*');
23
- }