code-squad-cli 1.2.7 → 1.2.10
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/dist/flip/constants/filters.d.ts +2 -0
- package/dist/flip/constants/filters.js +30 -0
- package/dist/flip/events/SSEManager.d.ts +10 -0
- package/dist/flip/events/SSEManager.js +28 -0
- package/dist/flip/events/types.d.ts +11 -0
- package/dist/flip/events/types.js +1 -0
- package/dist/flip/index.js +2 -2
- package/dist/flip/output/autopaste.js +15 -3
- package/dist/flip/output/clipboard.js +56 -2
- package/dist/flip/routes/events.d.ts +3 -0
- package/dist/flip/routes/events.js +25 -0
- package/dist/flip/routes/files.d.ts +6 -1
- package/dist/flip/routes/files.js +21 -33
- package/dist/flip/routes/static.js +8 -2
- package/dist/flip/routes/submit.js +14 -7
- package/dist/flip/server/Server.d.ts +1 -1
- package/dist/flip/server/Server.js +24 -2
- package/dist/flip/watcher/FileWatcher.d.ts +29 -0
- package/dist/flip/watcher/FileWatcher.js +128 -0
- package/dist/flip-ui/dist/assets/index-B2PjDe6F.js +217 -0
- package/dist/flip-ui/dist/assets/index-DYY1gRRa.css +1 -0
- package/dist/flip-ui/dist/index.html +2 -2
- package/dist/index.js +345 -80
- package/package.json +3 -2
- package/dist/flip-ui/dist/assets/abap-BdImnpbu.js +0 -1
- package/dist/flip-ui/dist/assets/actionscript-3-CfeIJUat.js +0 -1
- package/dist/flip-ui/dist/assets/ada-bCR0ucgS.js +0 -1
- package/dist/flip-ui/dist/assets/andromeeda-C-Jbm3Hp.js +0 -1
- package/dist/flip-ui/dist/assets/angular-html-CU67Zn6k.js +0 -1
- package/dist/flip-ui/dist/assets/angular-ts-BwZT4LLn.js +0 -1
- package/dist/flip-ui/dist/assets/apache-Pmp26Uib.js +0 -1
- package/dist/flip-ui/dist/assets/apex-D8_7TLub.js +0 -1
- package/dist/flip-ui/dist/assets/apl-dKokRX4l.js +0 -1
- package/dist/flip-ui/dist/assets/applescript-Co6uUVPk.js +0 -1
- package/dist/flip-ui/dist/assets/ara-BRHolxvo.js +0 -1
- package/dist/flip-ui/dist/assets/asciidoc-Dv7Oe6Be.js +0 -1
- package/dist/flip-ui/dist/assets/asm-D_Q5rh1f.js +0 -1
- package/dist/flip-ui/dist/assets/astro-CbQHKStN.js +0 -1
- package/dist/flip-ui/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
- package/dist/flip-ui/dist/assets/awk-DMzUqQB5.js +0 -1
- package/dist/flip-ui/dist/assets/ayu-dark-CmMr59Fi.js +0 -1
- package/dist/flip-ui/dist/assets/ballerina-BFfxhgS-.js +0 -1
- package/dist/flip-ui/dist/assets/bat-BkioyH1T.js +0 -1
- package/dist/flip-ui/dist/assets/beancount-k_qm7-4y.js +0 -1
- package/dist/flip-ui/dist/assets/berry-uYugtg8r.js +0 -1
- package/dist/flip-ui/dist/assets/bibtex-CHM0blh-.js +0 -1
- package/dist/flip-ui/dist/assets/bicep-Bmn6On1c.js +0 -1
- package/dist/flip-ui/dist/assets/blade-D4QpJJKB.js +0 -1
- package/dist/flip-ui/dist/assets/bsl-BO_Y6i37.js +0 -1
- package/dist/flip-ui/dist/assets/c-BIGW1oBm.js +0 -1
- package/dist/flip-ui/dist/assets/c3-VCDPK7BO.js +0 -1
- package/dist/flip-ui/dist/assets/cadence-Bv_4Rxtq.js +0 -1
- package/dist/flip-ui/dist/assets/cairo-KRGpt6FW.js +0 -1
- package/dist/flip-ui/dist/assets/catppuccin-frappe-DFWUc33u.js +0 -1
- package/dist/flip-ui/dist/assets/catppuccin-latte-C9dUb6Cb.js +0 -1
- package/dist/flip-ui/dist/assets/catppuccin-macchiato-DQyhUUbL.js +0 -1
- package/dist/flip-ui/dist/assets/catppuccin-mocha-D87Tk5Gz.js +0 -1
- package/dist/flip-ui/dist/assets/clarity-D53aC0YG.js +0 -1
- package/dist/flip-ui/dist/assets/clojure-P80f7IUj.js +0 -1
- package/dist/flip-ui/dist/assets/cmake-D1j8_8rp.js +0 -1
- package/dist/flip-ui/dist/assets/cobol-nwyudZeR.js +0 -1
- package/dist/flip-ui/dist/assets/codeowners-Bp6g37R7.js +0 -1
- package/dist/flip-ui/dist/assets/codeql-DsOJ9woJ.js +0 -1
- package/dist/flip-ui/dist/assets/coffee-Ch7k5sss.js +0 -1
- package/dist/flip-ui/dist/assets/common-lisp-Cg-RD9OK.js +0 -1
- package/dist/flip-ui/dist/assets/coq-DkFqJrB1.js +0 -1
- package/dist/flip-ui/dist/assets/cpp-CofmeUqb.js +0 -1
- package/dist/flip-ui/dist/assets/crystal-tKQVLTB8.js +0 -1
- package/dist/flip-ui/dist/assets/csharp-K5feNrxe.js +0 -1
- package/dist/flip-ui/dist/assets/css-DPfMkruS.js +0 -1
- package/dist/flip-ui/dist/assets/csv-fuZLfV_i.js +0 -1
- package/dist/flip-ui/dist/assets/cue-D82EKSYY.js +0 -1
- package/dist/flip-ui/dist/assets/cypher-COkxafJQ.js +0 -1
- package/dist/flip-ui/dist/assets/d-85-TOEBH.js +0 -1
- package/dist/flip-ui/dist/assets/dark-plus-C3mMm8J8.js +0 -1
- package/dist/flip-ui/dist/assets/dart-CF10PKvl.js +0 -1
- package/dist/flip-ui/dist/assets/dax-CEL-wOlO.js +0 -1
- package/dist/flip-ui/dist/assets/desktop-BmXAJ9_W.js +0 -1
- package/dist/flip-ui/dist/assets/diff-D97Zzqfu.js +0 -1
- package/dist/flip-ui/dist/assets/docker-BcOcwvcX.js +0 -1
- package/dist/flip-ui/dist/assets/dotenv-Da5cRb03.js +0 -1
- package/dist/flip-ui/dist/assets/dracula-BzJJZx-M.js +0 -1
- package/dist/flip-ui/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
- package/dist/flip-ui/dist/assets/dream-maker-BtqSS_iP.js +0 -1
- package/dist/flip-ui/dist/assets/edge-BkV0erSs.js +0 -1
- package/dist/flip-ui/dist/assets/elixir-CDX3lj18.js +0 -1
- package/dist/flip-ui/dist/assets/elm-DbKCFpqz.js +0 -1
- package/dist/flip-ui/dist/assets/emacs-lisp-C9XAeP06.js +0 -1
- package/dist/flip-ui/dist/assets/erb-BOJIQeun.js +0 -1
- package/dist/flip-ui/dist/assets/erlang-DsQrWhSR.js +0 -1
- package/dist/flip-ui/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
- package/dist/flip-ui/dist/assets/everforest-light-C8M2exoo.js +0 -1
- package/dist/flip-ui/dist/assets/fennel-BYunw83y.js +0 -1
- package/dist/flip-ui/dist/assets/fish-BvzEVeQv.js +0 -1
- package/dist/flip-ui/dist/assets/fluent-C4IJs8-o.js +0 -1
- package/dist/flip-ui/dist/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
- package/dist/flip-ui/dist/assets/fortran-free-form-BxgE0vQu.js +0 -1
- package/dist/flip-ui/dist/assets/fsharp-CXgrBDvD.js +0 -1
- package/dist/flip-ui/dist/assets/gdresource-B7Tvp0Sc.js +0 -1
- package/dist/flip-ui/dist/assets/gdscript-DTMYz4Jt.js +0 -1
- package/dist/flip-ui/dist/assets/gdshader-DkwncUOv.js +0 -1
- package/dist/flip-ui/dist/assets/genie-D0YGMca9.js +0 -1
- package/dist/flip-ui/dist/assets/gherkin-DyxjwDmM.js +0 -1
- package/dist/flip-ui/dist/assets/git-commit-F4YmCXRG.js +0 -1
- package/dist/flip-ui/dist/assets/git-rebase-r7XF79zn.js +0 -1
- package/dist/flip-ui/dist/assets/github-dark-DHJKELXO.js +0 -1
- package/dist/flip-ui/dist/assets/github-dark-default-Cuk6v7N8.js +0 -1
- package/dist/flip-ui/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
- package/dist/flip-ui/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
- package/dist/flip-ui/dist/assets/github-light-DAi9KRSo.js +0 -1
- package/dist/flip-ui/dist/assets/github-light-default-D7oLnXFd.js +0 -1
- package/dist/flip-ui/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
- package/dist/flip-ui/dist/assets/gleam-BspZqrRM.js +0 -1
- package/dist/flip-ui/dist/assets/glimmer-js-Rg0-pVw9.js +0 -1
- package/dist/flip-ui/dist/assets/glimmer-ts-U6CK756n.js +0 -1
- package/dist/flip-ui/dist/assets/glsl-DplSGwfg.js +0 -1
- package/dist/flip-ui/dist/assets/gn-n2N0HUVH.js +0 -1
- package/dist/flip-ui/dist/assets/gnuplot-DdkO51Og.js +0 -1
- package/dist/flip-ui/dist/assets/go-Dn2_MT6a.js +0 -1
- package/dist/flip-ui/dist/assets/graphql-ChdNCCLP.js +0 -1
- package/dist/flip-ui/dist/assets/groovy-gcz8RCvz.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
- package/dist/flip-ui/dist/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
- package/dist/flip-ui/dist/assets/hack-CaT9iCJl.js +0 -1
- package/dist/flip-ui/dist/assets/haml-B8DHNrY2.js +0 -1
- package/dist/flip-ui/dist/assets/handlebars-BL8al0AC.js +0 -1
- package/dist/flip-ui/dist/assets/haskell-Df6bDoY_.js +0 -1
- package/dist/flip-ui/dist/assets/haxe-CzTSHFRz.js +0 -1
- package/dist/flip-ui/dist/assets/hcl-BWvSN4gD.js +0 -1
- package/dist/flip-ui/dist/assets/hjson-D5-asLiD.js +0 -1
- package/dist/flip-ui/dist/assets/hlsl-D3lLCCz7.js +0 -1
- package/dist/flip-ui/dist/assets/houston-DnULxvSX.js +0 -1
- package/dist/flip-ui/dist/assets/html-GMplVEZG.js +0 -1
- package/dist/flip-ui/dist/assets/html-derivative-BFtXZ54Q.js +0 -1
- package/dist/flip-ui/dist/assets/http-jrhK8wxY.js +0 -1
- package/dist/flip-ui/dist/assets/hurl-irOxFIW8.js +0 -1
- package/dist/flip-ui/dist/assets/hxml-Bvhsp5Yf.js +0 -1
- package/dist/flip-ui/dist/assets/hy-DFXneXwc.js +0 -1
- package/dist/flip-ui/dist/assets/imba-DGztddWO.js +0 -1
- package/dist/flip-ui/dist/assets/index-BYcwO1DZ.js +0 -154
- package/dist/flip-ui/dist/assets/index-iFjjtGMT.css +0 -1
- package/dist/flip-ui/dist/assets/ini-BEwlwnbL.js +0 -1
- package/dist/flip-ui/dist/assets/java-CylS5w8V.js +0 -1
- package/dist/flip-ui/dist/assets/javascript-wDzz0qaB.js +0 -1
- package/dist/flip-ui/dist/assets/jinja-4LBKfQ-Z.js +0 -1
- package/dist/flip-ui/dist/assets/jison-wvAkD_A8.js +0 -1
- package/dist/flip-ui/dist/assets/json-Cp-IABpG.js +0 -1
- package/dist/flip-ui/dist/assets/json5-C9tS-k6U.js +0 -1
- package/dist/flip-ui/dist/assets/jsonc-Des-eS-w.js +0 -1
- package/dist/flip-ui/dist/assets/jsonl-DcaNXYhu.js +0 -1
- package/dist/flip-ui/dist/assets/jsonnet-DFQXde-d.js +0 -1
- package/dist/flip-ui/dist/assets/jssm-C2t-YnRu.js +0 -1
- package/dist/flip-ui/dist/assets/jsx-g9-lgVsj.js +0 -1
- package/dist/flip-ui/dist/assets/julia-CxzCAyBv.js +0 -1
- package/dist/flip-ui/dist/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
- package/dist/flip-ui/dist/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
- package/dist/flip-ui/dist/assets/kanagawa-wave-DWedfzmr.js +0 -1
- package/dist/flip-ui/dist/assets/kdl-DV7GczEv.js +0 -1
- package/dist/flip-ui/dist/assets/kotlin-BdnUsdx6.js +0 -1
- package/dist/flip-ui/dist/assets/kusto-DZf3V79B.js +0 -1
- package/dist/flip-ui/dist/assets/laserwave-DUszq2jm.js +0 -1
- package/dist/flip-ui/dist/assets/latex-B4uzh10-.js +0 -1
- package/dist/flip-ui/dist/assets/lean-BZvkOJ9d.js +0 -1
- package/dist/flip-ui/dist/assets/less-B1dDrJ26.js +0 -1
- package/dist/flip-ui/dist/assets/light-plus-B7mTdjB0.js +0 -1
- package/dist/flip-ui/dist/assets/liquid-DYVedYrR.js +0 -1
- package/dist/flip-ui/dist/assets/llvm-BtvRca6l.js +0 -1
- package/dist/flip-ui/dist/assets/log-2UxHyX5q.js +0 -1
- package/dist/flip-ui/dist/assets/logo-BtOb2qkB.js +0 -1
- package/dist/flip-ui/dist/assets/lua-BbnMAYS6.js +0 -1
- package/dist/flip-ui/dist/assets/luau-C-HG3fhB.js +0 -1
- package/dist/flip-ui/dist/assets/make-CHLpvVh8.js +0 -1
- package/dist/flip-ui/dist/assets/markdown-Cvjx9yec.js +0 -1
- package/dist/flip-ui/dist/assets/marko-DZsq8hO1.js +0 -1
- package/dist/flip-ui/dist/assets/material-theme-D5KoaKCx.js +0 -1
- package/dist/flip-ui/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
- package/dist/flip-ui/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
- package/dist/flip-ui/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
- package/dist/flip-ui/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
- package/dist/flip-ui/dist/assets/matlab-D7o27uSR.js +0 -1
- package/dist/flip-ui/dist/assets/mdc-DUICxH0z.js +0 -1
- package/dist/flip-ui/dist/assets/mdx-Cmh6b_Ma.js +0 -1
- package/dist/flip-ui/dist/assets/mermaid-mWjccvbQ.js +0 -1
- package/dist/flip-ui/dist/assets/min-dark-CafNBF8u.js +0 -1
- package/dist/flip-ui/dist/assets/min-light-CTRr51gU.js +0 -1
- package/dist/flip-ui/dist/assets/mipsasm-CKIfxQSi.js +0 -1
- package/dist/flip-ui/dist/assets/mojo-B93PlW-d.js +0 -1
- package/dist/flip-ui/dist/assets/monokai-D4h5O-jR.js +0 -1
- package/dist/flip-ui/dist/assets/moonbit-Ba13S78F.js +0 -1
- package/dist/flip-ui/dist/assets/move-Bu9oaDYs.js +0 -1
- package/dist/flip-ui/dist/assets/narrat-DRg8JJMk.js +0 -1
- package/dist/flip-ui/dist/assets/nextflow-BrzmwbiE.js +0 -1
- package/dist/flip-ui/dist/assets/nginx-DknmC5AR.js +0 -1
- package/dist/flip-ui/dist/assets/night-owl-C39BiMTA.js +0 -1
- package/dist/flip-ui/dist/assets/nim-CVrawwO9.js +0 -1
- package/dist/flip-ui/dist/assets/nix-CwoSXNpI.js +0 -1
- package/dist/flip-ui/dist/assets/nord-Ddv68eIx.js +0 -1
- package/dist/flip-ui/dist/assets/nushell-C-sUppwS.js +0 -1
- package/dist/flip-ui/dist/assets/objective-c-DXmwc3jG.js +0 -1
- package/dist/flip-ui/dist/assets/objective-cpp-CLxacb5B.js +0 -1
- package/dist/flip-ui/dist/assets/ocaml-C0hk2d4L.js +0 -1
- package/dist/flip-ui/dist/assets/one-dark-pro-DVMEJ2y_.js +0 -1
- package/dist/flip-ui/dist/assets/one-light-PoHY5YXO.js +0 -1
- package/dist/flip-ui/dist/assets/openscad-C4EeE6gA.js +0 -1
- package/dist/flip-ui/dist/assets/pascal-D93ZcfNL.js +0 -1
- package/dist/flip-ui/dist/assets/perl-C0TMdlhV.js +0 -1
- package/dist/flip-ui/dist/assets/php-CDn_0X-4.js +0 -1
- package/dist/flip-ui/dist/assets/pkl-u5AG7uiY.js +0 -1
- package/dist/flip-ui/dist/assets/plastic-3e1v2bzS.js +0 -1
- package/dist/flip-ui/dist/assets/plsql-ChMvpjG-.js +0 -1
- package/dist/flip-ui/dist/assets/po-BTJTHyun.js +0 -1
- package/dist/flip-ui/dist/assets/poimandres-CS3Unz2-.js +0 -1
- package/dist/flip-ui/dist/assets/polar-C0HS_06l.js +0 -1
- package/dist/flip-ui/dist/assets/postcss-CXtECtnM.js +0 -1
- package/dist/flip-ui/dist/assets/powerquery-CEu0bR-o.js +0 -1
- package/dist/flip-ui/dist/assets/powershell-Dpen1YoG.js +0 -1
- package/dist/flip-ui/dist/assets/prisma-Dd19v3D-.js +0 -1
- package/dist/flip-ui/dist/assets/prolog-CbFg5uaA.js +0 -1
- package/dist/flip-ui/dist/assets/proto-C7zT0LnQ.js +0 -1
- package/dist/flip-ui/dist/assets/pug-CGlum2m_.js +0 -1
- package/dist/flip-ui/dist/assets/puppet-BMWR74SV.js +0 -1
- package/dist/flip-ui/dist/assets/purescript-CklMAg4u.js +0 -1
- package/dist/flip-ui/dist/assets/python-B6aJPvgy.js +0 -1
- package/dist/flip-ui/dist/assets/qml-3beO22l8.js +0 -1
- package/dist/flip-ui/dist/assets/qmldir-C8lEn-DE.js +0 -1
- package/dist/flip-ui/dist/assets/qss-IeuSbFQv.js +0 -1
- package/dist/flip-ui/dist/assets/r-Dspwwk_N.js +0 -1
- package/dist/flip-ui/dist/assets/racket-BqYA7rlc.js +0 -1
- package/dist/flip-ui/dist/assets/raku-DXvB9xmW.js +0 -1
- package/dist/flip-ui/dist/assets/razor-C1TweQQi.js +0 -1
- package/dist/flip-ui/dist/assets/red-bN70gL4F.js +0 -1
- package/dist/flip-ui/dist/assets/reg-C-SQnVFl.js +0 -1
- package/dist/flip-ui/dist/assets/regexp-CDVJQ6XC.js +0 -1
- package/dist/flip-ui/dist/assets/rel-C3B-1QV4.js +0 -1
- package/dist/flip-ui/dist/assets/riscv-BM1_JUlF.js +0 -1
- package/dist/flip-ui/dist/assets/rose-pine-dawn-DHQR4-dF.js +0 -1
- package/dist/flip-ui/dist/assets/rose-pine-moon-D4_iv3hh.js +0 -1
- package/dist/flip-ui/dist/assets/rose-pine-qdsjHGoJ.js +0 -1
- package/dist/flip-ui/dist/assets/rosmsg-BJDFO7_C.js +0 -1
- package/dist/flip-ui/dist/assets/rst-B0xPkSld.js +0 -1
- package/dist/flip-ui/dist/assets/ruby-BvKwtOVI.js +0 -1
- package/dist/flip-ui/dist/assets/rust-B1yitclQ.js +0 -1
- package/dist/flip-ui/dist/assets/sas-cz2c8ADy.js +0 -1
- package/dist/flip-ui/dist/assets/sass-Cj5Yp3dK.js +0 -1
- package/dist/flip-ui/dist/assets/scala-C151Ov-r.js +0 -1
- package/dist/flip-ui/dist/assets/scheme-C98Dy4si.js +0 -1
- package/dist/flip-ui/dist/assets/scss-OYdSNvt2.js +0 -1
- package/dist/flip-ui/dist/assets/sdbl-DVxCFoDh.js +0 -1
- package/dist/flip-ui/dist/assets/shaderlab-Dg9Lc6iA.js +0 -1
- package/dist/flip-ui/dist/assets/shellscript-Yzrsuije.js +0 -1
- package/dist/flip-ui/dist/assets/shellsession-BADoaaVG.js +0 -1
- package/dist/flip-ui/dist/assets/slack-dark-BthQWCQV.js +0 -1
- package/dist/flip-ui/dist/assets/slack-ochin-DqwNpetd.js +0 -1
- package/dist/flip-ui/dist/assets/smalltalk-BERRCDM3.js +0 -1
- package/dist/flip-ui/dist/assets/snazzy-light-Bw305WKR.js +0 -1
- package/dist/flip-ui/dist/assets/solarized-dark-DXbdFlpD.js +0 -1
- package/dist/flip-ui/dist/assets/solarized-light-L9t79GZl.js +0 -1
- package/dist/flip-ui/dist/assets/solidity-rGO070M0.js +0 -1
- package/dist/flip-ui/dist/assets/soy-Brmx7dQM.js +0 -1
- package/dist/flip-ui/dist/assets/sparql-rVzFXLq3.js +0 -1
- package/dist/flip-ui/dist/assets/splunk-BtCnVYZw.js +0 -1
- package/dist/flip-ui/dist/assets/sql-BLtJtn59.js +0 -1
- package/dist/flip-ui/dist/assets/ssh-config-_ykCGR6B.js +0 -1
- package/dist/flip-ui/dist/assets/stata-BH5u7GGu.js +0 -1
- package/dist/flip-ui/dist/assets/stylus-BEDo0Tqx.js +0 -1
- package/dist/flip-ui/dist/assets/svelte-zxCyuUbr.js +0 -1
- package/dist/flip-ui/dist/assets/swift-Dg5xB15N.js +0 -1
- package/dist/flip-ui/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
- package/dist/flip-ui/dist/assets/system-verilog-CnnmHF94.js +0 -1
- package/dist/flip-ui/dist/assets/systemd-4A_iFExJ.js +0 -1
- package/dist/flip-ui/dist/assets/talonscript-CkByrt1z.js +0 -1
- package/dist/flip-ui/dist/assets/tasl-QIJgUcNo.js +0 -1
- package/dist/flip-ui/dist/assets/tcl-dwOrl1Do.js +0 -1
- package/dist/flip-ui/dist/assets/templ-W15q3VgB.js +0 -1
- package/dist/flip-ui/dist/assets/terraform-BETggiCN.js +0 -1
- package/dist/flip-ui/dist/assets/tex-CvyZ59Mk.js +0 -1
- package/dist/flip-ui/dist/assets/tokyo-night-hegEt444.js +0 -1
- package/dist/flip-ui/dist/assets/toml-vGWfd6FD.js +0 -1
- package/dist/flip-ui/dist/assets/ts-tags-zn1MmPIZ.js +0 -1
- package/dist/flip-ui/dist/assets/tsv-B_m7g4N7.js +0 -1
- package/dist/flip-ui/dist/assets/tsx-COt5Ahok.js +0 -1
- package/dist/flip-ui/dist/assets/turtle-BsS91CYL.js +0 -1
- package/dist/flip-ui/dist/assets/twig-CO9l9SDP.js +0 -1
- package/dist/flip-ui/dist/assets/typescript-BPQ3VLAy.js +0 -1
- package/dist/flip-ui/dist/assets/typespec-BGHnOYBU.js +0 -1
- package/dist/flip-ui/dist/assets/typst-DHCkPAjA.js +0 -1
- package/dist/flip-ui/dist/assets/v-BcVCzyr7.js +0 -1
- package/dist/flip-ui/dist/assets/vala-CsfeWuGM.js +0 -1
- package/dist/flip-ui/dist/assets/vb-D17OF-Vu.js +0 -1
- package/dist/flip-ui/dist/assets/verilog-BQ8w6xss.js +0 -1
- package/dist/flip-ui/dist/assets/vesper-DU1UobuO.js +0 -1
- package/dist/flip-ui/dist/assets/vhdl-CeAyd5Ju.js +0 -1
- package/dist/flip-ui/dist/assets/viml-CJc9bBzg.js +0 -1
- package/dist/flip-ui/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
- package/dist/flip-ui/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
- package/dist/flip-ui/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
- package/dist/flip-ui/dist/assets/vue-DN_0RTcg.js +0 -1
- package/dist/flip-ui/dist/assets/vue-html-AaS7Mt5G.js +0 -1
- package/dist/flip-ui/dist/assets/vue-vine-CQOfvN7w.js +0 -1
- package/dist/flip-ui/dist/assets/vyper-CDx5xZoG.js +0 -1
- package/dist/flip-ui/dist/assets/wasm-CG6Dc4jp.js +0 -1
- package/dist/flip-ui/dist/assets/wasm-MzD3tlZU.js +0 -1
- package/dist/flip-ui/dist/assets/wenyan-BV7otONQ.js +0 -1
- package/dist/flip-ui/dist/assets/wgsl-Dx-B1_4e.js +0 -1
- package/dist/flip-ui/dist/assets/wikitext-BhOHFoWU.js +0 -1
- package/dist/flip-ui/dist/assets/wit-5i3qLPDT.js +0 -1
- package/dist/flip-ui/dist/assets/wolfram-lXgVvXCa.js +0 -1
- package/dist/flip-ui/dist/assets/xml-sdJ4AIDG.js +0 -1
- package/dist/flip-ui/dist/assets/xsl-CtQFsRM5.js +0 -1
- package/dist/flip-ui/dist/assets/yaml-Buea-lGh.js +0 -1
- package/dist/flip-ui/dist/assets/zenscript-DVFEvuxE.js +0 -1
- package/dist/flip-ui/dist/assets/zig-VOosw3JB.js +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Patterns to filter for performance (O(1) lookup with Set)
|
|
2
|
+
// These are system directories that users don't directly edit
|
|
3
|
+
export const FILTERED_PATTERNS = new Set([
|
|
4
|
+
// Package managers
|
|
5
|
+
'node_modules',
|
|
6
|
+
'vendor',
|
|
7
|
+
'.pnpm-store',
|
|
8
|
+
// VCS internal
|
|
9
|
+
'.git',
|
|
10
|
+
'.svn',
|
|
11
|
+
'.hg',
|
|
12
|
+
// OS metadata
|
|
13
|
+
'.DS_Store',
|
|
14
|
+
'Thumbs.db',
|
|
15
|
+
// Build output
|
|
16
|
+
'dist',
|
|
17
|
+
'build',
|
|
18
|
+
'out',
|
|
19
|
+
// Cache directories
|
|
20
|
+
'.cache',
|
|
21
|
+
'.next',
|
|
22
|
+
'.nuxt',
|
|
23
|
+
'coverage',
|
|
24
|
+
'__pycache__',
|
|
25
|
+
'.pytest_cache',
|
|
26
|
+
'target',
|
|
27
|
+
]);
|
|
28
|
+
export function isFiltered(name) {
|
|
29
|
+
return FILTERED_PATTERNS.has(name);
|
|
30
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { SyncEvent } from './types.js';
|
|
3
|
+
export declare class SSEManager {
|
|
4
|
+
private clients;
|
|
5
|
+
addClient(res: Response): void;
|
|
6
|
+
removeClient(res: Response): void;
|
|
7
|
+
broadcast(event: SyncEvent): void;
|
|
8
|
+
closeAll(): void;
|
|
9
|
+
get clientCount(): number;
|
|
10
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class SSEManager {
|
|
2
|
+
clients = new Set();
|
|
3
|
+
addClient(res) {
|
|
4
|
+
this.clients.add(res);
|
|
5
|
+
res.on('close', () => {
|
|
6
|
+
this.clients.delete(res);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
removeClient(res) {
|
|
10
|
+
this.clients.delete(res);
|
|
11
|
+
}
|
|
12
|
+
broadcast(event) {
|
|
13
|
+
const data = JSON.stringify(event);
|
|
14
|
+
const message = `data: ${data}\n\n`;
|
|
15
|
+
this.clients.forEach(client => {
|
|
16
|
+
client.write(message);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
closeAll() {
|
|
20
|
+
this.clients.forEach(client => {
|
|
21
|
+
client.end();
|
|
22
|
+
});
|
|
23
|
+
this.clients.clear();
|
|
24
|
+
}
|
|
25
|
+
get clientCount() {
|
|
26
|
+
return this.clients.size;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type FilesChangeEvent = {
|
|
2
|
+
type: 'files-changed';
|
|
3
|
+
};
|
|
4
|
+
export type FileContentEvent = {
|
|
5
|
+
type: 'file-changed';
|
|
6
|
+
path: string;
|
|
7
|
+
};
|
|
8
|
+
export type GitChangeEvent = {
|
|
9
|
+
type: 'git-changed';
|
|
10
|
+
};
|
|
11
|
+
export type SyncEvent = FilesChangeEvent | FileContentEvent | GitChangeEvent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/flip/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import fs from 'fs';
|
|
|
5
5
|
import os from 'os';
|
|
6
6
|
import { execSync } from 'child_process';
|
|
7
7
|
import { confirm } from '@inquirer/prompts';
|
|
8
|
-
import
|
|
8
|
+
import { copyToClipboard } from './output/clipboard.js';
|
|
9
9
|
const DEFAULT_PORT = 51234;
|
|
10
10
|
function formatTime() {
|
|
11
11
|
const now = new Date();
|
|
@@ -226,7 +226,7 @@ osascript ${applescriptPath} > /dev/null 2>&1
|
|
|
226
226
|
console.log('└─────────────────────────────────────────────────┘');
|
|
227
227
|
console.log('');
|
|
228
228
|
// Copy path to clipboard
|
|
229
|
-
await
|
|
229
|
+
await copyToClipboard(shPath);
|
|
230
230
|
console.log(`✓ Copied to clipboard: ${shPath}`);
|
|
231
231
|
console.log('');
|
|
232
232
|
await confirm({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import os from 'os';
|
|
@@ -70,9 +70,21 @@ async function pasteToOriginalSession(sessionId) {
|
|
|
70
70
|
`;
|
|
71
71
|
}
|
|
72
72
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// Write script to temp file and execute via detached process
|
|
74
|
+
const tmpScript = path.join(os.tmpdir(), `flip-paste-${Date.now()}.scpt`);
|
|
75
|
+
fs.writeFileSync(tmpScript, script);
|
|
76
|
+
const child = spawn('osascript', [tmpScript], {
|
|
77
|
+
detached: true,
|
|
78
|
+
stdio: 'ignore',
|
|
75
79
|
});
|
|
80
|
+
child.unref();
|
|
81
|
+
// Schedule cleanup
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
try {
|
|
84
|
+
fs.unlinkSync(tmpScript);
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}, 5000);
|
|
76
88
|
}
|
|
77
89
|
catch (e) {
|
|
78
90
|
console.error('Failed to paste to iTerm:', e);
|
|
@@ -1,7 +1,61 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
2
5
|
/**
|
|
3
6
|
* Copy text to system clipboard
|
|
4
7
|
*/
|
|
5
8
|
export async function copyToClipboard(text) {
|
|
6
|
-
|
|
9
|
+
if (process.platform === 'darwin') {
|
|
10
|
+
// Write to temp file first, then use pbcopy via shell
|
|
11
|
+
const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
|
|
12
|
+
try {
|
|
13
|
+
fs.writeFileSync(tmpFile, text);
|
|
14
|
+
// Use a detached process to avoid EBADF
|
|
15
|
+
const child = spawn('sh', ['-c', `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`], {
|
|
16
|
+
detached: true,
|
|
17
|
+
stdio: 'ignore',
|
|
18
|
+
});
|
|
19
|
+
child.unref();
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
// Fallback: just leave the file for manual copy
|
|
23
|
+
console.log(`Output saved to: ${tmpFile}`);
|
|
24
|
+
throw e;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (process.platform === 'linux') {
|
|
28
|
+
const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
|
|
29
|
+
fs.writeFileSync(tmpFile, text);
|
|
30
|
+
try {
|
|
31
|
+
const child = spawn('sh', ['-c', `cat "${tmpFile}" | xclip -selection clipboard && rm "${tmpFile}"`], {
|
|
32
|
+
detached: true,
|
|
33
|
+
stdio: 'ignore',
|
|
34
|
+
});
|
|
35
|
+
child.unref();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
try {
|
|
39
|
+
const child = spawn('sh', ['-c', `cat "${tmpFile}" | xsel --clipboard --input && rm "${tmpFile}"`], {
|
|
40
|
+
detached: true,
|
|
41
|
+
stdio: 'ignore',
|
|
42
|
+
});
|
|
43
|
+
child.unref();
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// Final fallback if both xclip and xsel fail
|
|
47
|
+
console.log(`Output saved to: ${tmpFile}`);
|
|
48
|
+
throw e;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (process.platform === 'win32') {
|
|
53
|
+
const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
|
|
54
|
+
fs.writeFileSync(tmpFile, text);
|
|
55
|
+
const child = spawn('cmd', ['/c', `type "${tmpFile}" | clip && del "${tmpFile}"`], {
|
|
56
|
+
detached: true,
|
|
57
|
+
stdio: 'ignore',
|
|
58
|
+
});
|
|
59
|
+
child.unref();
|
|
60
|
+
}
|
|
7
61
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
export function createEventsRouter(sseManager) {
|
|
3
|
+
const router = Router();
|
|
4
|
+
// GET /api/events - SSE endpoint for real-time updates
|
|
5
|
+
router.get('/', (req, res) => {
|
|
6
|
+
// Set SSE headers
|
|
7
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
8
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
9
|
+
res.setHeader('Connection', 'keep-alive');
|
|
10
|
+
res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
|
|
11
|
+
// Send initial connection message
|
|
12
|
+
res.write('data: {"type":"connected"}\n\n');
|
|
13
|
+
// Register client
|
|
14
|
+
sseManager.addClient(res);
|
|
15
|
+
// Keep connection alive with heartbeat
|
|
16
|
+
const heartbeat = setInterval(() => {
|
|
17
|
+
res.write(':heartbeat\n\n');
|
|
18
|
+
}, 30000);
|
|
19
|
+
// Cleanup on close (removeClient is handled by SSEManager)
|
|
20
|
+
req.on('close', () => {
|
|
21
|
+
clearInterval(heartbeat);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
return router;
|
|
25
|
+
}
|
|
@@ -10,9 +10,14 @@ export interface FilesResponse {
|
|
|
10
10
|
root: string;
|
|
11
11
|
tree: FileNode[];
|
|
12
12
|
}
|
|
13
|
+
export interface FileWithMtime {
|
|
14
|
+
path: string;
|
|
15
|
+
mtime: number;
|
|
16
|
+
}
|
|
13
17
|
export interface FlatFilesResponse {
|
|
14
|
-
files:
|
|
18
|
+
files: FileWithMtime[];
|
|
15
19
|
filteredDirs: string[];
|
|
20
|
+
recentFile: string | null;
|
|
16
21
|
}
|
|
17
22
|
declare const router: IRouter;
|
|
18
23
|
export { router as filesRouter };
|
|
@@ -1,36 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
|
|
5
|
-
// These are system directories that users don't directly edit
|
|
6
|
-
const FILTERED_PATTERNS = new Set([
|
|
7
|
-
// Package managers
|
|
8
|
-
'node_modules',
|
|
9
|
-
'vendor',
|
|
10
|
-
'.pnpm-store',
|
|
11
|
-
// VCS internal
|
|
12
|
-
'.git',
|
|
13
|
-
'.svn',
|
|
14
|
-
'.hg',
|
|
15
|
-
// OS metadata
|
|
16
|
-
'.DS_Store',
|
|
17
|
-
'Thumbs.db',
|
|
18
|
-
// Build output
|
|
19
|
-
'dist',
|
|
20
|
-
'build',
|
|
21
|
-
'out',
|
|
22
|
-
// Cache directories
|
|
23
|
-
'.cache',
|
|
24
|
-
'.next',
|
|
25
|
-
'.nuxt',
|
|
26
|
-
'coverage',
|
|
27
|
-
'__pycache__',
|
|
28
|
-
'.pytest_cache',
|
|
29
|
-
'target',
|
|
30
|
-
]);
|
|
31
|
-
function isFiltered(name) {
|
|
32
|
-
return FILTERED_PATTERNS.has(name);
|
|
33
|
-
}
|
|
4
|
+
import { isFiltered } from '../constants/filters.js';
|
|
34
5
|
const router = Router();
|
|
35
6
|
function buildFileTree(rootPath, currentPath, maxDepth, depth = 0) {
|
|
36
7
|
if (depth > maxDepth)
|
|
@@ -78,7 +49,16 @@ function collectFlatFiles(rootPath, currentPath, maxDepth, depth = 0, result = {
|
|
|
78
49
|
continue; // Don't traverse filtered directories
|
|
79
50
|
}
|
|
80
51
|
if (entry.isFile()) {
|
|
81
|
-
|
|
52
|
+
try {
|
|
53
|
+
const stat = fs.statSync(fullPath);
|
|
54
|
+
result.files.push({
|
|
55
|
+
path: relativePath,
|
|
56
|
+
mtime: stat.mtimeMs,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Skip files that can't be stat'd
|
|
61
|
+
}
|
|
82
62
|
}
|
|
83
63
|
else if (entry.isDirectory()) {
|
|
84
64
|
collectFlatFiles(rootPath, fullPath, maxDepth, depth + 1, result);
|
|
@@ -96,15 +76,23 @@ router.get('/', (req, res) => {
|
|
|
96
76
|
};
|
|
97
77
|
res.json(response);
|
|
98
78
|
});
|
|
99
|
-
// GET /api/files/flat - Get flat list of all files
|
|
79
|
+
// GET /api/files/flat - Get flat list of all files with mtime
|
|
100
80
|
router.get('/flat', (req, res) => {
|
|
101
81
|
const state = req.app.locals.state;
|
|
102
82
|
const result = collectFlatFiles(state.cwd, state.cwd, 10);
|
|
103
|
-
|
|
83
|
+
// Sort files by path for consistent display
|
|
84
|
+
result.files.sort((a, b) => a.path.localeCompare(b.path));
|
|
104
85
|
result.filteredDirs.sort();
|
|
86
|
+
// Find the most recently modified file
|
|
87
|
+
let recentFile = null;
|
|
88
|
+
if (result.files.length > 0) {
|
|
89
|
+
const mostRecent = result.files.reduce((prev, curr) => curr.mtime > prev.mtime ? curr : prev);
|
|
90
|
+
recentFile = mostRecent.path;
|
|
91
|
+
}
|
|
105
92
|
const response = {
|
|
106
93
|
files: result.files,
|
|
107
94
|
filteredDirs: result.filteredDirs,
|
|
95
|
+
recentFile,
|
|
108
96
|
};
|
|
109
97
|
res.json(response);
|
|
110
98
|
});
|
|
@@ -8,8 +8,14 @@ export function createStaticRouter() {
|
|
|
8
8
|
// Get __dirname equivalent in ESM
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = path.dirname(__filename);
|
|
11
|
-
//
|
|
12
|
-
|
|
11
|
+
// First, check for the bundled path. This is more robust than checking the filename.
|
|
12
|
+
// - Bundled: dist/flip-ui/dist
|
|
13
|
+
let distPath = path.resolve(__dirname, 'flip-ui/dist');
|
|
14
|
+
// If the bundled path doesn't exist, fall back to the unbundled (development) path.
|
|
15
|
+
// - Unbundled: packages/cli/flip-ui/dist
|
|
16
|
+
if (!fs.existsSync(distPath)) {
|
|
17
|
+
distPath = path.resolve(__dirname, '../../../flip-ui/dist');
|
|
18
|
+
}
|
|
13
19
|
// Check if dist exists (for development vs production)
|
|
14
20
|
if (fs.existsSync(distPath)) {
|
|
15
21
|
// Serve static files
|
|
@@ -18,19 +18,26 @@ router.post('/', async (req, res) => {
|
|
|
18
18
|
}));
|
|
19
19
|
// Format the output
|
|
20
20
|
const formatted = formatComments(comments);
|
|
21
|
-
// Copy to clipboard
|
|
21
|
+
// Copy to clipboard and schedule paste only if copy succeeds
|
|
22
|
+
let clipboardSuccess = false;
|
|
22
23
|
try {
|
|
23
24
|
await copyToClipboard(formatted);
|
|
25
|
+
clipboardSuccess = true;
|
|
24
26
|
}
|
|
25
27
|
catch (e) {
|
|
26
28
|
console.error('Failed to copy to clipboard:', e);
|
|
29
|
+
console.log('\n--- Output (copy manually) ---');
|
|
30
|
+
console.log(formatted);
|
|
31
|
+
console.log('--- End of output ---\n');
|
|
27
32
|
}
|
|
28
|
-
// Schedule paste
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
// Schedule paste only if clipboard copy succeeded
|
|
34
|
+
if (clipboardSuccess) {
|
|
35
|
+
try {
|
|
36
|
+
await schedulePaste(body.session_id);
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.error('Failed to schedule paste:', e);
|
|
40
|
+
}
|
|
34
41
|
}
|
|
35
42
|
// Send response before shutdown
|
|
36
43
|
res.json({ status: 'ok' });
|
|
@@ -8,6 +8,9 @@ import { gitRouter } from '../routes/git.js';
|
|
|
8
8
|
import { submitRouter } from '../routes/submit.js';
|
|
9
9
|
import { cancelRouter } from '../routes/cancel.js';
|
|
10
10
|
import { createStaticRouter } from '../routes/static.js';
|
|
11
|
+
import { createEventsRouter } from '../routes/events.js';
|
|
12
|
+
import { FileWatcher } from '../watcher/FileWatcher.js';
|
|
13
|
+
import { SSEManager } from '../events/SSEManager.js';
|
|
11
14
|
export class Server {
|
|
12
15
|
cwd;
|
|
13
16
|
port;
|
|
@@ -27,18 +30,37 @@ export class Server {
|
|
|
27
30
|
app.use(express.json());
|
|
28
31
|
// Store state in app locals
|
|
29
32
|
app.locals.state = state;
|
|
33
|
+
// Initialize SSE manager and file watcher
|
|
34
|
+
const sseManager = new SSEManager();
|
|
35
|
+
const fileWatcher = new FileWatcher({ cwd: this.cwd });
|
|
36
|
+
// Set up watcher event handlers
|
|
37
|
+
fileWatcher.onFilesChanged(() => {
|
|
38
|
+
sseManager.broadcast({ type: 'files-changed' });
|
|
39
|
+
});
|
|
40
|
+
fileWatcher.onFileChanged((path) => {
|
|
41
|
+
sseManager.broadcast({ type: 'file-changed', path });
|
|
42
|
+
});
|
|
43
|
+
fileWatcher.onGitChanged(() => {
|
|
44
|
+
sseManager.broadcast({ type: 'git-changed' });
|
|
45
|
+
});
|
|
46
|
+
// Start watching
|
|
47
|
+
fileWatcher.start();
|
|
30
48
|
// API routes
|
|
31
49
|
app.use('/api/files', filesRouter);
|
|
32
50
|
app.use('/api/file', fileRouter);
|
|
33
51
|
app.use('/api/git', gitRouter);
|
|
34
52
|
app.use('/api/submit', submitRouter);
|
|
35
53
|
app.use('/api/cancel', cancelRouter);
|
|
54
|
+
app.use('/api/events', createEventsRouter(sseManager));
|
|
36
55
|
// Static files (fallback to web-ui dist)
|
|
37
56
|
app.use(createStaticRouter());
|
|
38
57
|
const server = http.createServer(app);
|
|
39
58
|
// Set up the shutdown mechanism
|
|
40
|
-
state.resolve = (output) => {
|
|
41
|
-
|
|
59
|
+
state.resolve = async (output) => {
|
|
60
|
+
// Cleanup watcher and SSE connections
|
|
61
|
+
await fileWatcher.stop();
|
|
62
|
+
sseManager.closeAll();
|
|
63
|
+
await new Promise(res => server.close(() => res()));
|
|
42
64
|
resolve(output);
|
|
43
65
|
};
|
|
44
66
|
server.listen(this.port, '127.0.0.1', () => {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface FileWatcherOptions {
|
|
2
|
+
cwd: string;
|
|
3
|
+
debounceMs?: number;
|
|
4
|
+
}
|
|
5
|
+
type EventCallback = () => void;
|
|
6
|
+
type FileEventCallback = (filePath: string) => void;
|
|
7
|
+
export declare class FileWatcher {
|
|
8
|
+
private watcher;
|
|
9
|
+
private cwd;
|
|
10
|
+
private debounceMs;
|
|
11
|
+
private filesChangedCallbacks;
|
|
12
|
+
private fileChangedCallbacks;
|
|
13
|
+
private gitChangedCallbacks;
|
|
14
|
+
private filesDebounceTimer;
|
|
15
|
+
private gitDebounceTimer;
|
|
16
|
+
private fileDebounceTimers;
|
|
17
|
+
constructor(options: FileWatcherOptions);
|
|
18
|
+
start(): void;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
onFilesChanged(callback: EventCallback): void;
|
|
21
|
+
onFileChanged(callback: FileEventCallback): void;
|
|
22
|
+
onGitChanged(callback: EventCallback): void;
|
|
23
|
+
private handleFileEvent;
|
|
24
|
+
private handleDirEvent;
|
|
25
|
+
private emitFilesChanged;
|
|
26
|
+
private emitFileChanged;
|
|
27
|
+
private emitGitChanged;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import chokidar from 'chokidar';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { FILTERED_PATTERNS } from '../constants/filters.js';
|
|
4
|
+
export class FileWatcher {
|
|
5
|
+
watcher = null;
|
|
6
|
+
cwd;
|
|
7
|
+
debounceMs;
|
|
8
|
+
filesChangedCallbacks = [];
|
|
9
|
+
fileChangedCallbacks = [];
|
|
10
|
+
gitChangedCallbacks = [];
|
|
11
|
+
filesDebounceTimer = null;
|
|
12
|
+
gitDebounceTimer = null;
|
|
13
|
+
fileDebounceTimers = new Map();
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.cwd = options.cwd;
|
|
16
|
+
this.debounceMs = options.debounceMs ?? 300;
|
|
17
|
+
}
|
|
18
|
+
start() {
|
|
19
|
+
const ignoredPatterns = Array.from(FILTERED_PATTERNS).map(pattern => {
|
|
20
|
+
// .git은 감시하되 내부 변경은 git-changed 이벤트로 처리
|
|
21
|
+
if (pattern === '.git') {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return `**/${pattern}/**`;
|
|
25
|
+
}).filter(Boolean);
|
|
26
|
+
this.watcher = chokidar.watch(this.cwd, {
|
|
27
|
+
ignored: ignoredPatterns,
|
|
28
|
+
persistent: true,
|
|
29
|
+
ignoreInitial: true,
|
|
30
|
+
awaitWriteFinish: {
|
|
31
|
+
stabilityThreshold: 100,
|
|
32
|
+
pollInterval: 50,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
this.watcher
|
|
36
|
+
.on('add', (filePath) => this.handleFileEvent(filePath, 'add'))
|
|
37
|
+
.on('unlink', (filePath) => this.handleFileEvent(filePath, 'unlink'))
|
|
38
|
+
.on('change', (filePath) => this.handleFileEvent(filePath, 'change'))
|
|
39
|
+
.on('addDir', (filePath) => this.handleDirEvent(filePath, 'addDir'))
|
|
40
|
+
.on('unlinkDir', (filePath) => this.handleDirEvent(filePath, 'unlinkDir'))
|
|
41
|
+
.on('error', (error) => console.error('Watcher error:', error));
|
|
42
|
+
}
|
|
43
|
+
async stop() {
|
|
44
|
+
if (this.filesDebounceTimer) {
|
|
45
|
+
clearTimeout(this.filesDebounceTimer);
|
|
46
|
+
}
|
|
47
|
+
if (this.gitDebounceTimer) {
|
|
48
|
+
clearTimeout(this.gitDebounceTimer);
|
|
49
|
+
}
|
|
50
|
+
Array.from(this.fileDebounceTimers.values()).forEach(timer => {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
});
|
|
53
|
+
this.fileDebounceTimers.clear();
|
|
54
|
+
if (this.watcher) {
|
|
55
|
+
await this.watcher.close();
|
|
56
|
+
this.watcher = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
onFilesChanged(callback) {
|
|
60
|
+
this.filesChangedCallbacks.push(callback);
|
|
61
|
+
}
|
|
62
|
+
onFileChanged(callback) {
|
|
63
|
+
this.fileChangedCallbacks.push(callback);
|
|
64
|
+
}
|
|
65
|
+
onGitChanged(callback) {
|
|
66
|
+
this.gitChangedCallbacks.push(callback);
|
|
67
|
+
}
|
|
68
|
+
handleFileEvent(filePath, event) {
|
|
69
|
+
const relativePath = path.relative(this.cwd, filePath);
|
|
70
|
+
// .git 내부 변경은 git-changed 이벤트
|
|
71
|
+
if (relativePath.startsWith('.git')) {
|
|
72
|
+
this.emitGitChanged();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// 파일 추가/삭제는 트리 변경
|
|
76
|
+
if (event === 'add' || event === 'unlink') {
|
|
77
|
+
this.emitFilesChanged();
|
|
78
|
+
}
|
|
79
|
+
// 파일 내용 변경
|
|
80
|
+
if (event === 'change' || event === 'add') {
|
|
81
|
+
this.emitFileChanged(relativePath);
|
|
82
|
+
}
|
|
83
|
+
// 모든 파일 변경은 잠재적으로 git 상태에 영향
|
|
84
|
+
this.emitGitChanged();
|
|
85
|
+
}
|
|
86
|
+
handleDirEvent(dirPath, event) {
|
|
87
|
+
const relativePath = path.relative(this.cwd, dirPath);
|
|
88
|
+
// .git 내부는 무시
|
|
89
|
+
if (relativePath.startsWith('.git')) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// 디렉토리 변경은 트리 변경
|
|
93
|
+
this.emitFilesChanged();
|
|
94
|
+
}
|
|
95
|
+
emitFilesChanged() {
|
|
96
|
+
if (this.filesDebounceTimer) {
|
|
97
|
+
clearTimeout(this.filesDebounceTimer);
|
|
98
|
+
}
|
|
99
|
+
this.filesDebounceTimer = setTimeout(() => {
|
|
100
|
+
for (const callback of this.filesChangedCallbacks) {
|
|
101
|
+
callback();
|
|
102
|
+
}
|
|
103
|
+
}, this.debounceMs);
|
|
104
|
+
}
|
|
105
|
+
emitFileChanged(relativePath) {
|
|
106
|
+
const existingTimer = this.fileDebounceTimers.get(relativePath);
|
|
107
|
+
if (existingTimer) {
|
|
108
|
+
clearTimeout(existingTimer);
|
|
109
|
+
}
|
|
110
|
+
const timer = setTimeout(() => {
|
|
111
|
+
this.fileDebounceTimers.delete(relativePath);
|
|
112
|
+
for (const callback of this.fileChangedCallbacks) {
|
|
113
|
+
callback(relativePath);
|
|
114
|
+
}
|
|
115
|
+
}, this.debounceMs);
|
|
116
|
+
this.fileDebounceTimers.set(relativePath, timer);
|
|
117
|
+
}
|
|
118
|
+
emitGitChanged() {
|
|
119
|
+
if (this.gitDebounceTimer) {
|
|
120
|
+
clearTimeout(this.gitDebounceTimer);
|
|
121
|
+
}
|
|
122
|
+
this.gitDebounceTimer = setTimeout(() => {
|
|
123
|
+
for (const callback of this.gitChangedCallbacks) {
|
|
124
|
+
callback();
|
|
125
|
+
}
|
|
126
|
+
}, this.debounceMs);
|
|
127
|
+
}
|
|
128
|
+
}
|