@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.
- package/README.md +85 -144
- package/bin/bd-web +94 -0
- package/dist/assets/index-BBVIMXaM.js +73 -0
- package/dist/assets/index-SUXI6Mzt.css +1 -0
- package/dist/bd-favicon-16.svg +6 -0
- package/dist/bd-favicon-32.svg +6 -0
- package/dist/bd-logo-512.svg +6 -0
- package/dist/favicon.ico +0 -0
- package/dist/icon-180.png +0 -0
- package/dist/icon-192.png +0 -0
- package/dist/icon-512.png +0 -0
- package/dist/index.html +8 -5
- package/package.json +39 -29
- package/server/auth.js +68 -87
- package/server/db.js +91 -134
- package/server/dsn.js +130 -0
- package/server/index.js +151 -87
- package/server/queries.js +247 -0
- package/server/routes/auth.js +27 -0
- package/server/routes/issues.js +120 -0
- package/server/routes/stream.js +111 -0
- package/server/types.js +83 -0
- package/app/protocol.js +0 -216
- package/bin/bd-grep +0 -121
- package/bin/bd-ui +0 -19
- package/dist/assets/abap-DsBKuouk.js +0 -1
- package/dist/assets/actionscript-3-D_z4Izcz.js +0 -1
- package/dist/assets/ada-727ZlQH0.js +0 -1
- package/dist/assets/andromeeda-C3khCPGq.js +0 -1
- package/dist/assets/angular-html-LfdN0zeE.js +0 -1
- package/dist/assets/angular-ts-CKsD7JZE.js +0 -1
- package/dist/assets/apache-Dn00JSTd.js +0 -1
- package/dist/assets/apex-COJ4H7py.js +0 -1
- package/dist/assets/apl-BBq3IX1j.js +0 -1
- package/dist/assets/applescript-Bu5BbsvL.js +0 -1
- package/dist/assets/ara-7O62HKoU.js +0 -1
- package/dist/assets/asciidoc-BPT9niGB.js +0 -1
- package/dist/assets/asm-Dhn9LcZ4.js +0 -1
- package/dist/assets/astro-CqkE3fuf.js +0 -1
- package/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
- package/dist/assets/awk-eg146-Ew.js +0 -1
- package/dist/assets/ayu-dark-Cv9koXgw.js +0 -1
- package/dist/assets/ballerina-Du268qiB.js +0 -1
- package/dist/assets/bat-fje9CFhw.js +0 -1
- package/dist/assets/beancount-BwXTMy5W.js +0 -1
- package/dist/assets/berry-3xVqZejG.js +0 -1
- package/dist/assets/bibtex-xW4inM5L.js +0 -1
- package/dist/assets/bicep-DHo0CJ0O.js +0 -1
- package/dist/assets/blade-a8OxSdnT.js +0 -1
- package/dist/assets/bsl-Dgyn0ogV.js +0 -1
- package/dist/assets/c-C3t2pwGQ.js +0 -1
- package/dist/assets/cadence-DNquZEk8.js +0 -1
- package/dist/assets/cairo--RitsXJZ.js +0 -1
- package/dist/assets/catppuccin-frappe-CD_QflpE.js +0 -1
- package/dist/assets/catppuccin-latte-DRW-0cLl.js +0 -1
- package/dist/assets/catppuccin-macchiato-C-_shW-Y.js +0 -1
- package/dist/assets/catppuccin-mocha-LGGdnPYs.js +0 -1
- package/dist/assets/clarity-BHOwM8T6.js +0 -1
- package/dist/assets/clojure-DxSadP1t.js +0 -1
- package/dist/assets/cmake-DbXoA79R.js +0 -1
- package/dist/assets/cobol-PTqiYgYu.js +0 -1
- package/dist/assets/codeowners-Bp6g37R7.js +0 -1
- package/dist/assets/codeql-sacFqUAJ.js +0 -1
- package/dist/assets/coffee-dyiR41kL.js +0 -1
- package/dist/assets/common-lisp-C7gG9l05.js +0 -1
- package/dist/assets/coq-Dsg_Bt_b.js +0 -1
- package/dist/assets/cpp-BksuvNSY.js +0 -1
- package/dist/assets/crystal-DtDmRg-F.js +0 -1
- package/dist/assets/csharp-D9R-vmeu.js +0 -1
- package/dist/assets/css-BPhBrDlE.js +0 -1
- package/dist/assets/csv-B0qRVHPH.js +0 -1
- package/dist/assets/cue-DtFQj3wx.js +0 -1
- package/dist/assets/cypher-m2LEI-9-.js +0 -1
- package/dist/assets/d-BoXegm-a.js +0 -1
- package/dist/assets/dark-plus-C3mMm8J8.js +0 -1
- package/dist/assets/dart-B9wLZaAG.js +0 -1
- package/dist/assets/dax-ClGRhx96.js +0 -1
- package/dist/assets/desktop-DEIpsLCJ.js +0 -1
- package/dist/assets/diff-BgYniUM_.js +0 -1
- package/dist/assets/docker-COcR7UxN.js +0 -1
- package/dist/assets/dotenv-BjQB5zDj.js +0 -1
- package/dist/assets/dracula-BzJJZx-M.js +0 -1
- package/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
- package/dist/assets/dream-maker-C-nORZOA.js +0 -1
- package/dist/assets/edge-D5gP-w-T.js +0 -1
- package/dist/assets/elixir-CLiX3zqd.js +0 -1
- package/dist/assets/elm-CmHSxxaM.js +0 -1
- package/dist/assets/emacs-lisp-BX77sIaO.js +0 -1
- package/dist/assets/erb-BYTLMnw6.js +0 -1
- package/dist/assets/erlang-B-DoSBHF.js +0 -1
- package/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
- package/dist/assets/everforest-light-C8M2exoo.js +0 -1
- package/dist/assets/fennel-bCA53EVm.js +0 -1
- package/dist/assets/fish-w-ucz2PV.js +0 -1
- package/dist/assets/fluent-Dayu4EKP.js +0 -1
- package/dist/assets/fortran-fixed-form-TqA4NnZg.js +0 -1
- package/dist/assets/fortran-free-form-DKXYxT9g.js +0 -1
- package/dist/assets/fsharp-XplgxFYe.js +0 -1
- package/dist/assets/gdresource-BHYsBjWJ.js +0 -1
- package/dist/assets/gdscript-DfxzS6Rs.js +0 -1
- package/dist/assets/gdshader-SKMF96pI.js +0 -1
- package/dist/assets/genie-ajMbGru0.js +0 -1
- package/dist/assets/gherkin--30QC5Em.js +0 -1
- package/dist/assets/git-commit-i4q6IMui.js +0 -1
- package/dist/assets/git-rebase-B-v9cOL2.js +0 -1
- package/dist/assets/github-dark-DHJKELXO.js +0 -1
- package/dist/assets/github-dark-default-Cuk6v7N8.js +0 -1
- package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
- package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
- package/dist/assets/github-light-DAi9KRSo.js +0 -1
- package/dist/assets/github-light-default-D7oLnXFd.js +0 -1
- package/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
- package/dist/assets/gleam-B430Bg39.js +0 -1
- package/dist/assets/glimmer-js-D-cwc0-E.js +0 -1
- package/dist/assets/glimmer-ts-pgjy16dm.js +0 -1
- package/dist/assets/glsl-DBO2IWDn.js +0 -1
- package/dist/assets/gnuplot-CM8KxXT1.js +0 -1
- package/dist/assets/go-B1SYOhNW.js +0 -1
- package/dist/assets/graphql-cDcHW_If.js +0 -1
- package/dist/assets/groovy-DkBy-JyN.js +0 -1
- package/dist/assets/hack-D1yCygmZ.js +0 -1
- package/dist/assets/haml-B2EZWmdv.js +0 -1
- package/dist/assets/handlebars-BQGss363.js +0 -1
- package/dist/assets/haskell-BILxekzW.js +0 -1
- package/dist/assets/haxe-C5wWYbrZ.js +0 -1
- package/dist/assets/hcl-HzYwdGDm.js +0 -1
- package/dist/assets/hjson-T-Tgc4AT.js +0 -1
- package/dist/assets/hlsl-ifBTmRxC.js +0 -1
- package/dist/assets/houston-DnULxvSX.js +0 -1
- package/dist/assets/html-C2L_23MC.js +0 -1
- package/dist/assets/html-derivative-CSfWNPLT.js +0 -1
- package/dist/assets/http-FRrOvY1W.js +0 -1
- package/dist/assets/hxml-TIA70rKU.js +0 -1
- package/dist/assets/hy-BMj5Y0dO.js +0 -1
- package/dist/assets/imba-bv_oIlVt.js +0 -1
- package/dist/assets/index-CNDeKQGk.js +0 -125
- package/dist/assets/index-oO5WB2l2.css +0 -1
- package/dist/assets/ini-BjABl1g7.js +0 -1
- package/dist/assets/java-xI-RfyKK.js +0 -1
- package/dist/assets/javascript-ySlJ1b_l.js +0 -1
- package/dist/assets/jinja-DGy0s7-h.js +0 -1
- package/dist/assets/jison-BqZprYcd.js +0 -1
- package/dist/assets/json-BQoSv7ci.js +0 -1
- package/dist/assets/json5-w8dY5SsB.js +0 -1
- package/dist/assets/jsonc-TU54ms6u.js +0 -1
- package/dist/assets/jsonl-DREVFZK8.js +0 -1
- package/dist/assets/jsonnet-BfivnA6A.js +0 -1
- package/dist/assets/jssm-P4WzXJd0.js +0 -1
- package/dist/assets/jsx-BAng5TT0.js +0 -1
- package/dist/assets/julia-BBuGR-5E.js +0 -1
- package/dist/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
- package/dist/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
- package/dist/assets/kanagawa-wave-DWedfzmr.js +0 -1
- package/dist/assets/kotlin-B5lbUyaz.js +0 -1
- package/dist/assets/kusto-mebxcVVE.js +0 -1
- package/dist/assets/laserwave-DUszq2jm.js +0 -1
- package/dist/assets/latex-C-cWTeAZ.js +0 -1
- package/dist/assets/lean-XBlWyCtg.js +0 -1
- package/dist/assets/less-BfCpw3nA.js +0 -1
- package/dist/assets/light-plus-B7mTdjB0.js +0 -1
- package/dist/assets/liquid-D3W5UaiH.js +0 -1
- package/dist/assets/log-Cc5clBb7.js +0 -1
- package/dist/assets/logo-IuBKFhSY.js +0 -1
- package/dist/assets/lua-CvWAzNxB.js +0 -1
- package/dist/assets/luau-Du5NY7AG.js +0 -1
- package/dist/assets/make-Bvotw-X0.js +0 -1
- package/dist/assets/markdown-UIAJJxZW.js +0 -1
- package/dist/assets/marko-z0MBrx5-.js +0 -1
- package/dist/assets/material-theme-D5KoaKCx.js +0 -1
- package/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
- package/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
- package/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
- package/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
- package/dist/assets/matlab-D9-PGadD.js +0 -1
- package/dist/assets/mdc-DB_EDNY_.js +0 -1
- package/dist/assets/mdx-sdHcTMYB.js +0 -1
- package/dist/assets/mermaid-Ci6OQyBP.js +0 -1
- package/dist/assets/min-dark-CafNBF8u.js +0 -1
- package/dist/assets/min-light-CTRr51gU.js +0 -1
- package/dist/assets/mipsasm-BC5c_5Pe.js +0 -1
- package/dist/assets/mojo-Tz6hzZYG.js +0 -1
- package/dist/assets/monokai-D4h5O-jR.js +0 -1
- package/dist/assets/move-DB_GagMm.js +0 -1
- package/dist/assets/narrat-DLbgOhZU.js +0 -1
- package/dist/assets/nextflow-B0XVJmRM.js +0 -1
- package/dist/assets/nginx-D_VnBJ67.js +0 -1
- package/dist/assets/night-owl-C39BiMTA.js +0 -1
- package/dist/assets/nim-ZlGxZxc3.js +0 -1
- package/dist/assets/nix-shcSOmrb.js +0 -1
- package/dist/assets/nord-Ddv68eIx.js +0 -1
- package/dist/assets/nushell-D4Tzg5kh.js +0 -1
- package/dist/assets/objective-c-Deuh7S70.js +0 -1
- package/dist/assets/objective-cpp-BUEGK8hf.js +0 -1
- package/dist/assets/ocaml-BNioltXt.js +0 -1
- package/dist/assets/one-dark-pro-GBQ2dnAY.js +0 -1
- package/dist/assets/one-light-PoHY5YXO.js +0 -1
- package/dist/assets/pascal-JqZropPD.js +0 -1
- package/dist/assets/perl-CHQXSrWU.js +0 -1
- package/dist/assets/php-B5ebYQev.js +0 -1
- package/dist/assets/plastic-3e1v2bzS.js +0 -1
- package/dist/assets/plsql-LKU2TuZ1.js +0 -1
- package/dist/assets/po-BFLt1xDp.js +0 -1
- package/dist/assets/poimandres-CS3Unz2-.js +0 -1
- package/dist/assets/polar-DKykz6zU.js +0 -1
- package/dist/assets/postcss-B3ZDOciz.js +0 -1
- package/dist/assets/powerquery-CSHBycmS.js +0 -1
- package/dist/assets/powershell-BIEUsx6d.js +0 -1
- package/dist/assets/prisma-B48N-Iqd.js +0 -1
- package/dist/assets/prolog-BY-TUvya.js +0 -1
- package/dist/assets/proto-zocC4JxJ.js +0 -1
- package/dist/assets/pug-CM9l7STV.js +0 -1
- package/dist/assets/puppet-Cza_XSSt.js +0 -1
- package/dist/assets/purescript-Bg-kzb6g.js +0 -1
- package/dist/assets/python-DhUJRlN_.js +0 -1
- package/dist/assets/qml-D8XfuvdV.js +0 -1
- package/dist/assets/qmldir-C8lEn-DE.js +0 -1
- package/dist/assets/qss-DhMKtDLN.js +0 -1
- package/dist/assets/r-CwjWoCRV.js +0 -1
- package/dist/assets/racket-CzouJOBO.js +0 -1
- package/dist/assets/raku-B1bQXN8T.js +0 -1
- package/dist/assets/razor-CNLDkMZG.js +0 -1
- package/dist/assets/red-bN70gL4F.js +0 -1
- package/dist/assets/reg-5LuOXUq_.js +0 -1
- package/dist/assets/regexp-DWJ3fJO_.js +0 -1
- package/dist/assets/rel-DJlmqQ1C.js +0 -1
- package/dist/assets/riscv-QhoSD0DR.js +0 -1
- package/dist/assets/rose-pine-CmCqftbK.js +0 -1
- package/dist/assets/rose-pine-dawn-Ds-gbosJ.js +0 -1
- package/dist/assets/rose-pine-moon-CjDtw9vr.js +0 -1
- package/dist/assets/rst-4NLicBqY.js +0 -1
- package/dist/assets/ruby-DeZ3UC14.js +0 -1
- package/dist/assets/rust-Be6lgOlo.js +0 -1
- package/dist/assets/sas-BmTFh92c.js +0 -1
- package/dist/assets/sass-BJ4Li9vH.js +0 -1
- package/dist/assets/scala-DQVVAn-B.js +0 -1
- package/dist/assets/scheme-BJGe-b2p.js +0 -1
- package/dist/assets/scss-C31hgJw-.js +0 -1
- package/dist/assets/sdbl-BLhTXw86.js +0 -1
- package/dist/assets/shaderlab-B7qAK45m.js +0 -1
- package/dist/assets/shellscript-atvbtKCR.js +0 -1
- package/dist/assets/shellsession-C_rIy8kc.js +0 -1
- package/dist/assets/slack-dark-BthQWCQV.js +0 -1
- package/dist/assets/slack-ochin-DqwNpetd.js +0 -1
- package/dist/assets/smalltalk-DkLiglaE.js +0 -1
- package/dist/assets/snazzy-light-Bw305WKR.js +0 -1
- package/dist/assets/solarized-dark-DXbdFlpD.js +0 -1
- package/dist/assets/solarized-light-L9t79GZl.js +0 -1
- package/dist/assets/solidity-C1w2a3ep.js +0 -1
- package/dist/assets/soy-C-lX7w71.js +0 -1
- package/dist/assets/sparql-bYkjHRlG.js +0 -1
- package/dist/assets/splunk-Cf8iN4DR.js +0 -1
- package/dist/assets/sql-COK4E0Yg.js +0 -1
- package/dist/assets/ssh-config-BknIz3MU.js +0 -1
- package/dist/assets/stata-DorPZHa4.js +0 -1
- package/dist/assets/stylus-BeQkCIfX.js +0 -1
- package/dist/assets/svelte-MSaWC3Je.js +0 -1
- package/dist/assets/swift-BSxZ-RaX.js +0 -1
- package/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
- package/dist/assets/system-verilog-C7L56vO4.js +0 -1
- package/dist/assets/systemd-CUnW07Te.js +0 -1
- package/dist/assets/talonscript-C1XDQQGZ.js +0 -1
- package/dist/assets/tasl-CQjiPCtT.js +0 -1
- package/dist/assets/tcl-DQ1-QYvQ.js +0 -1
- package/dist/assets/templ-dwX3ZSMB.js +0 -1
- package/dist/assets/terraform-BbSNqyBO.js +0 -1
- package/dist/assets/tex-rYs2v40G.js +0 -1
- package/dist/assets/tokyo-night-DBQeEorK.js +0 -1
- package/dist/assets/toml-CB2ApiWb.js +0 -1
- package/dist/assets/ts-tags-CipyTH0X.js +0 -1
- package/dist/assets/tsv-B_m7g4N7.js +0 -1
- package/dist/assets/tsx-B6W0miNI.js +0 -1
- package/dist/assets/turtle-BMR_PYu6.js +0 -1
- package/dist/assets/twig-NC5TFiHP.js +0 -1
- package/dist/assets/typescript-Dj6nwHGl.js +0 -1
- package/dist/assets/typespec-BpWG_bgh.js +0 -1
- package/dist/assets/typst-BVUVsWT6.js +0 -1
- package/dist/assets/v-CAQ2eGtk.js +0 -1
- package/dist/assets/vala-BFOHcciG.js +0 -1
- package/dist/assets/vb-CdO5JTpU.js +0 -1
- package/dist/assets/verilog-CJaU5se_.js +0 -1
- package/dist/assets/vesper-BEBZ7ncR.js +0 -1
- package/dist/assets/vhdl-DYoNaHQp.js +0 -1
- package/dist/assets/viml-m4uW47V2.js +0 -1
- package/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
- package/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
- package/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
- package/dist/assets/vue-BuYVFjOK.js +0 -1
- package/dist/assets/vue-html-xdeiXROB.js +0 -1
- package/dist/assets/vyper-nyqBNV6O.js +0 -1
- package/dist/assets/wasm-C6j12Q_x.js +0 -1
- package/dist/assets/wasm-CG6Dc4jp.js +0 -1
- package/dist/assets/wenyan-7A4Fjokl.js +0 -1
- package/dist/assets/wgsl-CB0Krxn9.js +0 -1
- package/dist/assets/wikitext-DCE3LsBG.js +0 -1
- package/dist/assets/wolfram-C3FkfJm5.js +0 -1
- package/dist/assets/xml-e3z08dGr.js +0 -1
- package/dist/assets/xsl-Dd0NUgwM.js +0 -1
- package/dist/assets/yaml-CVw76BM1.js +0 -1
- package/dist/assets/zenscript-HnGAYVZD.js +0 -1
- package/dist/assets/zig-BVz_zdnA.js +0 -1
- package/server/app.js +0 -165
- package/server/app.test.js +0 -30
- package/server/bd.js +0 -227
- package/server/bd.test.js +0 -194
- package/server/cli/cli.test.js +0 -207
- package/server/cli/commands.integration.test.js +0 -148
- package/server/cli/commands.js +0 -285
- package/server/cli/commands.unit.test.js +0 -408
- package/server/cli/daemon.js +0 -340
- package/server/cli/daemon.test.js +0 -31
- package/server/cli/index.js +0 -135
- package/server/cli/open.js +0 -178
- package/server/cli/open.test.js +0 -26
- package/server/cli/usage.js +0 -49
- package/server/config.js +0 -36
- package/server/db.test.js +0 -169
- package/server/dolt-pool.js +0 -313
- package/server/dolt-queries.js +0 -781
- package/server/list-adapters.js +0 -421
- package/server/list-adapters.test.js +0 -208
- package/server/logging.js +0 -23
- package/server/registry-watcher.js +0 -200
- package/server/subscriptions.js +0 -299
- package/server/subscriptions.test.js +0 -128
- package/server/validators.js +0 -124
- package/server/watcher.js +0 -139
- package/server/watcher.test.js +0 -120
- package/server/ws.comments.test.js +0 -262
- package/server/ws.delete.test.js +0 -119
- package/server/ws.js +0 -1329
- package/server/ws.labels.test.js +0 -95
- package/server/ws.list-refresh.coalesce.test.js +0 -95
- package/server/ws.list-subscriptions.test.js +0 -403
- package/server/ws.mutation-window.test.js +0 -147
- package/server/ws.mutations.test.js +0 -389
- package/server/ws.test.js +0 -52
package/server/cli/usage.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Print CLI usage to a stream-like target.
|
|
3
|
-
*
|
|
4
|
-
* @param {{ write: (chunk: string) => any }} out_stream
|
|
5
|
-
*/
|
|
6
|
-
export function printUsage(out_stream) {
|
|
7
|
-
const lines = [
|
|
8
|
-
'Usage: bdui <command> [options]',
|
|
9
|
-
'',
|
|
10
|
-
'Commands:',
|
|
11
|
-
' start Start the UI server',
|
|
12
|
-
' stop Stop the UI server',
|
|
13
|
-
' restart Restart the UI server',
|
|
14
|
-
'',
|
|
15
|
-
'Options:',
|
|
16
|
-
' -h, --help Show this help message',
|
|
17
|
-
' -v, --version Show the CLI version',
|
|
18
|
-
' -d, --debug Enable debug logging',
|
|
19
|
-
' --open Open the browser after start/restart',
|
|
20
|
-
' --host <addr> Bind to a specific host (default: 127.0.0.1)',
|
|
21
|
-
' --port <num> Bind to a specific port (default: 3000)',
|
|
22
|
-
'',
|
|
23
|
-
'Environment variables:',
|
|
24
|
-
' PORT Server port (default: 3333)',
|
|
25
|
-
' HOST Bind address (default: 127.0.0.1)',
|
|
26
|
-
' BEADS_DOLT_PASSWORD Password for remote Dolt server',
|
|
27
|
-
' FILE_ATTACHMENT_BASE_URL Base URL for attach:// URIs in markdown',
|
|
28
|
-
'',
|
|
29
|
-
'Dolt modes:',
|
|
30
|
-
' Embedded (default): spawns a local dolt sql-server from .beads/embeddeddolt/',
|
|
31
|
-
' Remote server: set dolt_mode: "server" in .beads/metadata.json with',
|
|
32
|
-
' dolt_server_host, dolt_server_port, dolt_server_user, dolt_database.',
|
|
33
|
-
' Password is read from BEADS_DOLT_PASSWORD env var.',
|
|
34
|
-
'',
|
|
35
|
-
'Attachments:',
|
|
36
|
-
' Markdown content can use attach://<path> URIs for portable file references.',
|
|
37
|
-
' Set FILE_ATTACHMENT_BASE_URL to resolve them at render time.',
|
|
38
|
-
' Example: attach://bead-42/shot.png becomes',
|
|
39
|
-
' ${FILE_ATTACHMENT_BASE_URL}/bead-42/shot.png',
|
|
40
|
-
'',
|
|
41
|
-
'Issue mentions:',
|
|
42
|
-
' Use #issue-id to mention issues in markdown (e.g., #yuklar-985).',
|
|
43
|
-
' These are auto-linked to the issue detail page.',
|
|
44
|
-
''
|
|
45
|
-
];
|
|
46
|
-
for (const line of lines) {
|
|
47
|
-
out_stream.write(line + '\n');
|
|
48
|
-
}
|
|
49
|
-
}
|
package/server/config.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolve runtime configuration for the server.
|
|
6
|
-
* Notes:
|
|
7
|
-
* - `app_dir` is resolved relative to the installed package location.
|
|
8
|
-
* - `root_dir` represents the directory where the process was invoked
|
|
9
|
-
* (i.e., the current working directory) so DB resolution follows the
|
|
10
|
-
* caller's context rather than the install location.
|
|
11
|
-
*
|
|
12
|
-
* @returns {{ host: string, port: number, app_dir: string, root_dir: string, url: string }}
|
|
13
|
-
*/
|
|
14
|
-
export function getConfig() {
|
|
15
|
-
const this_file = fileURLToPath(new URL(import.meta.url));
|
|
16
|
-
const server_dir = path.dirname(this_file);
|
|
17
|
-
const package_root = path.resolve(server_dir, '..');
|
|
18
|
-
// Always reflect the directory from which the process was started
|
|
19
|
-
const root_dir = process.cwd();
|
|
20
|
-
|
|
21
|
-
let port_value = Number.parseInt(process.env.PORT || '', 10);
|
|
22
|
-
if (!Number.isFinite(port_value)) {
|
|
23
|
-
port_value = 3333;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const host_env = process.env.HOST;
|
|
27
|
-
const host_value = host_env && host_env.length > 0 ? host_env : '127.0.0.1';
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
host: host_value,
|
|
31
|
-
port: port_value,
|
|
32
|
-
app_dir: path.resolve(package_root, 'app'),
|
|
33
|
-
root_dir,
|
|
34
|
-
url: `http://${host_value}:${port_value}`
|
|
35
|
-
};
|
|
36
|
-
}
|
package/server/db.test.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
findNearestBeadsDb,
|
|
7
|
-
findNearestBeadsMetadata,
|
|
8
|
-
resolveDbPath,
|
|
9
|
-
resolveWorkspaceDatabase
|
|
10
|
-
} from './db.js';
|
|
11
|
-
|
|
12
|
-
/** @type {string[]} */
|
|
13
|
-
const tmps = [];
|
|
14
|
-
|
|
15
|
-
function mkdtemp() {
|
|
16
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'beads-ui-test-'));
|
|
17
|
-
tmps.push(dir);
|
|
18
|
-
return dir;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
vi.resetModules();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
for (const d of tmps.splice(0)) {
|
|
27
|
-
try {
|
|
28
|
-
fs.rmSync(d, { recursive: true, force: true });
|
|
29
|
-
} catch {
|
|
30
|
-
// ignore cleanup errors
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe('resolveDbPath', () => {
|
|
36
|
-
test('uses explicit_db when provided', () => {
|
|
37
|
-
const res = resolveDbPath({ cwd: '/x', explicit_db: './my.db', env: {} });
|
|
38
|
-
expect(res.path.endsWith('/x/my.db')).toBe(true);
|
|
39
|
-
expect(res.source).toBe('flag');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('uses BEADS_DB from env when set', () => {
|
|
43
|
-
const res = resolveDbPath({ cwd: '/x', env: { BEADS_DB: '/abs/env.db' } });
|
|
44
|
-
expect(res.path).toBe('/abs/env.db');
|
|
45
|
-
expect(res.source).toBe('env');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('finds nearest .beads/ui.db walking up', () => {
|
|
49
|
-
const root = mkdtemp();
|
|
50
|
-
const nested = path.join(root, 'a', 'b', 'c');
|
|
51
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
52
|
-
const beads = path.join(root, '.beads');
|
|
53
|
-
fs.mkdirSync(beads);
|
|
54
|
-
const ui_db = path.join(beads, 'ui.db');
|
|
55
|
-
fs.writeFileSync(ui_db, '');
|
|
56
|
-
|
|
57
|
-
const found = findNearestBeadsDb(nested);
|
|
58
|
-
expect(found).toBe(ui_db);
|
|
59
|
-
|
|
60
|
-
const res = resolveDbPath({ cwd: nested, env: {} });
|
|
61
|
-
expect(res.path).toBe(ui_db);
|
|
62
|
-
expect(res.source).toBe('nearest');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('falls back to ~/.beads/default.db when none found', async () => {
|
|
66
|
-
// Mock os.homedir to a deterministic location using spy
|
|
67
|
-
const home = mkdtemp();
|
|
68
|
-
vi.spyOn(os, 'homedir').mockReturnValue(home);
|
|
69
|
-
const mod = await import('./db.js');
|
|
70
|
-
const res = mod.resolveDbPath({ cwd: '/no/db/here', env: {} });
|
|
71
|
-
expect(res.path).toBe(path.join(home, '.beads', 'default.db'));
|
|
72
|
-
expect(res.source).toBe('home-default');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('treats ~/.beads/default.db as fallback, not nearest workspace db', async () => {
|
|
76
|
-
const home = mkdtemp();
|
|
77
|
-
const nested = path.join(home, 'projects', 'repo', 'deep');
|
|
78
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
79
|
-
const home_beads = path.join(home, '.beads');
|
|
80
|
-
fs.mkdirSync(home_beads, { recursive: true });
|
|
81
|
-
fs.writeFileSync(path.join(home_beads, 'default.db'), '');
|
|
82
|
-
vi.spyOn(os, 'homedir').mockReturnValue(home);
|
|
83
|
-
const mod = await import('./db.js');
|
|
84
|
-
|
|
85
|
-
const res = mod.resolveDbPath({ cwd: nested, env: {} });
|
|
86
|
-
|
|
87
|
-
expect(res.path).toBe(path.join(home, '.beads', 'default.db'));
|
|
88
|
-
expect(res.source).toBe('home-default');
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('findNearestBeadsMetadata', () => {
|
|
93
|
-
test('finds nearest metadata walking up', () => {
|
|
94
|
-
const root = mkdtemp();
|
|
95
|
-
const nested = path.join(root, 'a', 'b', 'c');
|
|
96
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
97
|
-
const beads_dir = path.join(root, '.beads');
|
|
98
|
-
fs.mkdirSync(beads_dir, { recursive: true });
|
|
99
|
-
const metadata = path.join(beads_dir, 'metadata.json');
|
|
100
|
-
fs.writeFileSync(metadata, '{}');
|
|
101
|
-
|
|
102
|
-
const found = findNearestBeadsMetadata(nested);
|
|
103
|
-
|
|
104
|
-
expect(found).toBe(metadata);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('returns null when metadata is missing', () => {
|
|
108
|
-
const root = mkdtemp();
|
|
109
|
-
|
|
110
|
-
const found = findNearestBeadsMetadata(root);
|
|
111
|
-
|
|
112
|
-
expect(found).toBeNull();
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('resolveWorkspaceDatabase', () => {
|
|
117
|
-
test('uses metadata directory for non-SQLite workspace', () => {
|
|
118
|
-
const root = mkdtemp();
|
|
119
|
-
const nested = path.join(root, 'workspace', 'nested');
|
|
120
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
121
|
-
const beads_dir = path.join(root, '.beads');
|
|
122
|
-
fs.mkdirSync(beads_dir, { recursive: true });
|
|
123
|
-
fs.writeFileSync(path.join(beads_dir, 'metadata.json'), '{}');
|
|
124
|
-
|
|
125
|
-
const found = resolveWorkspaceDatabase({ cwd: nested, env: {} });
|
|
126
|
-
|
|
127
|
-
expect(found.path).toBe(beads_dir);
|
|
128
|
-
expect(found.source).toBe('metadata');
|
|
129
|
-
expect(found.exists).toBe(true);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('prefers metadata workspace when home default db exists', async () => {
|
|
133
|
-
const home = mkdtemp();
|
|
134
|
-
const root = path.join(home, 'project');
|
|
135
|
-
const nested = path.join(root, 'workspace', 'nested');
|
|
136
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
137
|
-
const home_beads = path.join(home, '.beads');
|
|
138
|
-
fs.mkdirSync(home_beads, { recursive: true });
|
|
139
|
-
fs.writeFileSync(path.join(home_beads, 'default.db'), '');
|
|
140
|
-
const beads_dir = path.join(root, '.beads');
|
|
141
|
-
fs.mkdirSync(beads_dir, { recursive: true });
|
|
142
|
-
fs.writeFileSync(path.join(beads_dir, 'metadata.json'), '{}');
|
|
143
|
-
vi.spyOn(os, 'homedir').mockReturnValue(home);
|
|
144
|
-
const mod = await import('./db.js');
|
|
145
|
-
|
|
146
|
-
const found = mod.resolveWorkspaceDatabase({ cwd: nested, env: {} });
|
|
147
|
-
|
|
148
|
-
expect(found.path).toBe(beads_dir);
|
|
149
|
-
expect(found.source).toBe('metadata');
|
|
150
|
-
expect(found.exists).toBe(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test('prefers nearest sqlite database when present', () => {
|
|
154
|
-
const root = mkdtemp();
|
|
155
|
-
const nested = path.join(root, 'workspace', 'nested');
|
|
156
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
157
|
-
const beads_dir = path.join(root, '.beads');
|
|
158
|
-
fs.mkdirSync(beads_dir, { recursive: true });
|
|
159
|
-
fs.writeFileSync(path.join(beads_dir, 'metadata.json'), '{}');
|
|
160
|
-
const sqlite_db = path.join(beads_dir, 'workspace.db');
|
|
161
|
-
fs.writeFileSync(sqlite_db, '');
|
|
162
|
-
|
|
163
|
-
const found = resolveWorkspaceDatabase({ cwd: nested, env: {} });
|
|
164
|
-
|
|
165
|
-
expect(found.path).toBe(sqlite_db);
|
|
166
|
-
expect(found.source).toBe('nearest');
|
|
167
|
-
expect(found.exists).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
});
|
package/server/dolt-pool.js
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import mysql from 'mysql2/promise';
|
|
5
|
-
import { findNearestBeadsMetadata } from './db.js';
|
|
6
|
-
import { debug } from './logging.js';
|
|
7
|
-
|
|
8
|
-
const log = debug('dolt-pool');
|
|
9
|
-
|
|
10
|
-
const DOLT_PORT = 3307;
|
|
11
|
-
const DOLT_SOCK = '/tmp/bdui-dolt.sock';
|
|
12
|
-
|
|
13
|
-
/** @type {import('mysql2/promise').Pool | null} */
|
|
14
|
-
let pool = null;
|
|
15
|
-
|
|
16
|
-
/** @type {import('node:child_process').ChildProcess | null} */
|
|
17
|
-
let serverProcess = null;
|
|
18
|
-
|
|
19
|
-
/** @type {string | null} */
|
|
20
|
-
let currentDataDir = null;
|
|
21
|
-
|
|
22
|
-
/** @type {'embedded' | 'server' | null} */
|
|
23
|
-
let currentMode = null;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {{ mode: 'embedded', dataDir: string, database: string }} EmbeddedDoltInfo
|
|
27
|
-
* @typedef {{ mode: 'server', host: string, port: number, user: string, password: string, database: string }} ServerDoltInfo
|
|
28
|
-
* @typedef {EmbeddedDoltInfo | ServerDoltInfo} DoltInfo
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Resolve Dolt connection info from the workspace root.
|
|
33
|
-
* Walks up from cwd to find .beads/metadata.json, then returns either
|
|
34
|
-
* embedded or server connection info depending on dolt_mode.
|
|
35
|
-
*
|
|
36
|
-
* @param {string} cwd
|
|
37
|
-
* @returns {DoltInfo | null}
|
|
38
|
-
*/
|
|
39
|
-
export function resolveDoltDir(cwd) {
|
|
40
|
-
const metadataPath = findNearestBeadsMetadata(cwd);
|
|
41
|
-
if (!metadataPath) return null;
|
|
42
|
-
|
|
43
|
-
const beadsDir = path.dirname(metadataPath);
|
|
44
|
-
let metadata;
|
|
45
|
-
try {
|
|
46
|
-
metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
47
|
-
} catch {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (metadata.backend !== 'dolt' && metadata.database !== 'dolt') return null;
|
|
52
|
-
|
|
53
|
-
const database = metadata.dolt_database || 'default';
|
|
54
|
-
|
|
55
|
-
if (metadata.dolt_mode === 'server') {
|
|
56
|
-
return {
|
|
57
|
-
mode: 'server',
|
|
58
|
-
host: metadata.dolt_server_host || '127.0.0.1',
|
|
59
|
-
port: metadata.dolt_server_port || 3306,
|
|
60
|
-
user: metadata.dolt_server_user || 'root',
|
|
61
|
-
password: process.env.BEADS_DOLT_PASSWORD || '',
|
|
62
|
-
database
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const dataDir = path.join(beadsDir, 'embeddeddolt', database);
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
fs.accessSync(path.join(dataDir, '.dolt'), fs.constants.F_OK);
|
|
70
|
-
} catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return { mode: 'embedded', dataDir, database };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Start the Dolt SQL server and create a connection pool.
|
|
79
|
-
* Idempotent — returns existing pool if already running for the same dataDir.
|
|
80
|
-
*
|
|
81
|
-
* @param {string} cwd - Workspace root directory
|
|
82
|
-
* @returns {Promise<import('mysql2/promise').Pool | null>}
|
|
83
|
-
*/
|
|
84
|
-
export async function startDoltServer(cwd) {
|
|
85
|
-
const resolved = resolveDoltDir(cwd);
|
|
86
|
-
if (!resolved) {
|
|
87
|
-
log('no Dolt database found for %s', cwd);
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Server mode — connect directly, no child process
|
|
92
|
-
if (resolved.mode === 'server') {
|
|
93
|
-
const { host, port, user, password, database } = resolved;
|
|
94
|
-
|
|
95
|
-
// Already connected to this server
|
|
96
|
-
if (pool && currentMode === 'server') {
|
|
97
|
-
return pool;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
await stopDoltServer();
|
|
101
|
-
|
|
102
|
-
log('connecting to remote dolt server at %s:%d (database=%s)', host, port, database);
|
|
103
|
-
currentMode = 'server';
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
pool = await createPool({ host, port, user, password, database });
|
|
107
|
-
log('connected to remote dolt server at %s:%d', host, port);
|
|
108
|
-
ensureIndexes(pool).catch((err) => log('ensureIndexes error: %o', err));
|
|
109
|
-
return pool;
|
|
110
|
-
} catch (err) {
|
|
111
|
-
log('failed to connect to remote dolt server: %o', err);
|
|
112
|
-
pool = null;
|
|
113
|
-
currentMode = null;
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Embedded mode — spawn local dolt sql-server
|
|
119
|
-
const { dataDir, database } = resolved;
|
|
120
|
-
|
|
121
|
-
// Already running for this data dir
|
|
122
|
-
if (pool && currentDataDir === dataDir && serverProcess && !serverProcess.killed) {
|
|
123
|
-
return pool;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Clean up any previous server
|
|
127
|
-
await stopDoltServer();
|
|
128
|
-
|
|
129
|
-
log('starting dolt sql-server at %s (database=%s)', dataDir, database);
|
|
130
|
-
|
|
131
|
-
// Clean up stale socket
|
|
132
|
-
try { fs.unlinkSync(DOLT_SOCK); } catch { /* ignore */ }
|
|
133
|
-
|
|
134
|
-
currentDataDir = dataDir;
|
|
135
|
-
currentMode = 'embedded';
|
|
136
|
-
|
|
137
|
-
return new Promise((resolve) => {
|
|
138
|
-
const child = spawn('dolt', [
|
|
139
|
-
'sql-server',
|
|
140
|
-
'-P', String(DOLT_PORT),
|
|
141
|
-
'--socket', DOLT_SOCK,
|
|
142
|
-
'-l', 'warning'
|
|
143
|
-
], {
|
|
144
|
-
cwd: dataDir,
|
|
145
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
146
|
-
detached: false
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
serverProcess = child;
|
|
150
|
-
|
|
151
|
-
let resolved_already = false;
|
|
152
|
-
|
|
153
|
-
child.stderr?.setEncoding('utf8');
|
|
154
|
-
child.stderr?.on('data', (chunk) => {
|
|
155
|
-
// Log warnings/errors from dolt
|
|
156
|
-
if (chunk.trim()) log('dolt: %s', chunk.trim());
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
child.on('error', (err) => {
|
|
160
|
-
log('dolt sql-server spawn error: %o', err);
|
|
161
|
-
if (!resolved_already) {
|
|
162
|
-
resolved_already = true;
|
|
163
|
-
resolve(null);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
child.on('exit', (code) => {
|
|
168
|
-
log('dolt sql-server exited with code %d', code);
|
|
169
|
-
pool = null;
|
|
170
|
-
serverProcess = null;
|
|
171
|
-
currentDataDir = null;
|
|
172
|
-
currentMode = null;
|
|
173
|
-
if (!resolved_already) {
|
|
174
|
-
resolved_already = true;
|
|
175
|
-
resolve(null);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Poll for connectivity instead of parsing stdout
|
|
180
|
-
let attempts = 0;
|
|
181
|
-
const maxAttempts = 50; // 50 * 100ms = 5s max
|
|
182
|
-
const pollInterval = setInterval(async () => {
|
|
183
|
-
attempts++;
|
|
184
|
-
if (resolved_already) {
|
|
185
|
-
clearInterval(pollInterval);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
if (attempts > maxAttempts) {
|
|
189
|
-
clearInterval(pollInterval);
|
|
190
|
-
if (!resolved_already) {
|
|
191
|
-
resolved_already = true;
|
|
192
|
-
log('dolt sql-server start timeout after %d attempts', attempts);
|
|
193
|
-
resolve(null);
|
|
194
|
-
}
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
const p = await createPool({ host: '127.0.0.1', port: DOLT_PORT, user: 'root', database });
|
|
199
|
-
clearInterval(pollInterval);
|
|
200
|
-
if (!resolved_already) {
|
|
201
|
-
resolved_already = true;
|
|
202
|
-
pool = p;
|
|
203
|
-
log('dolt sql-server ready on port %d (after %d polls)', DOLT_PORT, attempts);
|
|
204
|
-
ensureIndexes(p).catch((err) => log('ensureIndexes error: %o', err));
|
|
205
|
-
resolve(pool);
|
|
206
|
-
} else {
|
|
207
|
-
// Pool created after we already resolved (race); close it
|
|
208
|
-
try { await p.end(); } catch { /* ignore */ }
|
|
209
|
-
}
|
|
210
|
-
} catch (poolErr) {
|
|
211
|
-
// Not ready yet, retry. Clean up any partial pool.
|
|
212
|
-
if (poolErr && typeof /** @type {any} */ (poolErr).pool?.end === 'function') {
|
|
213
|
-
try { await /** @type {any} */ (poolErr).pool.end(); } catch { /* ignore */ }
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}, 100);
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Create a mysql2 connection pool.
|
|
222
|
-
*
|
|
223
|
-
* @param {{ host: string, port: number, user: string, password?: string, database: string }} opts
|
|
224
|
-
* @returns {Promise<import('mysql2/promise').Pool>}
|
|
225
|
-
*/
|
|
226
|
-
async function createPool(opts) {
|
|
227
|
-
const p = mysql.createPool({
|
|
228
|
-
host: opts.host,
|
|
229
|
-
port: opts.port,
|
|
230
|
-
user: opts.user,
|
|
231
|
-
password: opts.password || undefined,
|
|
232
|
-
database: opts.database,
|
|
233
|
-
waitForConnections: true,
|
|
234
|
-
connectionLimit: 10,
|
|
235
|
-
queueLimit: 50,
|
|
236
|
-
enableKeepAlive: true,
|
|
237
|
-
keepAliveInitialDelay: 10000,
|
|
238
|
-
// Dolt dates come as strings; avoid extra parsing
|
|
239
|
-
dateStrings: true
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// Verify connectivity
|
|
243
|
-
const conn = await p.getConnection();
|
|
244
|
-
conn.release();
|
|
245
|
-
return p;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Ensure required indexes exist. Idempotent — skips if already present.
|
|
250
|
-
*
|
|
251
|
-
* @param {import('mysql2/promise').Pool} p
|
|
252
|
-
*/
|
|
253
|
-
async function ensureIndexes(p) {
|
|
254
|
-
const [rows] = await p.query(
|
|
255
|
-
`SELECT 1 FROM information_schema.statistics
|
|
256
|
-
WHERE table_schema = DATABASE() AND table_name = 'issues'
|
|
257
|
-
AND index_name = 'idx_ft_issues_title_desc' LIMIT 1`
|
|
258
|
-
);
|
|
259
|
-
if (/** @type {any[]} */ (rows).length > 0) {
|
|
260
|
-
log('FULLTEXT index already exists');
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
log('creating FULLTEXT index on issues(title, description)');
|
|
264
|
-
await p.query(`ALTER TABLE issues ADD FULLTEXT idx_ft_issues_title_desc (title, description)`);
|
|
265
|
-
await p.query(`CALL dolt_commit('-Am', 'add FULLTEXT index on issues(title, description)')`);
|
|
266
|
-
log('FULLTEXT index created');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Get the current pool, or null if not started.
|
|
271
|
-
*
|
|
272
|
-
* @returns {import('mysql2/promise').Pool | null}
|
|
273
|
-
*/
|
|
274
|
-
export function getPool() {
|
|
275
|
-
return pool;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Stop the Dolt SQL server and close the pool.
|
|
280
|
-
*/
|
|
281
|
-
export async function stopDoltServer() {
|
|
282
|
-
if (pool) {
|
|
283
|
-
try { await pool.end(); } catch { /* ignore */ }
|
|
284
|
-
pool = null;
|
|
285
|
-
}
|
|
286
|
-
if (serverProcess && !serverProcess.killed) {
|
|
287
|
-
serverProcess.kill('SIGTERM');
|
|
288
|
-
serverProcess = null;
|
|
289
|
-
}
|
|
290
|
-
currentDataDir = null;
|
|
291
|
-
currentMode = null;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Rebind to a new workspace directory (e.g., after workspace switch).
|
|
296
|
-
*
|
|
297
|
-
* @param {string} cwd
|
|
298
|
-
* @returns {Promise<import('mysql2/promise').Pool | null>}
|
|
299
|
-
*/
|
|
300
|
-
export async function rebindDoltServer(cwd) {
|
|
301
|
-
const resolved = resolveDoltDir(cwd);
|
|
302
|
-
if (!resolved) {
|
|
303
|
-
await stopDoltServer();
|
|
304
|
-
return null;
|
|
305
|
-
}
|
|
306
|
-
if (resolved.mode === 'server' && pool && currentMode === 'server') {
|
|
307
|
-
return pool;
|
|
308
|
-
}
|
|
309
|
-
if (resolved.mode === 'embedded' && resolved.dataDir === currentDataDir && pool && serverProcess && !serverProcess.killed) {
|
|
310
|
-
return pool;
|
|
311
|
-
}
|
|
312
|
-
return startDoltServer(cwd);
|
|
313
|
-
}
|