@sanurb/ringi 0.2.1 → 0.3.1
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/LICENSE +21 -0
- package/dist/cli.mjs +505 -114
- package/dist/cli.mjs.map +1 -1
- package/dist/mcp.mjs +35 -39
- package/dist/mcp.mjs.map +1 -1
- package/dist/runtime.mjs +569 -428
- package/dist/runtime.mjs.map +1 -1
- package/package.json +13 -13
- package/server/nitro.json +17 -0
- package/server/public/assets/ClientOnly-QdfAxyFs.js +1 -0
- package/server/public/assets/_reviewId-CmXHvWLn.js +1 -0
- package/server/public/assets/_reviewId-DdOpDx4U.js +1 -0
- package/server/public/assets/abap-B1dkBSPn.js +1 -0
- package/server/public/assets/action-bar-DLRNvLjj.js +45 -0
- package/server/public/assets/actionscript-3-BT4ibYlP.js +1 -0
- package/server/public/assets/ada-CD92zeps.js +1 -0
- package/server/public/assets/andromeeda-DqSmgxi0.js +1 -0
- package/server/public/assets/angular-html-BDC0PfKr.js +1 -0
- package/server/public/assets/angular-ts-B9yoQMtj.js +1 -0
- package/server/public/assets/apache-D5suuoa_.js +1 -0
- package/server/public/assets/apex-BL-m4VHy.js +1 -0
- package/server/public/assets/apl-CldhY0Pn.js +1 -0
- package/server/public/assets/applescript-CLiBqvKT.js +1 -0
- package/server/public/assets/ara-LdDF8cmv.js +1 -0
- package/server/public/assets/asciidoc-2DZ9hC2N.js +1 -0
- package/server/public/assets/asm-0ZPGRSUy.js +1 -0
- package/server/public/assets/astro-DR6labZJ.js +1 -0
- package/server/public/assets/aurora-x-Da7Zfvbg.js +1 -0
- package/server/public/assets/awk-Bn0gn_B_.js +1 -0
- package/server/public/assets/ayu-dark-bqYKoqpM.js +1 -0
- package/server/public/assets/ayu-light-C45jTIzZ.js +1 -0
- package/server/public/assets/ayu-mirage-BV_FCTQi.js +1 -0
- package/server/public/assets/ballerina-D2nw_w8Q.js +1 -0
- package/server/public/assets/bat-ByUBN5gS.js +1 -0
- package/server/public/assets/beancount-BTb2W6Mp.js +1 -0
- package/server/public/assets/berry-5SO2uITG.js +1 -0
- package/server/public/assets/bibtex-CDBTNfUI.js +1 -0
- package/server/public/assets/bicep-fgxG_4rP.js +1 -0
- package/server/public/assets/bird2-BCwzDhwX.js +1 -0
- package/server/public/assets/blade-BBTRu2-g.js +1 -0
- package/server/public/assets/bsl-CG-fq4sc.js +1 -0
- package/server/public/assets/c-CEvNj7xl.js +1 -0
- package/server/public/assets/c3-Dlaci63_.js +1 -0
- package/server/public/assets/cadence-DHbRuEmm.js +1 -0
- package/server/public/assets/cairo-Ds0kTeYT.js +1 -0
- package/server/public/assets/catppuccin-frappe-DrL1fUuH.js +1 -0
- package/server/public/assets/catppuccin-latte-C0REgVjl.js +1 -0
- package/server/public/assets/catppuccin-macchiato-ChQpylWO.js +1 -0
- package/server/public/assets/catppuccin-mocha-Dd0JU1T0.js +1 -0
- package/server/public/assets/clarity-DMoTOm4G.js +1 -0
- package/server/public/assets/clojure-DBhE3PpS.js +1 -0
- package/server/public/assets/cmake-DwMc40Or.js +1 -0
- package/server/public/assets/cobol-BdNJSMRt.js +1 -0
- package/server/public/assets/codeowners-1lVr8wqV.js +1 -0
- package/server/public/assets/codeql-DWflolvo.js +1 -0
- package/server/public/assets/coffee-RA4xA24H.js +1 -0
- package/server/public/assets/common-lisp-CrVQ5xT-.js +1 -0
- package/server/public/assets/compiler-runtime-DZXZ41-q.js +1 -0
- package/server/public/assets/coq-CjfoyYSh.js +1 -0
- package/server/public/assets/cpp-BoW7e2Ow.js +1 -0
- package/server/public/assets/createServerFn-DTk395iP.js +9 -0
- package/server/public/assets/crystal-CYKRo3F9.js +1 -0
- package/server/public/assets/csharp-C7bIWP5y.js +1 -0
- package/server/public/assets/css-Ck2tii2d.js +1 -0
- package/server/public/assets/csv-DsAkDVtA.js +1 -0
- package/server/public/assets/cue-BWmQgbOB.js +1 -0
- package/server/public/assets/cypher-D-jVC50Q.js +1 -0
- package/server/public/assets/d-CaviyOrm.js +1 -0
- package/server/public/assets/dark-plus-DIrnwZt9.js +1 -0
- package/server/public/assets/dart-CZEi7JgC.js +1 -0
- package/server/public/assets/dax-BK-8zffy.js +1 -0
- package/server/public/assets/desktop-D3cjbL4D.js +1 -0
- package/server/public/assets/diff-sHAzLvlp.js +1 -0
- package/server/public/assets/docker--xs2Ng3w.js +1 -0
- package/server/public/assets/dotenv-Cm4nwcJ7.js +1 -0
- package/server/public/assets/dracula-CAUSusef.js +1 -0
- package/server/public/assets/dracula-soft-cjNkMFza.js +1 -0
- package/server/public/assets/dream-maker-fjmWTFCO.js +1 -0
- package/server/public/assets/edge-DxycC9wl.js +1 -0
- package/server/public/assets/elixir-B-50Er3p.js +1 -0
- package/server/public/assets/elm-B4-ygIVo.js +1 -0
- package/server/public/assets/emacs-lisp-CJzqStIa.js +1 -0
- package/server/public/assets/erb-DJvYE1L1.js +1 -0
- package/server/public/assets/erlang-C-m_88FN.js +1 -0
- package/server/public/assets/everforest-dark-DBpaSMx1.js +1 -0
- package/server/public/assets/everforest-light-CiGrXwia.js +1 -0
- package/server/public/assets/fennel-DRaXF7k8.js +1 -0
- package/server/public/assets/file-tree-CI3Xwwid.js +1907 -0
- package/server/public/assets/fish-Bn-Yh3Jj.js +1 -0
- package/server/public/assets/fluent-DF5F8Ks_.js +1 -0
- package/server/public/assets/fortran-fixed-form-Cx1lv7HN.js +1 -0
- package/server/public/assets/fortran-free-form-hCQHRqew.js +1 -0
- package/server/public/assets/fsharp-DC5k9sy2.js +1 -0
- package/server/public/assets/gdresource-D0EsKdgH.js +1 -0
- package/server/public/assets/gdscript-_C9_Hi_w.js +1 -0
- package/server/public/assets/gdshader-BW7b1X1Y.js +1 -0
- package/server/public/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/server/public/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/server/public/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/server/public/assets/genie-Ch_6TCHd.js +1 -0
- package/server/public/assets/gherkin-CaNUsmTq.js +1 -0
- package/server/public/assets/git-commit-BcFsuO5E.js +1 -0
- package/server/public/assets/git-rebase-ChGA-z50.js +1 -0
- package/server/public/assets/github-dark-B9ygjgg6.js +1 -0
- package/server/public/assets/github-dark-default-Br2bgYSx.js +1 -0
- package/server/public/assets/github-dark-dimmed-CmtqpPJ-.js +1 -0
- package/server/public/assets/github-dark-high-contrast-fSfmrZcC.js +1 -0
- package/server/public/assets/github-light-BZjUqfZl.js +1 -0
- package/server/public/assets/github-light-default-lIytXXhR.js +1 -0
- package/server/public/assets/github-light-high-contrast-BRrjFb7n.js +1 -0
- package/server/public/assets/gleam-DALMDpNs.js +1 -0
- package/server/public/assets/glimmer-js-maLb6ysA.js +1 -0
- package/server/public/assets/glimmer-ts-DGNr-OBA.js +1 -0
- package/server/public/assets/glsl-CmplqyQ1.js +1 -0
- package/server/public/assets/gn-DGjqrYN9.js +1 -0
- package/server/public/assets/gnuplot-BYckvgQI.js +1 -0
- package/server/public/assets/go-JycvP538.js +1 -0
- package/server/public/assets/graphql-VhP7n4--.js +1 -0
- package/server/public/assets/groovy-D5qMRONT.js +1 -0
- package/server/public/assets/gruvbox-dark-hard-M1dj1e6V.js +1 -0
- package/server/public/assets/gruvbox-dark-medium-cqq_ncQu.js +1 -0
- package/server/public/assets/gruvbox-dark-soft-B4QwL2a9.js +1 -0
- package/server/public/assets/gruvbox-light-hard-DLayMKOQ.js +1 -0
- package/server/public/assets/gruvbox-light-medium-D52XgPKf.js +1 -0
- package/server/public/assets/gruvbox-light-soft-Dola3KdD.js +1 -0
- package/server/public/assets/hack-BVSQ2bxM.js +1 -0
- package/server/public/assets/haml-CwTtRHoj.js +1 -0
- package/server/public/assets/handlebars-CcO01SVo.js +1 -0
- package/server/public/assets/haskell-ys7wPPEd.js +1 -0
- package/server/public/assets/haxe-94kiChn7.js +1 -0
- package/server/public/assets/hcl-DmHt_-wq.js +1 -0
- package/server/public/assets/hjson-xMmoJ0Gx.js +1 -0
- package/server/public/assets/hlsl-b-Pskdze.js +1 -0
- package/server/public/assets/horizon-BKMqttiR.js +1 -0
- package/server/public/assets/horizon-bright-HNkBlnm5.js +1 -0
- package/server/public/assets/houston-BkBSBSOQ.js +1 -0
- package/server/public/assets/html-derivative-Cz-cKMi2.js +1 -0
- package/server/public/assets/html-zQbUS8Is.js +1 -0
- package/server/public/assets/http-CaGQ9BgA.js +1 -0
- package/server/public/assets/hurl-BBoki9bg.js +1 -0
- package/server/public/assets/hxml-iQTOTWpM.js +1 -0
- package/server/public/assets/hy-DKl1XhBq.js +1 -0
- package/server/public/assets/imba-DPxkOTAg.js +1 -0
- package/server/public/assets/ini-lkLGq_1x.js +1 -0
- package/server/public/assets/java-LAx6oszV.js +1 -0
- package/server/public/assets/javascript-COqx-gKX.js +1 -0
- package/server/public/assets/jinja-x-G_qSCP.js +1 -0
- package/server/public/assets/jison-7oSeVkKJ.js +1 -0
- package/server/public/assets/json-sTLOVXhc.js +1 -0
- package/server/public/assets/json5-Cy6ypJuJ.js +1 -0
- package/server/public/assets/jsonc-Cw2ugYAK.js +1 -0
- package/server/public/assets/jsonl-Dp5_qBVH.js +1 -0
- package/server/public/assets/jsonnet-BTbmg_-u.js +1 -0
- package/server/public/assets/jssm-CnT7nPea.js +1 -0
- package/server/public/assets/jsx-zXeIBQLI.js +1 -0
- package/server/public/assets/julia-E-6Xm9nd.js +1 -0
- package/server/public/assets/just-D9n74gZy.js +1 -0
- package/server/public/assets/kanagawa-dragon-CxsBnuhV.js +1 -0
- package/server/public/assets/kanagawa-lotus-vHdxDDOS.js +1 -0
- package/server/public/assets/kanagawa-wave-CIkfTKWk.js +1 -0
- package/server/public/assets/kdl-BwK60g80.js +1 -0
- package/server/public/assets/kotlin-Dbd9Vi-v.js +1 -0
- package/server/public/assets/kusto-BuTk9usc.js +1 -0
- package/server/public/assets/laserwave-C0wf_d3o.js +1 -0
- package/server/public/assets/latex-D0t4RtEU.js +1 -0
- package/server/public/assets/lean-CYAW8bRN.js +1 -0
- package/server/public/assets/less-D4uen21c.js +1 -0
- package/server/public/assets/light-plus-oqYyWKEE.js +1 -0
- package/server/public/assets/liquid-BzXN12F6.js +1 -0
- package/server/public/assets/llvm-Z1xJzteV.js +1 -0
- package/server/public/assets/log-BGUxlsk3.js +1 -0
- package/server/public/assets/logo-wVUhvQ1b.js +1 -0
- package/server/public/assets/lua-B0Cg8RP4.js +1 -0
- package/server/public/assets/luau-rPFZzCmq.js +1 -0
- package/server/public/assets/main-FvxVz-kD.js +15 -0
- package/server/public/assets/make-BmPf6m0P.js +1 -0
- package/server/public/assets/markdown-AseU6zcW.js +1 -0
- package/server/public/assets/marko-BlRPXWOe.js +1 -0
- package/server/public/assets/material-theme-6_W6rQhR.js +1 -0
- package/server/public/assets/material-theme-darker-VPEo3Sem.js +1 -0
- package/server/public/assets/material-theme-lighter-CUhzCcZ9.js +1 -0
- package/server/public/assets/material-theme-ocean-B2JdsaGb.js +1 -0
- package/server/public/assets/material-theme-palenight-DhY-sklA.js +1 -0
- package/server/public/assets/matlab-BOj_BDQv.js +1 -0
- package/server/public/assets/mdc-FiVDZSZ4.js +1 -0
- package/server/public/assets/mdx-Cm6cDkDI.js +1 -0
- package/server/public/assets/mermaid-DLO-R4hv.js +1 -0
- package/server/public/assets/min-dark-D34a_pX7.js +1 -0
- package/server/public/assets/min-light-Cdd4KORE.js +1 -0
- package/server/public/assets/mipsasm-DYpHF-GA.js +1 -0
- package/server/public/assets/mojo-DqYVFv_G.js +1 -0
- package/server/public/assets/monokai-CDR4sQ2n.js +1 -0
- package/server/public/assets/moonbit-DRKee9wk.js +1 -0
- package/server/public/assets/move-DbRk6Vn9.js +1 -0
- package/server/public/assets/narrat-IOfmaXfb.js +1 -0
- package/server/public/assets/new-DOyplRwM.js +1 -0
- package/server/public/assets/nextflow-D-Ec_bsY.js +1 -0
- package/server/public/assets/nextflow-groovy-EYl0c2BQ.js +1 -0
- package/server/public/assets/nginx-3JLAqmJa.js +1 -0
- package/server/public/assets/night-owl-light-Bedht9b4.js +1 -0
- package/server/public/assets/night-owl-yQJ3-I0I.js +1 -0
- package/server/public/assets/nim-DyjFVMzT.js +1 -0
- package/server/public/assets/nix-C2IovEl2.js +1 -0
- package/server/public/assets/nord-BjZ63GNL.js +1 -0
- package/server/public/assets/nushell-BflTrRB5.js +1 -0
- package/server/public/assets/objective-c-GRClK1S7.js +1 -0
- package/server/public/assets/objective-cpp-l3qYw-v5.js +1 -0
- package/server/public/assets/ocaml-BBDyhyMH.js +1 -0
- package/server/public/assets/odin-jCJ7Js99.js +1 -0
- package/server/public/assets/one-dark-pro-PIx2Diul.js +1 -0
- package/server/public/assets/one-light-BFMEz49S.js +1 -0
- package/server/public/assets/openscad-Drf0LgCX.js +1 -0
- package/server/public/assets/pascal-BT2XAUTl.js +1 -0
- package/server/public/assets/perl-Dr47G_2Q.js +1 -0
- package/server/public/assets/php-BhBDWTJe.js +1 -0
- package/server/public/assets/pierre-dark-CTXzTLfO.js +1 -0
- package/server/public/assets/pierre-light-C_5rlJRo.js +1 -0
- package/server/public/assets/pkl-ML-dWShO.js +1 -0
- package/server/public/assets/plastic-BFI-Z5Z2.js +1 -0
- package/server/public/assets/plsql-0vd5cLro.js +1 -0
- package/server/public/assets/po-CbZ_uqQA.js +1 -0
- package/server/public/assets/poimandres-Cayhd01L.js +1 -0
- package/server/public/assets/polar-C4hfV8Nc.js +1 -0
- package/server/public/assets/postcss-osFUbTLw.js +1 -0
- package/server/public/assets/powerquery-CTlGUQPj.js +1 -0
- package/server/public/assets/powershell-DyZsOmuq.js +1 -0
- package/server/public/assets/preload-helper-D7oT-Xwl.js +20 -0
- package/server/public/assets/prisma-SS92PO_I.js +1 -0
- package/server/public/assets/prolog-B1O1NNVC.js +1 -0
- package/server/public/assets/proto-BWu3eZTs.js +1 -0
- package/server/public/assets/pug-Dij_IK5w.js +1 -0
- package/server/public/assets/puppet-tvtRVdr6.js +1 -0
- package/server/public/assets/purescript-Dtbpb7D-.js +1 -0
- package/server/public/assets/python-Dlk0Acio.js +1 -0
- package/server/public/assets/qml-qUwk3nhh.js +1 -0
- package/server/public/assets/qmldir-B-iEOngH.js +1 -0
- package/server/public/assets/qss-Ba0p-aHw.js +1 -0
- package/server/public/assets/r-WmtNicKM.js +1 -0
- package/server/public/assets/racket-BXDsxf2U.js +1 -0
- package/server/public/assets/raku-Dw1WWFXK.js +1 -0
- package/server/public/assets/razor-DaqiVx3Q.js +1 -0
- package/server/public/assets/red-BC3Ds49b.js +1 -0
- package/server/public/assets/reg-DXFHGaM4.js +1 -0
- package/server/public/assets/regexp-CiSWN5Ne.js +1 -0
- package/server/public/assets/rel-Dc5_Ytx2.js +1 -0
- package/server/public/assets/reviews-CJvVXRLH.js +1 -0
- package/server/public/assets/reviews-CfbuF6ib.js +1 -0
- package/server/public/assets/riscv-ZgswiWij.js +1 -0
- package/server/public/assets/ron-YghabWAH.js +1 -0
- package/server/public/assets/rose-pine-ByWLnVr3.js +1 -0
- package/server/public/assets/rose-pine-dawn-DBmeySrz.js +1 -0
- package/server/public/assets/rose-pine-moon-B9J-N3nK.js +1 -0
- package/server/public/assets/rosmsg-DTKmAsVH.js +1 -0
- package/server/public/assets/routes-DNxq1Fba.js +1 -0
- package/server/public/assets/routes-Dp0ODZ55.js +2 -0
- package/server/public/assets/rst-CP6xOYlY.js +1 -0
- package/server/public/assets/ruby-BXYLc1CM.js +1 -0
- package/server/public/assets/rust-nfXwuE6F.js +1 -0
- package/server/public/assets/sas-CFdtZutF.js +1 -0
- package/server/public/assets/sass-CbRjkld3.js +1 -0
- package/server/public/assets/scala-BzD3eypx.js +1 -0
- package/server/public/assets/scheme-D4d1PV1y.js +1 -0
- package/server/public/assets/scss-D8KhdObH.js +1 -0
- package/server/public/assets/sdbl-Cf-Ydnvx.js +1 -0
- package/server/public/assets/shaderlab-DGohHMiF.js +1 -0
- package/server/public/assets/shellscript-BHdEbumI.js +1 -0
- package/server/public/assets/shellsession-Dh-bxrap.js +1 -0
- package/server/public/assets/slack-dark-MszIyPZ2.js +1 -0
- package/server/public/assets/slack-ochin-tQ3Q0gE9.js +1 -0
- package/server/public/assets/smalltalk-_uWoArwn.js +1 -0
- package/server/public/assets/snazzy-light-9sniMEk5.js +1 -0
- package/server/public/assets/solarized-dark-CdD0Hxzv.js +1 -0
- package/server/public/assets/solarized-light-C-nsEdqF.js +1 -0
- package/server/public/assets/solidity-D6uC-xwP.js +1 -0
- package/server/public/assets/soy-cDuODfbT.js +1 -0
- package/server/public/assets/sparql-BgU2QITA.js +1 -0
- package/server/public/assets/splunk-LQYHRu14.js +1 -0
- package/server/public/assets/sql-CKZpK620.js +1 -0
- package/server/public/assets/ssh-config-B7BUl8Rd.js +1 -0
- package/server/public/assets/stata-BLJTbKOO.js +1 -0
- package/server/public/assets/styles-UDowwF7S.css +2 -0
- package/server/public/assets/stylus-Byjxdx_q.js +1 -0
- package/server/public/assets/surrealql-C96KvYaj.js +1 -0
- package/server/public/assets/svelte-Qnbj2GWx.js +1 -0
- package/server/public/assets/swift-BexLlMrU.js +1 -0
- package/server/public/assets/synthwave-84-BxMBwQMS.js +1 -0
- package/server/public/assets/system-verilog-DVGwm0mw.js +1 -0
- package/server/public/assets/systemd-H2IT3-p5.js +1 -0
- package/server/public/assets/talonscript-mKZIGM8n.js +1 -0
- package/server/public/assets/tasl-B7he_Ugr.js +1 -0
- package/server/public/assets/tcl-5mT3RxHH.js +1 -0
- package/server/public/assets/templ-CQPDll3D.js +1 -0
- package/server/public/assets/terraform-BZP0GLsT.js +1 -0
- package/server/public/assets/test-D7JRfog1.js +1 -0
- package/server/public/assets/tex-97QNLoBJ.js +1 -0
- package/server/public/assets/tokyo-night-CTPVdZt9.js +1 -0
- package/server/public/assets/toml-CTFA98he.js +1 -0
- package/server/public/assets/ts-tags-B8zlXe2n.js +1 -0
- package/server/public/assets/tsv-BayJtYdY.js +1 -0
- package/server/public/assets/tsx-VqRU8NCz.js +1 -0
- package/server/public/assets/turtle-TVCBh_kY.js +1 -0
- package/server/public/assets/twig-FTTF8rVk.js +1 -0
- package/server/public/assets/typescript-CuX0hIVY.js +1 -0
- package/server/public/assets/typespec-BUvaJDLF.js +1 -0
- package/server/public/assets/typst-8NBaY7Ec.js +1 -0
- package/server/public/assets/useStore-M3H8PB1v.js +1 -0
- package/server/public/assets/utils-DElCu2hq.js +1 -0
- package/server/public/assets/v-VihyTigi.js +1 -0
- package/server/public/assets/vala-DyFAPyX6.js +1 -0
- package/server/public/assets/vb-Dg1Iqi4J.js +1 -0
- package/server/public/assets/verilog-D2Xc-vhD.js +1 -0
- package/server/public/assets/vesper-DJbtqYNr.js +1 -0
- package/server/public/assets/vhdl-CU3BVeE7.js +1 -0
- package/server/public/assets/viml-hG2shuOW.js +1 -0
- package/server/public/assets/vitesse-black-DbG2gsc0.js +1 -0
- package/server/public/assets/vitesse-dark-B6WV4xXH.js +1 -0
- package/server/public/assets/vitesse-light-DC1pdD02.js +1 -0
- package/server/public/assets/vue-DXwaEU0U.js +1 -0
- package/server/public/assets/vue-html-QD7AJ6JJ.js +1 -0
- package/server/public/assets/vue-vine-Bh2m1D2Z.js +1 -0
- package/server/public/assets/vyper-C1wojIuk.js +1 -0
- package/server/public/assets/wasm-C6Y0s02M.js +1 -0
- package/server/public/assets/wasm-qTvCOSHz.js +1 -0
- package/server/public/assets/wenyan-BG5vPQF0.js +1 -0
- package/server/public/assets/wgsl-DrVb-Cub.js +1 -0
- package/server/public/assets/wikitext-PRC4s8sH.js +1 -0
- package/server/public/assets/wit-ChW5qvg_.js +1 -0
- package/server/public/assets/wolfram-B8mKuZSQ.js +1 -0
- package/server/public/assets/xml-BK-rcb5a.js +1 -0
- package/server/public/assets/xsl-dt-d2R7p.js +1 -0
- package/server/public/assets/yaml-UiXU3hGj.js +1 -0
- package/server/public/assets/zenscript-C-jEPC9j.js +1 -0
- package/server/public/assets/zig-EbnRGjcz.js +1 -0
- package/server/public/favicon.ico +0 -0
- package/server/public/logo192.png +0 -0
- package/server/public/logo512.png +0 -0
- package/server/public/manifest.json +25 -0
- package/server/public/robots.txt +3 -0
- package/server/public/tanstack-circle-logo.png +0 -0
- package/server/public/tanstack-word-logo-white.svg +1 -0
- package/server/server/_chunks/ssr-renderer.mjs +15 -0
- package/server/server/_libs/@floating-ui/core+[...].mjs +698 -0
- package/server/server/_libs/@floating-ui/dom+[...].mjs +644 -0
- package/server/server/_libs/@floating-ui/react-dom+[...].mjs +839 -0
- package/server/server/_libs/@pierre/diffs+[...].mjs +18578 -0
- package/server/server/_libs/@radix-ui/react-arrow+[...].mjs +174 -0
- package/server/server/_libs/@radix-ui/react-collection+[...].mjs +162 -0
- package/server/server/_libs/@radix-ui/react-dialog+[...].mjs +1666 -0
- package/server/server/_libs/@radix-ui/react-popper+[...].mjs +289 -0
- package/server/server/_libs/@radix-ui/react-radio-group+[...].mjs +420 -0
- package/server/server/_libs/@radix-ui/react-select+[...].mjs +990 -0
- package/server/server/_libs/@tanstack/react-router+[...].mjs +14113 -0
- package/server/server/_libs/_.mjs +2 -0
- package/server/server/_libs/chokidar+readdirp.mjs +1599 -0
- package/server/server/_libs/class-variance-authority+clsx.mjs +69 -0
- package/server/server/_libs/effect+[...].mjs +34047 -0
- package/server/server/_libs/h3+rou3+srvx.mjs +1195 -0
- package/server/server/_libs/hookable.mjs +41 -0
- package/server/server/_libs/lucide-react.mjs +298 -0
- package/server/server/_libs/pierre__theme.mjs +2668 -0
- package/server/server/_libs/radix-ui__number.mjs +6 -0
- package/server/server/_libs/radix-ui__primitive.mjs +9 -0
- package/server/server/_libs/radix-ui__react-direction.mjs +11 -0
- package/server/server/_libs/shiki.mjs +16 -0
- package/server/server/_libs/shikijs__langs.mjs +1355 -0
- package/server/server/_libs/shikijs__themes.mjs +262 -0
- package/server/server/_libs/tailwind-merge.mjs +1962 -0
- package/server/server/_libs/tanstack__history.mjs +342 -0
- package/server/server/_libs/tanstack__router-core.mjs +6 -0
- package/server/server/_libs/ufo.mjs +64 -0
- package/server/server/_reviewId-AWnOGz5k.mjs +33 -0
- package/server/server/_reviewId-Com4yOlc.mjs +29 -0
- package/server/server/_reviewId-DAhmekJ2.mjs +277 -0
- package/server/server/_reviewId-p9mhYVwa.mjs +18 -0
- package/server/server/_runtime.mjs +35 -0
- package/server/server/_ssr/action-bar-C68xGnWW.mjs +592 -0
- package/server/server/_ssr/api-handler-CstW2n82.mjs +189 -0
- package/server/server/_ssr/client-runtime-BoPuAEoA.mjs +245 -0
- package/server/server/_ssr/createServerRpc--0mcGlWK.mjs +12 -0
- package/server/server/_ssr/createSsrRpc-AwdiLXmF.mjs +16 -0
- package/server/server/_ssr/domain-rpc-3Ds9DPr0.mjs +287 -0
- package/server/server/_ssr/file-tree-CQ5w2GHh.mjs +1951 -0
- package/server/server/_ssr/load-scoped-diff-NL2XAcdz.mjs +45 -0
- package/server/server/_ssr/new-BKl_G2Ks.mjs +37 -0
- package/server/server/_ssr/new-BREdMFAM.mjs +12 -0
- package/server/server/_ssr/new-DCz5eHkb.mjs +137 -0
- package/server/server/_ssr/reviews-BL5Nsgst.mjs +7 -0
- package/server/server/_ssr/reviews-BoaEgGKs.mjs +100 -0
- package/server/server/_ssr/reviews-C7_NIhY8.mjs +19 -0
- package/server/server/_ssr/reviews-Dd69YBDa.mjs +12 -0
- package/server/server/_ssr/router-DLxN8FOm.mjs +415 -0
- package/server/server/_ssr/routes-D25G8OuS.mjs +80 -0
- package/server/server/_ssr/routes-lz0AN75A.mjs +929 -0
- package/server/server/_ssr/runtime-D9IbnMlF.mjs +1401 -0
- package/server/server/_ssr/server-runtime-D99qpmma.mjs +12 -0
- package/server/server/_ssr/ssr.mjs +5318 -0
- package/server/server/_ssr/start-BIQfOZtj.mjs +4 -0
- package/server/server/_ssr/test-CQdMYlqa.mjs +6 -0
- package/server/server/_ssr/todo-m_uUvxca.mjs +88 -0
- package/server/server/_ssr/use-keyboard-shortcuts-D5b1Mxpq.mjs +25 -0
- package/server/server/_ssr/utils-BuOt9_LA.mjs +8 -0
- package/server/server/_tanstack-start-manifest_v-CnL10NRH.mjs +71 -0
- package/server/server/index.mjs +2615 -0
- package/server/server/node_modules/detect-libc/lib/detect-libc.js +313 -0
- package/server/server/node_modules/detect-libc/lib/elf.js +39 -0
- package/server/server/node_modules/detect-libc/lib/filesystem.js +51 -0
- package/server/server/node_modules/detect-libc/lib/process.js +24 -0
- package/server/server/node_modules/detect-libc/package.json +44 -0
- package/server/server/node_modules/msgpackr-extract/index.js +1 -0
- package/server/server/node_modules/msgpackr-extract/package.json +50 -0
- package/server/server/node_modules/node-gyp-build-optional-packages/index.js +6 -0
- package/server/server/node_modules/node-gyp-build-optional-packages/node-gyp-build.js +236 -0
- package/server/server/node_modules/node-gyp-build-optional-packages/package.json +32 -0
- package/server/server/node_modules/tslib/modules/index.js +70 -0
- package/server/server/node_modules/tslib/modules/package.json +3 -0
- package/server/server/node_modules/tslib/package.json +47 -0
- package/server/server/node_modules/tslib/tslib.js +484 -0
- package/server/server/package.json +12 -0
package/dist/runtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","names":["parseHunks","stat","presolve","pjoin","prelative","psep","osType","fs_watch","stat","fsrealpath","EV","stat","watch","chokidar"],"sources":["../../../packages/core/src/schemas/review.ts","../../../packages/core/src/schemas/todo.ts","../../../packages/core/src/db/migrations.ts","../../../packages/core/src/db/database.ts","../../../packages/core/src/repos/comment.repo.ts","../../../packages/core/src/schemas/comment.ts","../../../packages/core/src/services/comment.service.ts","../../../packages/core/src/services/diff.service.ts","../../../packages/core/src/repos/review-file.repo.ts","../../../packages/core/src/repos/review.repo.ts","../../../packages/core/src/services/git.service.ts","../../../packages/core/src/services/review.service.ts","../../../packages/core/src/repos/todo.repo.ts","../../../packages/core/src/services/todo.service.ts","../../../packages/core/src/services/export.service.ts","../../../node_modules/.pnpm/readdirp@5.0.0/node_modules/readdirp/index.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/handler.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js","../../../packages/core/src/services/event.service.ts","../../../packages/core/src/runtime.ts"],"sourcesContent":["import * as HttpApiSchema from \"@effect/platform/HttpApiSchema\";\nimport * as Schema from \"effect/Schema\";\n\nexport const ReviewId = Schema.String.pipe(Schema.brand(\"ReviewId\"));\nexport type ReviewId = typeof ReviewId.Type;\n\nexport const DIFF_SCOPES = [\n \"uncommitted\",\n \"staged\",\n \"unstaged\",\n \"last-commit\",\n] as const;\nexport type DiffScope = (typeof DIFF_SCOPES)[number];\n\nexport const ReviewStatus = Schema.Literal(\n \"in_progress\",\n \"approved\",\n \"changes_requested\"\n);\nexport type ReviewStatus = typeof ReviewStatus.Type;\n\nexport const ReviewSourceType = Schema.Literal(\"staged\", \"branch\", \"commits\");\nexport type ReviewSourceType = typeof ReviewSourceType.Type;\n\nexport const Review = Schema.Struct({\n baseRef: Schema.NullOr(Schema.String),\n createdAt: Schema.String,\n id: ReviewId,\n repositoryPath: Schema.String,\n snapshotData: Schema.String,\n sourceRef: Schema.NullOr(Schema.String),\n sourceType: ReviewSourceType,\n status: ReviewStatus,\n updatedAt: Schema.String,\n});\nexport type Review = typeof Review.Type;\n\nexport const CreateReviewInput = Schema.Struct({\n sourceRef: Schema.optionalWith(Schema.NullOr(Schema.String), {\n default: () => null,\n }),\n sourceType: Schema.optionalWith(ReviewSourceType, {\n default: () => \"staged\" as const,\n }),\n});\nexport type CreateReviewInput = typeof CreateReviewInput.Type;\n\nexport const UpdateReviewInput = Schema.Struct({\n status: Schema.optionalWith(ReviewStatus, { as: \"Option\" }),\n});\nexport type UpdateReviewInput = typeof UpdateReviewInput.Type;\n\nexport class ReviewNotFound extends Schema.TaggedError<ReviewNotFound>()(\n \"ReviewNotFound\",\n { id: ReviewId },\n HttpApiSchema.annotations({ status: 404 })\n) {}\n","import * as HttpApiSchema from \"@effect/platform/HttpApiSchema\";\nimport * as Schema from \"effect/Schema\";\n\nimport { ReviewId } from \"./review\";\n\nexport const TodoId = Schema.String.pipe(Schema.brand(\"TodoId\"));\nexport type TodoId = typeof TodoId.Type;\n\nexport const Todo = Schema.Struct({\n completed: Schema.Boolean,\n content: Schema.String,\n createdAt: Schema.String,\n id: TodoId,\n position: Schema.Number,\n reviewId: Schema.NullOr(ReviewId),\n updatedAt: Schema.String,\n});\nexport type Todo = typeof Todo.Type;\n\nexport const CreateTodoInput = Schema.Struct({\n content: Schema.String.pipe(Schema.minLength(1)),\n reviewId: Schema.optionalWith(Schema.NullOr(ReviewId), {\n default: () => null,\n }),\n});\nexport type CreateTodoInput = typeof CreateTodoInput.Type;\n\nexport const UpdateTodoInput = Schema.Struct({\n completed: Schema.optionalWith(Schema.Boolean, { as: \"Option\" }),\n content: Schema.optionalWith(Schema.String.pipe(Schema.minLength(1)), {\n as: \"Option\",\n }),\n});\nexport type UpdateTodoInput = typeof UpdateTodoInput.Type;\n\nexport class TodoNotFound extends Schema.TaggedError<TodoNotFound>()(\n \"TodoNotFound\",\n { id: TodoId },\n HttpApiSchema.annotations({ status: 404 })\n) {}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nconst migrations: readonly string[] = [\n // v1: reviews table\n `CREATE TABLE IF NOT EXISTS reviews (\n id TEXT PRIMARY KEY,\n repository_path TEXT NOT NULL,\n base_ref TEXT,\n snapshot_data TEXT NOT NULL,\n status TEXT DEFAULT 'in_progress',\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v2: comments table\n `CREATE TABLE IF NOT EXISTS comments (\n id TEXT PRIMARY KEY,\n review_id TEXT NOT NULL REFERENCES reviews(id) ON DELETE CASCADE,\n file_path TEXT NOT NULL,\n line_number INTEGER,\n line_type TEXT,\n content TEXT NOT NULL,\n suggestion TEXT,\n resolved INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v3: add source_type and source_ref to reviews\n `ALTER TABLE reviews ADD COLUMN source_type TEXT DEFAULT 'staged';\n ALTER TABLE reviews ADD COLUMN source_ref TEXT`,\n\n // v4: todos table\n `CREATE TABLE IF NOT EXISTS todos (\n id TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n completed INTEGER DEFAULT 0,\n review_id TEXT REFERENCES reviews(id) ON DELETE CASCADE,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v5: add position to todos\n `ALTER TABLE todos ADD COLUMN position INTEGER DEFAULT 0`,\n\n // v6: review_files table\n `CREATE TABLE IF NOT EXISTS review_files (\n id TEXT PRIMARY KEY,\n review_id TEXT NOT NULL REFERENCES reviews(id) ON DELETE CASCADE,\n file_path TEXT NOT NULL,\n old_path TEXT,\n status TEXT NOT NULL,\n additions INTEGER NOT NULL DEFAULT 0,\n deletions INTEGER NOT NULL DEFAULT 0,\n hunks_data TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n];\n\n/** Apply pending migrations using PRAGMA user_version as the version tracker. */\nexport const runMigrations = (db: DatabaseSync): void => {\n const currentVersion = (\n db.prepare(\"PRAGMA user_version\").get() as { user_version: number }\n ).user_version;\n\n for (let i = currentVersion; i < migrations.length; i++) {\n // v3 (and any future multi-statement migration) uses semicolons to\n // separate statements — split and execute each independently.\n const statements = migrations[i]!.split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n for (const sql of statements) {\n db.exec(sql);\n }\n\n db.exec(`PRAGMA user_version = ${i + 1}`);\n }\n};\n","import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nimport * as Config from \"effect/Config\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\n\nimport { runMigrations } from \"./migrations\";\n\n/**\n * Wraps `body` in a SQLite transaction: BEGIN before, COMMIT on success,\n * ROLLBACK on any failure or interruption.\n */\nexport const withTransaction = <A, E, R>(\n db: DatabaseSync,\n body: Effect.Effect<A, E, R>\n): Effect.Effect<A, E, R> =>\n Effect.acquireUseRelease(\n Effect.sync(() => db.exec(\"BEGIN\")),\n () => body,\n (_, exit) =>\n Effect.sync(() => {\n if (Exit.isSuccess(exit)) {\n db.exec(\"COMMIT\");\n } else {\n db.exec(\"ROLLBACK\");\n }\n })\n );\n\nexport class SqliteService extends Effect.Service<SqliteService>()(\n \"@ringi/SqliteService\",\n {\n effect: Effect.gen(function* effect() {\n const dbPath = yield* Config.string(\"DB_PATH\").pipe(\n Config.withDefault(\".ringi/reviews.db\")\n );\n\n mkdirSync(dirname(dbPath), { recursive: true });\n\n const db = new DatabaseSync(dbPath);\n db.exec(\"PRAGMA journal_mode=WAL\");\n db.exec(\"PRAGMA foreign_keys=ON\");\n\n runMigrations(db);\n\n return { db } as const;\n }),\n }\n) {}\n","import * as Effect from \"effect/Effect\";\n\nimport { SqliteService } from \"../db/database\";\nimport type { Comment, CommentId } from \"../schemas/comment\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface CommentRow {\n id: string;\n review_id: string;\n file_path: string;\n line_number: number | null;\n line_type: string | null;\n content: string;\n suggestion: string | null;\n resolved: number; // SQLite stores booleans as 0/1\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToComment = (row: CommentRow): Comment => ({\n content: row.content,\n createdAt: row.created_at,\n filePath: row.file_path,\n id: row.id as CommentId,\n lineNumber: row.line_number,\n lineType: row.line_type as Comment[\"lineType\"],\n resolved: row.resolved === 1,\n reviewId: row.review_id as ReviewId,\n suggestion: row.suggestion,\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class CommentRepo extends Effect.Service<CommentRepo>()(\n \"@ringi/CommentRepo\",\n {\n dependencies: [SqliteService.Default],\n effect: Effect.gen(function* effect() {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM comments WHERE id = ?\");\n const stmtFindByReview = db.prepare(\n \"SELECT * FROM comments WHERE review_id = ? ORDER BY created_at ASC\"\n );\n const stmtFindByFile = db.prepare(\n \"SELECT * FROM comments WHERE review_id = ? AND file_path = ? ORDER BY line_number ASC, created_at ASC\"\n );\n const stmtInsert = db.prepare(\n `INSERT INTO comments (id, review_id, file_path, line_number, line_type, content, suggestion, resolved, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 0, datetime('now'), datetime('now'))`\n );\n const stmtDelete = db.prepare(\"DELETE FROM comments WHERE id = ?\");\n const stmtDeleteByReview = db.prepare(\n \"DELETE FROM comments WHERE review_id = ?\"\n );\n const stmtSetResolved = db.prepare(\n \"UPDATE comments SET resolved = ?, updated_at = datetime('now') WHERE id = ?\"\n );\n const stmtCountByReview = db.prepare(\n `SELECT\n COUNT(*) as total,\n SUM(CASE WHEN resolved = 1 THEN 1 ELSE 0 END) as resolved,\n SUM(CASE WHEN resolved = 0 THEN 1 ELSE 0 END) as unresolved,\n SUM(CASE WHEN suggestion IS NOT NULL THEN 1 ELSE 0 END) as with_suggestions\n FROM comments WHERE review_id = ?`\n );\n\n // ------------------------------------------------------------------\n\n const findById = (id: CommentId): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const findByReview = (\n reviewId: ReviewId\n ): Effect.Effect<readonly Comment[]> =>\n Effect.sync(() => {\n const rows = stmtFindByReview.all(\n reviewId\n ) as unknown as CommentRow[];\n return rows.map(rowToComment);\n });\n\n const findByFile = (\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<readonly Comment[]> =>\n Effect.sync(() => {\n const rows = stmtFindByFile.all(\n reviewId,\n filePath\n ) as unknown as CommentRow[];\n return rows.map(rowToComment);\n });\n\n const create = (input: {\n id: CommentId;\n reviewId: ReviewId;\n filePath: string;\n lineNumber: number | null;\n lineType: string | null;\n content: string;\n suggestion: string | null;\n }): Effect.Effect<Comment> =>\n Effect.sync(() => {\n stmtInsert.run(\n input.id,\n input.reviewId,\n input.filePath,\n input.lineNumber,\n input.lineType,\n input.content,\n input.suggestion\n );\n return rowToComment(\n stmtFindById.get(input.id) as unknown as CommentRow\n );\n });\n\n const update = (\n id: CommentId,\n updates: { content?: string; suggestion?: string | null }\n ): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n const setClauses: string[] = [];\n const params: unknown[] = [];\n\n if (updates.content !== undefined) {\n setClauses.push(\"content = ?\");\n params.push(updates.content);\n }\n if (updates.suggestion !== undefined) {\n setClauses.push(\"suggestion = ?\");\n params.push(updates.suggestion);\n }\n\n if (setClauses.length === 0) {\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n }\n\n setClauses.push(\"updated_at = datetime('now')\");\n params.push(id);\n\n db.prepare(\n `UPDATE comments SET ${setClauses.join(\", \")} WHERE id = ?`\n ).run(...(params as import(\"node:sqlite\").SQLInputValue[]));\n\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const setResolved = (\n id: CommentId,\n resolved: boolean\n ): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n stmtSetResolved.run(resolved ? 1 : 0, id);\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const remove = (id: CommentId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const removeByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteByReview.run(reviewId);\n return Number(result.changes);\n });\n\n const countByReview = (\n reviewId: ReviewId\n ): Effect.Effect<{\n total: number;\n resolved: number;\n unresolved: number;\n withSuggestions: number;\n }> =>\n Effect.sync(() => {\n const row = stmtCountByReview.get(reviewId) as unknown as {\n total: number;\n resolved: number;\n unresolved: number;\n with_suggestions: number;\n };\n return {\n resolved: row.resolved,\n total: row.total,\n unresolved: row.unresolved,\n withSuggestions: row.with_suggestions,\n };\n });\n\n return {\n countByReview,\n create,\n findByFile,\n findById,\n findByReview,\n remove,\n removeByReview,\n setResolved,\n update,\n } as const;\n }),\n }\n) {}\n","import * as HttpApiSchema from \"@effect/platform/HttpApiSchema\";\nimport * as Schema from \"effect/Schema\";\n\nimport { ReviewId } from \"./review\";\n\nexport const CommentId = Schema.String.pipe(Schema.brand(\"CommentId\"));\nexport type CommentId = typeof CommentId.Type;\n\nexport const LineType = Schema.Literal(\"added\", \"removed\", \"context\");\nexport type LineType = typeof LineType.Type;\n\nexport const Comment = Schema.Struct({\n content: Schema.String,\n createdAt: Schema.String,\n filePath: Schema.String,\n id: CommentId,\n lineNumber: Schema.NullOr(Schema.Number),\n lineType: Schema.NullOr(LineType),\n resolved: Schema.Boolean,\n reviewId: ReviewId,\n suggestion: Schema.NullOr(Schema.String),\n updatedAt: Schema.String,\n});\nexport type Comment = typeof Comment.Type;\n\nexport const CreateCommentInput = Schema.Struct({\n content: Schema.String.pipe(Schema.minLength(1)),\n filePath: Schema.String.pipe(Schema.minLength(1)),\n lineNumber: Schema.optionalWith(Schema.NullOr(Schema.Number), {\n default: () => null,\n }),\n lineType: Schema.optionalWith(Schema.NullOr(LineType), {\n default: () => null,\n }),\n suggestion: Schema.optionalWith(Schema.NullOr(Schema.String), {\n default: () => null,\n }),\n});\nexport type CreateCommentInput = typeof CreateCommentInput.Type;\n\nexport const UpdateCommentInput = Schema.Struct({\n content: Schema.optionalWith(Schema.String.pipe(Schema.minLength(1)), {\n as: \"Option\",\n }),\n suggestion: Schema.optionalWith(Schema.NullOr(Schema.String), {\n as: \"Option\",\n }),\n});\nexport type UpdateCommentInput = typeof UpdateCommentInput.Type;\n\nexport class CommentNotFound extends Schema.TaggedError<CommentNotFound>()(\n \"CommentNotFound\",\n { id: CommentId },\n HttpApiSchema.annotations({ status: 404 })\n) {}\n","import { randomUUID } from \"node:crypto\";\n\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\n\nimport { CommentRepo } from \"../repos/comment.repo\";\nimport type {\n CommentId,\n CreateCommentInput,\n UpdateCommentInput,\n} from \"../schemas/comment\";\nimport { CommentNotFound } from \"../schemas/comment\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class CommentService extends Effect.Service<CommentService>()(\n \"@ringi/CommentService\",\n {\n dependencies: [CommentRepo.Default],\n effect: Effect.sync(() => {\n // -----------------------------------------------------------------------\n // create\n // -----------------------------------------------------------------------\n const create = Effect.fn(\"CommentService.create\")(function* create(\n reviewId: ReviewId,\n input: CreateCommentInput\n ) {\n const repo = yield* CommentRepo;\n const id = randomUUID() as CommentId;\n\n return yield* repo.create({\n content: input.content,\n filePath: input.filePath,\n id,\n lineNumber: input.lineNumber,\n lineType: input.lineType,\n reviewId,\n suggestion: input.suggestion,\n });\n });\n\n // -----------------------------------------------------------------------\n // getById\n // -----------------------------------------------------------------------\n const getById = Effect.fn(\"CommentService.getById\")(function* getById(\n id: CommentId\n ) {\n const repo = yield* CommentRepo;\n const comment = yield* repo.findById(id);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n // -----------------------------------------------------------------------\n // getByReview\n // -----------------------------------------------------------------------\n const getByReview = Effect.fn(\"CommentService.getByReview\")(\n function* getByReview(reviewId: ReviewId) {\n const repo = yield* CommentRepo;\n return yield* repo.findByReview(reviewId);\n }\n );\n\n // -----------------------------------------------------------------------\n // getByFile\n // -----------------------------------------------------------------------\n const getByFile = Effect.fn(\"CommentService.getByFile\")(\n function* getByFile(reviewId: ReviewId, filePath: string) {\n const repo = yield* CommentRepo;\n return yield* repo.findByFile(reviewId, filePath);\n }\n );\n\n // -----------------------------------------------------------------------\n // update\n // -----------------------------------------------------------------------\n const update = Effect.fn(\"CommentService.update\")(function* update(\n id: CommentId,\n input: UpdateCommentInput\n ) {\n const repo = yield* CommentRepo;\n\n const updates: { content?: string; suggestion?: string | null } = {};\n if (Option.isSome(input.content)) {\n updates.content = input.content.value;\n }\n if (Option.isSome(input.suggestion)) {\n updates.suggestion = input.suggestion.value;\n }\n\n const comment = yield* repo.update(id, updates);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n // -----------------------------------------------------------------------\n // resolve / unresolve\n // -----------------------------------------------------------------------\n const resolve = Effect.fn(\"CommentService.resolve\")(function* resolve(\n id: CommentId\n ) {\n const repo = yield* CommentRepo;\n const comment = yield* repo.setResolved(id, true);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n const unresolve = Effect.fn(\"CommentService.unresolve\")(\n function* unresolve(id: CommentId) {\n const repo = yield* CommentRepo;\n const comment = yield* repo.setResolved(id, false);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n }\n );\n\n // -----------------------------------------------------------------------\n // remove\n // -----------------------------------------------------------------------\n const remove = Effect.fn(\"CommentService.remove\")(function* remove(\n id: CommentId\n ) {\n const repo = yield* CommentRepo;\n const existed = yield* repo.remove(id);\n if (!existed) {\n return yield* new CommentNotFound({ id });\n }\n return { success: true as const };\n });\n\n // -----------------------------------------------------------------------\n // getStats\n // -----------------------------------------------------------------------\n const getStats = Effect.fn(\"CommentService.getStats\")(function* getStats(\n reviewId: ReviewId\n ) {\n const repo = yield* CommentRepo;\n return yield* repo.countByReview(reviewId);\n });\n\n // -----------------------------------------------------------------------\n // Public interface\n // -----------------------------------------------------------------------\n return {\n create,\n getByFile,\n getById,\n getByReview,\n getStats,\n remove,\n resolve,\n unresolve,\n update,\n } as const;\n }),\n }\n) {}\n","import type {\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffSummary,\n} from \"../schemas/diff\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst HUNK_HEADER = /@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/;\n\nconst splitIntoFiles = (diffText: string): readonly string[] => {\n const files: string[] = [];\n const lines = diffText.split(\"\\n\");\n let current: string[] = [];\n for (const line of lines) {\n if (line.startsWith(\"diff --git\")) {\n if (current.length > 0) {\n files.push(current.join(\"\\n\"));\n }\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) {\n files.push(current.join(\"\\n\"));\n }\n return files;\n};\n\nconst parseHunks = (lines: readonly string[]): readonly DiffHunk[] => {\n const hunks: DiffHunk[] = [];\n let currentHunk: {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n lines: DiffLine[];\n } | null = null;\n let oldLineNum = 0;\n let newLineNum = 0;\n\n for (const line of lines) {\n const match = line.match(HUNK_HEADER);\n if (match) {\n if (currentHunk) {\n hunks.push(currentHunk);\n }\n const oldStart = Number.parseInt(match[1]!, 10);\n const oldLines = Number.parseInt(match[2] ?? \"1\", 10);\n const newStart = Number.parseInt(match[3]!, 10);\n const newLines = Number.parseInt(match[4] ?? \"1\", 10);\n currentHunk = { lines: [], newLines, newStart, oldLines, oldStart };\n oldLineNum = oldStart;\n newLineNum = newStart;\n continue;\n }\n\n if (!currentHunk) {\n continue;\n }\n\n if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: newLineNum++,\n oldLineNumber: null,\n type: \"added\",\n });\n } else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: null,\n oldLineNumber: oldLineNum++,\n type: \"removed\",\n });\n } else if (line.startsWith(\" \")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: newLineNum++,\n oldLineNumber: oldLineNum++,\n type: \"context\",\n });\n }\n // Skip '\\\', '---', '+++', 'index', mode lines\n }\n\n if (currentHunk) {\n hunks.push(currentHunk);\n }\n return hunks;\n};\n\nconst parseFileDiff = (fileDiff: string): DiffFile | null => {\n const lines = fileDiff.split(\"\\n\");\n const diffLine = lines.find((l) => l.startsWith(\"diff --git\"));\n if (!diffLine) {\n return null;\n }\n\n const pathMatch = diffLine.match(/diff --git a\\/(.+) b\\/(.+)/);\n if (!pathMatch) {\n return null;\n }\n\n const oldPath = pathMatch[1]!;\n const newPath = pathMatch[2]!;\n\n // Status detection (priority order)\n let status: DiffFile[\"status\"] = \"modified\";\n if (lines.some((l) => l.startsWith(\"deleted file mode\"))) {\n status = \"deleted\";\n } else if (lines.some((l) => l.startsWith(\"new file mode\"))) {\n status = \"added\";\n } else if (\n lines.some((l) => l.startsWith(\"rename from\")) ||\n oldPath !== newPath\n ) {\n status = \"renamed\";\n }\n\n const hunks = parseHunks(lines);\n\n let additions = 0;\n let deletions = 0;\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.type === \"added\") {\n additions++;\n } else if (line.type === \"removed\") {\n deletions++;\n }\n }\n }\n\n return { additions, deletions, hunks, newPath, oldPath, status };\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Parse a full multi-file unified diff into structured DiffFile objects. */\nexport const parseDiff = (diffText: string): readonly DiffFile[] => {\n if (!diffText.trim()) {\n return [];\n }\n const blocks = splitIntoFiles(diffText);\n const files: DiffFile[] = [];\n for (const block of blocks) {\n const parsed = parseFileDiff(block);\n if (parsed) {\n files.push(parsed);\n }\n }\n return files;\n};\n\n/** Parse a unified diff and return only the first file, or null. */\nexport const parseSingleFileDiff = (diffText: string): DiffFile | null => {\n const files = parseDiff(diffText);\n return files[0] ?? null;\n};\n\n/** Aggregate stats from already-parsed files. */\nexport const getDiffSummary = (files: readonly DiffFile[]): DiffSummary => {\n let totalAdditions = 0;\n let totalDeletions = 0;\n for (const file of files) {\n totalAdditions += file.additions;\n totalDeletions += file.deletions;\n }\n return {\n filesAdded: files.filter((f) => f.status === \"added\").length,\n filesDeleted: files.filter((f) => f.status === \"deleted\").length,\n filesModified: files.filter((f) => f.status === \"modified\").length,\n filesRenamed: files.filter((f) => f.status === \"renamed\").length,\n totalAdditions,\n totalDeletions,\n totalFiles: files.length,\n };\n};\n","import { randomUUID } from \"node:crypto\";\n\nimport * as Effect from \"effect/Effect\";\n\nimport { SqliteService, withTransaction } from \"../db/database\";\nimport type { DiffHunk } from \"../schemas/diff\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shapes\n// ---------------------------------------------------------------------------\n\ninterface ReviewFileRow {\n id: string;\n review_id: string;\n file_path: string;\n old_path: string | null;\n status: string;\n additions: number;\n deletions: number;\n hunks_data: string | null;\n created_at: string;\n}\n\ninterface ReviewFileMetadataRow {\n id: string;\n review_id: string;\n file_path: string;\n old_path: string | null;\n status: string;\n additions: number;\n deletions: number;\n created_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input type for bulk creation\n// ---------------------------------------------------------------------------\n\nexport interface CreateReviewFileInput {\n readonly reviewId: ReviewId;\n readonly filePath: string;\n readonly oldPath: string | null;\n readonly status: string;\n readonly additions: number;\n readonly deletions: number;\n readonly hunksData: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Static helpers\n// ---------------------------------------------------------------------------\n\nexport const parseHunks = (\n hunksData: string | null\n): Effect.Effect<readonly DiffHunk[]> =>\n hunksData == null\n ? Effect.succeed([])\n : Effect.try(() => JSON.parse(hunksData) as readonly DiffHunk[]).pipe(\n Effect.orElseSucceed(() => [] as readonly DiffHunk[])\n );\n\nexport const serializeHunks = (hunks: readonly DiffHunk[]): string =>\n JSON.stringify(hunks);\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ReviewFileRepo extends Effect.Service<ReviewFileRepo>()(\n \"@ringi/ReviewFileRepo\",\n {\n dependencies: [SqliteService.Default],\n effect: Effect.gen(function* effect() {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements\n const stmtFindByReview = db.prepare(\n `SELECT id, review_id, file_path, old_path, status, additions, deletions, created_at\n FROM review_files WHERE review_id = ? ORDER BY file_path`\n );\n const stmtFindByReviewAndPath = db.prepare(\n \"SELECT * FROM review_files WHERE review_id = ? AND file_path = ?\"\n );\n const stmtInsert = db.prepare(\n `INSERT INTO review_files (id, review_id, file_path, old_path, status, additions, deletions, hunks_data, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`\n );\n const stmtDeleteByReview = db.prepare(\n \"DELETE FROM review_files WHERE review_id = ?\"\n );\n const stmtCountByReview = db.prepare(\n \"SELECT COUNT(*) as count FROM review_files WHERE review_id = ?\"\n );\n\n // ------------------------------------------------------------------\n\n const findByReview = (\n reviewId: ReviewId\n ): Effect.Effect<readonly ReviewFileMetadataRow[]> =>\n Effect.sync(\n () =>\n stmtFindByReview.all(reviewId) as unknown as ReviewFileMetadataRow[]\n );\n\n const findByReviewAndPath = (\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<ReviewFileRow | null> =>\n Effect.sync(() => {\n const row = stmtFindByReviewAndPath.get(\n reviewId,\n filePath\n ) as unknown as ReviewFileRow | undefined;\n return row ?? null;\n });\n\n const createBulk = (\n files: readonly CreateReviewFileInput[]\n ): Effect.Effect<void> =>\n withTransaction(\n db,\n Effect.sync(() => {\n for (const f of files) {\n stmtInsert.run(\n randomUUID(),\n f.reviewId,\n f.filePath,\n f.oldPath,\n f.status,\n f.additions,\n f.deletions,\n f.hunksData\n );\n }\n })\n );\n\n const deleteByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteByReview.run(reviewId);\n return Number(result.changes);\n });\n\n const countByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountByReview.get(reviewId) as { count: number };\n return row.count;\n });\n\n return {\n countByReview,\n createBulk,\n deleteByReview,\n findByReview,\n findByReviewAndPath,\n } as const;\n }),\n }\n) {}\n","import * as Effect from \"effect/Effect\";\n\nimport { SqliteService } from \"../db/database\";\nimport type { Review, ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface ReviewRow {\n id: string;\n repository_path: string;\n base_ref: string | null;\n source_type: string;\n source_ref: string | null;\n snapshot_data: string;\n status: string;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToReview = (row: ReviewRow): Review => ({\n baseRef: row.base_ref,\n createdAt: row.created_at,\n id: row.id as ReviewId,\n repositoryPath: row.repository_path,\n snapshotData: row.snapshot_data,\n sourceRef: row.source_ref,\n sourceType: row.source_type as Review[\"sourceType\"],\n status: row.status as Review[\"status\"],\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\ninterface FindAllOpts {\n readonly status?: string;\n readonly repositoryPath?: string;\n readonly sourceType?: string;\n readonly page?: number;\n readonly pageSize?: number;\n}\n\nexport class ReviewRepo extends Effect.Service<ReviewRepo>()(\n \"@ringi/ReviewRepo\",\n {\n dependencies: [SqliteService.Default],\n effect: Effect.gen(function* effect() {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM reviews WHERE id = ?\");\n const stmtInsert = db.prepare(\n `INSERT INTO reviews (id, repository_path, base_ref, source_type, source_ref, snapshot_data, status, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))`\n );\n const stmtUpdate = db.prepare(\n `UPDATE reviews SET status = COALESCE(?, status), updated_at = datetime('now') WHERE id = ?`\n );\n const stmtDelete = db.prepare(\"DELETE FROM reviews WHERE id = ?\");\n const stmtCountAll = db.prepare(\"SELECT COUNT(*) as count FROM reviews\");\n const stmtCountByStatus = db.prepare(\n \"SELECT COUNT(*) as count FROM reviews WHERE status = ?\"\n );\n\n // ------------------------------------------------------------------\n\n const findById = (id: ReviewId): Effect.Effect<Review | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as ReviewRow | undefined;\n return row ? rowToReview(row) : null;\n });\n\n const findAll = (\n opts: FindAllOpts = {}\n ): Effect.Effect<{ data: readonly Review[]; total: number }> =>\n Effect.sync(() => {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.status != null) {\n conditions.push(\"status = ?\");\n params.push(opts.status);\n }\n if (opts.repositoryPath != null) {\n conditions.push(\"repository_path = ?\");\n params.push(opts.repositoryPath);\n }\n if (opts.sourceType != null) {\n conditions.push(\"source_type = ?\");\n params.push(opts.sourceType);\n }\n\n const where =\n conditions.length > 0 ? ` WHERE ${conditions.join(\" AND \")}` : \"\";\n\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n const offset = (page - 1) * pageSize;\n\n const totalRow = db\n .prepare(`SELECT COUNT(*) as count FROM reviews${where}`)\n .get(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as { count: number };\n\n const rows = db\n .prepare(\n `SELECT * FROM reviews${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`\n )\n .all(\n ...(params as import(\"node:sqlite\").SQLInputValue[]),\n pageSize,\n offset\n ) as unknown as ReviewRow[];\n\n return { data: rows.map(rowToReview), total: totalRow.count };\n });\n\n const create = (input: {\n id: ReviewId;\n repositoryPath: string;\n baseRef: string | null;\n sourceType: string;\n sourceRef: string | null;\n snapshotData: string;\n status: string;\n }): Effect.Effect<Review> =>\n Effect.sync(() => {\n stmtInsert.run(\n input.id,\n input.repositoryPath,\n input.baseRef,\n input.sourceType,\n input.sourceRef,\n input.snapshotData,\n input.status\n );\n // Row guaranteed to exist after successful insert\n return rowToReview(\n stmtFindById.get(input.id) as unknown as ReviewRow\n );\n });\n\n const update = (\n id: ReviewId,\n status: string | null\n ): Effect.Effect<Review | null> =>\n Effect.sync(() => {\n stmtUpdate.run(status, id);\n const row = stmtFindById.get(id) as ReviewRow | undefined;\n return row ? rowToReview(row) : null;\n });\n\n const remove = (id: ReviewId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const countAll = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountAll.get() as { count: number };\n return row.count;\n });\n\n const countByStatus = (status: string): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountByStatus.get(status) as { count: number };\n return row.count;\n });\n\n return {\n countAll,\n countByStatus,\n create,\n findAll,\n findById,\n remove,\n update,\n } as const;\n }),\n }\n) {}\n","import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport * as HttpApiSchema from \"@effect/platform/HttpApiSchema\";\nimport * as Config from \"effect/Config\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\n// ---------------------------------------------------------------------------\n// Error\n// ---------------------------------------------------------------------------\n\nexport class GitError extends Schema.TaggedError<GitError>()(\n \"GitError\",\n { message: Schema.String },\n HttpApiSchema.annotations({ status: 500 })\n) {}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Max bytes to collect from a git command before truncating (200 MB). */\nconst MAX_STDOUT_BYTES = 200 * 1024 * 1024;\n\nconst execGit = (args: readonly string[], repoPath: string) =>\n Effect.tryPromise({\n catch: (error) => new GitError({ message: String(error) }),\n try: () =>\n new Promise<string>((resolve, reject) => {\n const child = spawn(\"git\", [...args], { cwd: repoPath });\n\n const chunks: Buffer[] = [];\n let bytes = 0;\n let truncated = false;\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n if (truncated) {\n return;\n }\n bytes += chunk.length;\n if (bytes > MAX_STDOUT_BYTES) {\n truncated = true;\n child.kill();\n return;\n }\n chunks.push(chunk);\n });\n\n let stderr = \"\";\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n child.on(\"error\", reject);\n\n child.on(\"close\", (code) => {\n if (truncated) {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n return;\n }\n if (code !== 0) {\n reject(\n new Error(`git ${args[0]} exited with code ${code}: ${stderr}`)\n );\n } else {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n }\n });\n }),\n });\n\n/** Split git output into non-empty lines. */\nconst lines = (output: string): string[] =>\n output.trim().split(\"\\n\").filter(Boolean);\n\n/** Parse name-status output (e.g. `M\\tfile.ts`). */\nconst parseNameStatus = (output: string) =>\n lines(output).map((line) => {\n const [status, ...rest] = line.split(\"\\t\");\n return { path: rest.join(\"\\t\"), status: status! };\n });\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class GitService extends Effect.Service<GitService>()(\n \"@ringi/GitService\",\n {\n effect: Effect.gen(function* effect() {\n const repoPath = yield* Config.string(\"REPOSITORY_PATH\").pipe(\n Config.withDefault(process.cwd())\n );\n\n // -- repo state --------------------------------------------------------\n\n const hasCommits = execGit([\"rev-parse\", \"HEAD\"], repoPath).pipe(\n Effect.as(true),\n Effect.catchTag(\"GitError\", () => Effect.succeed(false)),\n Effect.withSpan(\"GitService.hasCommits\")\n );\n\n // -- repository info --------------------------------------------------\n\n const getRepositoryInfo = Effect.gen(function* getRepositoryInfo() {\n const name = yield* execGit(\n [\"rev-parse\", \"--show-toplevel\"],\n repoPath\n ).pipe(Effect.map((s) => s.trim().split(\"/\").pop() ?? \"unknown\"));\n\n const branch = yield* execGit(\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n repoPath\n ).pipe(Effect.map((s) => s.trim()));\n\n const remote = yield* execGit(\n [\"config\", \"--get\", \"remote.origin.url\"],\n repoPath\n ).pipe(\n Effect.map((s) => s.trim() || null),\n Effect.catchTag(\"GitError\", () => Effect.succeed(null))\n );\n\n return { branch, name, path: repoPath, remote };\n }).pipe(Effect.withSpan(\"GitService.getRepositoryInfo\"));\n\n // -- diffs -------------------------------------------------------------\n\n const getStagedDiff = execGit(\n [\"diff\", \"--cached\", \"--no-color\", \"--unified=3\"],\n repoPath\n ).pipe(Effect.withSpan(\"GitService.getStagedDiff\"));\n\n const getUncommittedDiff = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit([\"diff\", \"HEAD\", \"--no-color\", \"--unified=3\"], repoPath)\n : Effect.succeed(\"\")\n ),\n Effect.withSpan(\"GitService.getUncommittedDiff\")\n );\n\n const getUnstagedDiff = execGit(\n [\"diff\", \"--no-color\", \"--unified=3\"],\n repoPath\n ).pipe(Effect.withSpan(\"GitService.getUnstagedDiff\"));\n\n const getLastCommitDiff = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit(\n [\"show\", \"HEAD\", \"--format=\", \"--no-color\", \"--unified=3\"],\n repoPath\n )\n : Effect.succeed(\"\")\n ),\n Effect.withSpan(\"GitService.getLastCommitDiff\")\n );\n\n const getBranchDiff = Effect.fn(\"GitService.getBranchDiff\")(\n function* getBranchDiff(branch: string) {\n return yield* execGit(\n [\"diff\", `${branch}...HEAD`, \"--no-color\", \"--unified=3\"],\n repoPath\n );\n }\n );\n\n const getCommitDiff = Effect.fn(\"GitService.getCommitDiff\")(\n function* getCommitDiff(shas: readonly string[]) {\n if (shas.length === 1) {\n return yield* execGit(\n [\"show\", shas[0]!, \"--format=\", \"--no-color\", \"--unified=3\"],\n repoPath\n );\n }\n const first = shas.at(-1)!;\n const last = shas[0]!;\n return yield* execGit(\n [\"diff\", `${first}~1..${last}`, \"--no-color\", \"--unified=3\"],\n repoPath\n );\n }\n );\n\n // -- file lists --------------------------------------------------------\n\n const getStagedFiles = execGit(\n [\"diff\", \"--cached\", \"--name-status\"],\n repoPath\n ).pipe(\n Effect.map(parseNameStatus),\n Effect.withSpan(\"GitService.getStagedFiles\")\n );\n\n const getUncommittedFiles = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit([\"diff\", \"HEAD\", \"--name-status\"], repoPath).pipe(\n Effect.map(parseNameStatus)\n )\n : Effect.succeed([])\n ),\n Effect.withSpan(\"GitService.getUncommittedFiles\")\n );\n\n const getUnstagedFiles = execGit(\n [\"diff\", \"--name-status\"],\n repoPath\n ).pipe(\n Effect.map(parseNameStatus),\n Effect.withSpan(\"GitService.getUnstagedFiles\")\n );\n\n const getLastCommitFiles = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit(\n [\"show\", \"HEAD\", \"--format=\", \"--name-status\"],\n repoPath\n ).pipe(Effect.map(parseNameStatus))\n : Effect.succeed([])\n ),\n Effect.withSpan(\"GitService.getLastCommitFiles\")\n );\n\n // -- file content ------------------------------------------------------\n\n const getFileContent = Effect.fn(\"GitService.getFileContent\")(\n function* getFileContent(\n filePath: string,\n version: \"staged\" | \"head\" | \"working\"\n ) {\n switch (version) {\n case \"staged\": {\n return yield* execGit([\"show\", `:${filePath}`], repoPath);\n }\n case \"head\": {\n return yield* execGit([\"show\", `HEAD:${filePath}`], repoPath);\n }\n case \"working\":\n default: {\n return yield* Effect.tryPromise({\n catch: (error) =>\n new GitError({\n message: `Failed to read ${filePath}: ${String(error)}`,\n }),\n try: () => readFile(join(repoPath, filePath), \"utf8\"),\n });\n }\n }\n }\n );\n\n // -- tree / branches / commits -----------------------------------------\n\n const getFileTree = Effect.fn(\"GitService.getFileTree\")(\n function* getFileTree(ref: string) {\n return yield* execGit(\n [\"ls-tree\", \"-r\", \"--name-only\", ref],\n repoPath\n ).pipe(Effect.map(lines));\n }\n );\n\n const getBranches = execGit(\n [\"branch\", \"--format=%(refname:short)\\t%(HEAD)\"],\n repoPath\n ).pipe(\n Effect.map((output) =>\n lines(output).map((line) => {\n const [name, head] = line.split(\"\\t\");\n return { current: head === \"*\", name: name! };\n })\n ),\n Effect.withSpan(\"GitService.getBranches\")\n );\n\n const getCommits = Effect.fn(\"GitService.getCommits\")(\n function* getCommits(opts: {\n limit?: number;\n offset?: number;\n search?: string;\n }) {\n const limit = (opts.limit ?? 20) + 1; // +1 to detect hasMore\n const args = [\n \"log\",\n `--max-count=${limit}`,\n `--skip=${opts.offset ?? 0}`,\n \"--format=%H\\t%s\\t%an\\t%aI\",\n ];\n if (opts.search) {\n args.push(`--grep=${opts.search}`, \"-i\");\n }\n\n const output = yield* execGit(args, repoPath);\n const rows = lines(output);\n const hasMore = rows.length === limit;\n const commits = (hasMore ? rows.slice(0, -1) : rows).map((line) => {\n const [hash, message, author, date] = line.split(\"\\t\");\n return {\n author: author!,\n date: date!,\n hash: hash!,\n message: message!,\n };\n });\n return { commits, hasMore };\n }\n );\n\n // -- staging operations ------------------------------------------------\n\n const stageFiles = Effect.fn(\"GitService.stageFiles\")(\n function* stageFiles(files: readonly string[]) {\n return yield* execGit([\"add\", \"--\", ...files], repoPath).pipe(\n Effect.as(files)\n );\n }\n );\n\n const stageAll = execGit([\"add\", \"-A\"], repoPath).pipe(\n Effect.flatMap(() => getStagedFiles),\n Effect.map((files) => files.map((f) => f.path)),\n Effect.withSpan(\"GitService.stageAll\")\n );\n\n const unstageFiles = Effect.fn(\"GitService.unstageFiles\")(\n function* unstageFiles(files: readonly string[]) {\n return yield* execGit(\n [\"reset\", \"HEAD\", \"--\", ...files],\n repoPath\n ).pipe(Effect.as(files));\n }\n );\n\n const getRepositoryPath = execGit(\n [\"rev-parse\", \"--show-toplevel\"],\n repoPath\n ).pipe(\n Effect.map((s) => s.trim()),\n Effect.withSpan(\"GitService.getRepositoryPath\")\n );\n\n // -- public interface --------------------------------------------------\n\n return {\n getBranchDiff,\n getBranches,\n getCommitDiff,\n getCommits,\n getFileContent,\n getFileTree,\n getLastCommitDiff,\n getLastCommitFiles,\n getRepositoryInfo,\n getRepositoryPath,\n getStagedDiff,\n getStagedFiles,\n getUncommittedDiff,\n getUncommittedFiles,\n getUnstagedDiff,\n getUnstagedFiles,\n hasCommits,\n stageAll,\n stageFiles,\n unstageFiles,\n } as const;\n }),\n }\n) {}\n","import { execFile } from \"node:child_process\";\n\nimport * as HttpApiSchema from \"@effect/platform/HttpApiSchema\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\n\nimport {\n ReviewFileRepo,\n parseHunks,\n serializeHunks,\n} from \"../repos/review-file.repo\";\nimport { ReviewRepo } from \"../repos/review.repo\";\nimport type { DiffFile, DiffHunk } from \"../schemas/diff\";\nimport type {\n CreateReviewInput,\n ReviewId,\n ReviewStatus,\n UpdateReviewInput,\n} from \"../schemas/review\";\nimport { ReviewNotFound } from \"../schemas/review\";\nimport { parseDiff, getDiffSummary } from \"../services/diff.service\";\nimport { GitService } from \"../services/git.service\";\n\n// ---------------------------------------------------------------------------\n// Error\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line max-classes-per-file -- tagged error and service stay co-located for this domain module.\nexport class ReviewError extends Schema.TaggedError<ReviewError>()(\n \"ReviewError\",\n { code: Schema.String, message: Schema.String },\n HttpApiSchema.annotations({ status: 400 })\n) {}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Get HEAD SHA via git rev-parse. */\nconst getHeadSha = (repoPath: string) =>\n Effect.tryPromise({\n catch: () =>\n new ReviewError({ code: \"GIT_ERROR\", message: \"Failed to get HEAD\" }),\n try: () =>\n new Promise<string>((resolve, reject) => {\n execFile(\n \"git\",\n [\"rev-parse\", \"HEAD\"],\n { cwd: repoPath },\n (err, stdout) => {\n if (err) {\n reject(err);\n } else {\n resolve(stdout.trim());\n }\n }\n );\n }),\n });\n\ninterface SnapshotData {\n repository?: Record<string, unknown>;\n files?: DiffFile[];\n version?: number;\n}\n\n/**\n * Parse snapshotData JSON. Handles both v1 and v2 formats gracefully.\n * v1: { files: DiffFile[], repository: {...} }\n * v2: { repository: {...}, version: 2 }\n */\nconst parseSnapshotData = (s: string): Effect.Effect<SnapshotData> =>\n Effect.try(() => JSON.parse(s) as SnapshotData).pipe(\n Effect.orElseSucceed((): SnapshotData => ({}))\n );\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ReviewService extends Effect.Service<ReviewService>()(\n \"@ringi/ReviewService\",\n {\n dependencies: [\n ReviewRepo.Default,\n ReviewFileRepo.Default,\n GitService.Default,\n ],\n effect: Effect.sync(() => {\n // -----------------------------------------------------------------------\n // create\n // -----------------------------------------------------------------------\n const create = Effect.fn(\"ReviewService.create\")(function* create(\n input: CreateReviewInput\n ) {\n const git = yield* GitService;\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n\n const repoPath = yield* git.getRepositoryPath;\n const hasCommitsResult = yield* git.hasCommits;\n if (!hasCommitsResult) {\n return yield* new ReviewError({\n code: \"NO_COMMITS\",\n message: \"Repository has no commits\",\n });\n }\n\n let diffText: string;\n let baseRef: string | null = null;\n const { sourceType, sourceRef } = input;\n\n switch (sourceType) {\n case \"staged\": {\n diffText = yield* git.getStagedDiff;\n if (!diffText.trim()) {\n return yield* new ReviewError({\n code: \"NO_STAGED_CHANGES\",\n message: \"No staged changes\",\n });\n }\n baseRef = yield* getHeadSha(repoPath);\n break;\n }\n case \"branch\": {\n if (!sourceRef) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Branch name required\",\n });\n }\n diffText = yield* git.getBranchDiff(sourceRef);\n baseRef = sourceRef;\n break;\n }\n case \"commits\": {\n if (!sourceRef) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Commit SHAs required\",\n });\n }\n const shas = sourceRef\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n if (shas.length === 0) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"No valid commit SHAs\",\n });\n }\n diffText = yield* git.getCommitDiff(shas);\n baseRef = shas.at(-1) ?? null;\n break;\n }\n default: {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Unsupported review source\",\n });\n }\n }\n\n const files = parseDiff(diffText);\n if (files.length === 0) {\n return yield* new ReviewError({\n code: \"NO_CHANGES\",\n message: \"No changes found\",\n });\n }\n\n const repoInfo = yield* git.getRepositoryInfo;\n const reviewId = crypto.randomUUID() as ReviewId;\n const storeHunks = sourceType === \"staged\";\n\n const fileInputs = files.map((f) => ({\n additions: f.additions,\n deletions: f.deletions,\n filePath: f.newPath,\n hunksData: storeHunks ? serializeHunks(f.hunks as DiffHunk[]) : null,\n oldPath: f.oldPath !== f.newPath ? f.oldPath : null,\n reviewId,\n status: f.status,\n }));\n\n const snapshotData = JSON.stringify({\n repository: repoInfo,\n version: 2,\n });\n\n const review = yield* repo.create({\n baseRef,\n id: reviewId,\n repositoryPath: repoPath,\n snapshotData,\n sourceRef: sourceRef ?? null,\n sourceType,\n status: \"in_progress\",\n });\n\n yield* fileRepo.createBulk(fileInputs);\n\n return review;\n });\n\n // -----------------------------------------------------------------------\n // list\n // -----------------------------------------------------------------------\n const list = Effect.fn(\"ReviewService.list\")(function* list(opts: {\n page?: number;\n pageSize?: number;\n status?: ReviewStatus;\n repositoryPath?: string;\n sourceType?: string;\n }) {\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n\n const result = yield* repo.findAll({\n page,\n pageSize,\n repositoryPath: opts.repositoryPath,\n sourceType: opts.sourceType,\n status: opts.status,\n });\n\n const reviews = [];\n for (const review of result.data) {\n const fileCount = yield* fileRepo.countByReview(review.id);\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n reviews.push({\n ...review,\n fileCount,\n repository: snapshot.repository ?? null,\n });\n }\n\n return {\n hasMore: page * pageSize < result.total,\n page,\n pageSize,\n reviews,\n total: result.total,\n };\n });\n\n // -----------------------------------------------------------------------\n // getById\n // -----------------------------------------------------------------------\n const getById = Effect.fn(\"ReviewService.getById\")(function* getById(\n id: ReviewId\n ) {\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n\n const review = yield* repo.findById(id);\n if (!review) {\n return yield* new ReviewNotFound({ id });\n }\n\n // findByReview returns metadata rows (snake_case from DB)\n const fileRows = yield* fileRepo.findByReview(id);\n const files = fileRows.map((r) => ({\n additions: r.additions,\n deletions: r.deletions,\n filePath: r.file_path,\n id: r.id,\n oldPath: r.old_path,\n status: r.status,\n }));\n\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n const summary = getDiffSummary(\n files.map((f) => ({\n additions: f.additions,\n deletions: f.deletions,\n hunks: [],\n newPath: f.filePath,\n oldPath: f.oldPath ?? f.filePath,\n status: f.status as DiffFile[\"status\"],\n }))\n );\n\n return {\n ...review,\n files,\n repository: snapshot.repository ?? null,\n summary,\n };\n });\n\n // -----------------------------------------------------------------------\n // getFileHunks — lazy load hunks for a single file\n // -----------------------------------------------------------------------\n const getFileHunks = Effect.fn(\"ReviewService.getFileHunks\")(\n function* getFileHunks(reviewId: ReviewId, filePath: string) {\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n const git = yield* GitService;\n\n const review = yield* repo.findById(reviewId);\n if (!review) {\n return yield* new ReviewNotFound({ id: reviewId });\n }\n\n // Staged reviews store hunks in DB\n const fileRecord = yield* fileRepo.findByReviewAndPath(\n reviewId,\n filePath\n );\n if (fileRecord?.hunks_data) {\n return yield* parseHunks(fileRecord.hunks_data);\n }\n\n // Branch reviews: regenerate from git\n if (review.sourceType === \"branch\" && review.sourceRef) {\n const diff = yield* git.getBranchDiff(review.sourceRef);\n const diffFiles = parseDiff(diff);\n const file = diffFiles.find((f) => f.newPath === filePath);\n return (file?.hunks ?? []) as DiffHunk[];\n }\n\n // Commits reviews: regenerate from git\n if (review.sourceType === \"commits\" && review.sourceRef) {\n const shas = review.sourceRef.split(\",\").map((s) => s.trim());\n const diff = yield* git.getCommitDiff(shas);\n const diffFiles = parseDiff(diff);\n const file = diffFiles.find((f) => f.newPath === filePath);\n return (file?.hunks ?? []) as DiffHunk[];\n }\n\n // Legacy v1 fallback — hunks were embedded in snapshotData\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n if (snapshot.files) {\n const legacyFile = snapshot.files.find(\n (f) => f.newPath === filePath\n );\n return (legacyFile?.hunks ?? []) as DiffHunk[];\n }\n\n return [] as DiffHunk[];\n }\n );\n\n // -----------------------------------------------------------------------\n // update\n // -----------------------------------------------------------------------\n const update = Effect.fn(\"ReviewService.update\")(function* update(\n id: ReviewId,\n input: UpdateReviewInput\n ) {\n const repo = yield* ReviewRepo;\n\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new ReviewNotFound({ id });\n }\n\n const status = Option.getOrNull(input.status);\n const review = yield* repo.update(id, status);\n if (!review) {\n return yield* new ReviewNotFound({ id });\n }\n\n return review;\n });\n\n // -----------------------------------------------------------------------\n // remove\n // -----------------------------------------------------------------------\n const remove = Effect.fn(\"ReviewService.remove\")(function* remove(\n id: ReviewId\n ) {\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new ReviewNotFound({ id });\n }\n\n yield* fileRepo.deleteByReview(id);\n yield* repo.remove(id);\n\n return { success: true as const };\n });\n\n // -----------------------------------------------------------------------\n // getStats\n // -----------------------------------------------------------------------\n const getStats = Effect.fn(\"ReviewService.getStats\")(\n function* getStats() {\n const repo = yield* ReviewRepo;\n\n const total = yield* repo.countAll();\n const inProgress = yield* repo.countByStatus(\"in_progress\");\n const approved = yield* repo.countByStatus(\"approved\");\n const changesRequested =\n yield* repo.countByStatus(\"changes_requested\");\n\n return { approved, changesRequested, inProgress, total };\n }\n );\n\n // -----------------------------------------------------------------------\n // Public interface\n // -----------------------------------------------------------------------\n return {\n create,\n getById,\n getFileHunks,\n getStats,\n list,\n remove,\n update,\n } as const;\n }),\n }\n) {}\n","import * as Effect from \"effect/Effect\";\n\nimport { SqliteService, withTransaction } from \"../db/database\";\nimport type { Todo, TodoId } from \"../schemas/todo\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface TodoRow {\n id: string;\n content: string;\n completed: number;\n review_id: string | null;\n position: number;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToTodo = (row: TodoRow): Todo => ({\n completed: row.completed === 1,\n content: row.content,\n createdAt: row.created_at,\n id: row.id as TodoId,\n position: row.position,\n reviewId: row.review_id as Todo[\"reviewId\"],\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\ninterface FindAllOpts {\n readonly reviewId?: string;\n readonly completed?: boolean;\n readonly limit?: number;\n readonly offset?: number;\n}\n\nexport class TodoRepo extends Effect.Service<TodoRepo>()(\"@ringi/TodoRepo\", {\n dependencies: [SqliteService.Default],\n effect: Effect.gen(function* effect() {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM todos WHERE id = ?\");\n const stmtInsert = db.prepare(\n `INSERT INTO todos (id, content, completed, review_id, position, created_at, updated_at)\n VALUES (?, ?, 0, ?, ?, datetime('now'), datetime('now'))`\n );\n const stmtDelete = db.prepare(\"DELETE FROM todos WHERE id = ?\");\n const stmtDeleteCompleted = db.prepare(\n \"DELETE FROM todos WHERE completed = 1\"\n );\n const stmtNextPosition = db.prepare(\n \"SELECT COALESCE(MAX(position), -1) + 1 AS next_pos FROM todos\"\n );\n const stmtCountAll = db.prepare(\"SELECT COUNT(*) as count FROM todos\");\n const stmtCountCompleted = db.prepare(\n \"SELECT COUNT(*) as count FROM todos WHERE completed = 1\"\n );\n const stmtCountPending = db.prepare(\n \"SELECT COUNT(*) as count FROM todos WHERE completed = 0\"\n );\n\n // ------------------------------------------------------------------\n\n const findById = (id: TodoId): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n });\n\n const findAll = (\n opts: FindAllOpts = {}\n ): Effect.Effect<{ data: readonly Todo[]; total: number }> =>\n Effect.sync(() => {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.reviewId != null) {\n conditions.push(\"review_id = ?\");\n params.push(opts.reviewId);\n }\n if (opts.completed != null) {\n conditions.push(\"completed = ?\");\n params.push(opts.completed ? 1 : 0);\n }\n\n const where =\n conditions.length > 0 ? ` WHERE ${conditions.join(\" AND \")}` : \"\";\n\n const totalRow = db\n .prepare(`SELECT COUNT(*) as count FROM todos${where}`)\n .get(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as { count: number };\n\n const limitClause = opts.limit != null ? ` LIMIT ? OFFSET ?` : \"\";\n const queryParams =\n opts.limit != null\n ? [...params, opts.limit, opts.offset ?? 0]\n : params;\n\n const rows = db\n .prepare(\n `SELECT * FROM todos${where} ORDER BY position ASC${limitClause}`\n )\n .all(\n ...(queryParams as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as TodoRow[];\n\n return { data: rows.map(rowToTodo), total: totalRow.count };\n });\n\n const create = (input: {\n id: TodoId;\n content: string;\n reviewId: string | null;\n }): Effect.Effect<Todo> =>\n Effect.sync(() => {\n const { next_pos } = stmtNextPosition.get() as unknown as {\n next_pos: number;\n };\n stmtInsert.run(input.id, input.content, input.reviewId, next_pos);\n return rowToTodo(stmtFindById.get(input.id) as unknown as TodoRow);\n });\n\n const update = (\n id: TodoId,\n updates: { content?: string; completed?: boolean }\n ): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const sets: string[] = [];\n const params: unknown[] = [];\n\n if (updates.content != null) {\n sets.push(\"content = ?\");\n params.push(updates.content);\n }\n if (updates.completed != null) {\n sets.push(\"completed = ?\");\n params.push(updates.completed ? 1 : 0);\n }\n\n if (sets.length === 0) {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n }\n\n sets.push(\"updated_at = datetime('now')\");\n params.push(id);\n\n db.prepare(`UPDATE todos SET ${sets.join(\", \")} WHERE id = ?`).run(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n );\n\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n });\n\n const toggle = (id: TodoId): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n if (!row) {\n return null;\n }\n\n const newCompleted = row.completed === 1 ? 0 : 1;\n db.prepare(\n \"UPDATE todos SET completed = ?, updated_at = datetime('now') WHERE id = ?\"\n ).run(newCompleted, id);\n\n return rowToTodo(stmtFindById.get(id) as unknown as TodoRow);\n });\n\n const remove = (id: TodoId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const removeCompleted = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteCompleted.run();\n return Number(result.changes);\n });\n\n const reorder = (orderedIds: readonly string[]): Effect.Effect<number> =>\n withTransaction(\n db,\n Effect.sync(() => {\n const stmt = db.prepare(\n \"UPDATE todos SET position = ?, updated_at = datetime('now') WHERE id = ?\"\n );\n let updated = 0;\n for (let i = 0; i < orderedIds.length; i++) {\n const result = stmt.run(i, orderedIds[i]!);\n updated += Number(result.changes);\n }\n return updated;\n })\n );\n\n const move = (\n id: TodoId,\n newPosition: number\n ): Effect.Effect<Todo | null> =>\n Effect.gen(function* move() {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n if (!row) {\n return null;\n }\n\n const oldPosition = row.position;\n\n yield* withTransaction(\n db,\n Effect.sync(() => {\n if (newPosition < oldPosition) {\n db.prepare(\n \"UPDATE todos SET position = position + 1, updated_at = datetime('now') WHERE position >= ? AND position < ? AND id != ?\"\n ).run(newPosition, oldPosition, id);\n } else if (newPosition > oldPosition) {\n db.prepare(\n \"UPDATE todos SET position = position - 1, updated_at = datetime('now') WHERE position > ? AND position <= ? AND id != ?\"\n ).run(oldPosition, newPosition, id);\n }\n\n db.prepare(\n \"UPDATE todos SET position = ?, updated_at = datetime('now') WHERE id = ?\"\n ).run(newPosition, id);\n })\n );\n\n return rowToTodo(stmtFindById.get(id) as unknown as TodoRow);\n });\n\n const countAll = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountAll.get() as { count: number };\n return row.count;\n });\n\n const countCompleted = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountCompleted.get() as { count: number };\n return row.count;\n });\n\n const countPending = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountPending.get() as { count: number };\n return row.count;\n });\n\n return {\n countAll,\n countCompleted,\n countPending,\n create,\n findAll,\n findById,\n move,\n remove,\n removeCompleted,\n reorder,\n toggle,\n update,\n } as const;\n }),\n}) {}\n","import { randomUUID } from \"node:crypto\";\n\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\n\nimport { TodoRepo } from \"../repos/todo.repo\";\nimport type { CreateTodoInput, TodoId, UpdateTodoInput } from \"../schemas/todo\";\nimport { TodoNotFound } from \"../schemas/todo\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class TodoService extends Effect.Service<TodoService>()(\n \"@ringi/TodoService\",\n {\n dependencies: [TodoRepo.Default],\n effect: Effect.sync(() => {\n // -----------------------------------------------------------------------\n // create\n // -----------------------------------------------------------------------\n const create = Effect.fn(\"TodoService.create\")(function* create(\n input: CreateTodoInput\n ) {\n const repo = yield* TodoRepo;\n const id = randomUUID() as TodoId;\n return yield* repo.create({\n content: input.content,\n id,\n reviewId: input.reviewId,\n });\n });\n\n // -----------------------------------------------------------------------\n // getById\n // -----------------------------------------------------------------------\n const getById = Effect.fn(\"TodoService.getById\")(function* getById(\n id: TodoId\n ) {\n const repo = yield* TodoRepo;\n const todo = yield* repo.findById(id);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n // -----------------------------------------------------------------------\n // list\n // -----------------------------------------------------------------------\n const list = Effect.fn(\"TodoService.list\")(function* list(\n opts: {\n reviewId?: string;\n completed?: boolean;\n limit?: number;\n offset?: number;\n } = {}\n ) {\n const repo = yield* TodoRepo;\n const result = yield* repo.findAll(opts);\n return {\n data: result.data,\n limit: opts.limit ?? null,\n offset: opts.offset ?? 0,\n total: result.total,\n };\n });\n\n // -----------------------------------------------------------------------\n // update\n // -----------------------------------------------------------------------\n const update = Effect.fn(\"TodoService.update\")(function* update(\n id: TodoId,\n input: UpdateTodoInput\n ) {\n const repo = yield* TodoRepo;\n\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new TodoNotFound({ id });\n }\n\n const updates: { content?: string; completed?: boolean } = {};\n if (Option.isSome(input.content)) {\n updates.content = input.content.value;\n }\n if (Option.isSome(input.completed)) {\n updates.completed = input.completed.value;\n }\n\n const todo = yield* repo.update(id, updates);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n\n return todo;\n });\n\n // -----------------------------------------------------------------------\n // toggle\n // -----------------------------------------------------------------------\n const toggle = Effect.fn(\"TodoService.toggle\")(function* toggle(\n id: TodoId\n ) {\n const repo = yield* TodoRepo;\n const todo = yield* repo.toggle(id);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n // -----------------------------------------------------------------------\n // remove\n // -----------------------------------------------------------------------\n const remove = Effect.fn(\"TodoService.remove\")(function* remove(\n id: TodoId\n ) {\n const repo = yield* TodoRepo;\n\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new TodoNotFound({ id });\n }\n\n yield* repo.remove(id);\n return { success: true as const };\n });\n\n // -----------------------------------------------------------------------\n // removeCompleted\n // -----------------------------------------------------------------------\n const removeCompleted = Effect.fn(\"TodoService.removeCompleted\")(\n function* removeCompleted() {\n const repo = yield* TodoRepo;\n const deleted = yield* repo.removeCompleted();\n return { deleted };\n }\n );\n\n // -----------------------------------------------------------------------\n // reorder\n // -----------------------------------------------------------------------\n const reorder = Effect.fn(\"TodoService.reorder\")(function* reorder(\n orderedIds: readonly string[]\n ) {\n const repo = yield* TodoRepo;\n const updated = yield* repo.reorder(orderedIds);\n return { updated };\n });\n\n // -----------------------------------------------------------------------\n // move\n // -----------------------------------------------------------------------\n const move = Effect.fn(\"TodoService.move\")(function* move(\n id: TodoId,\n position: number\n ) {\n const repo = yield* TodoRepo;\n const todo = yield* repo.move(id, position);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n // -----------------------------------------------------------------------\n // getStats\n // -----------------------------------------------------------------------\n const getStats = Effect.fn(\"TodoService.getStats\")(function* getStats() {\n const repo = yield* TodoRepo;\n const total = yield* repo.countAll();\n const completed = yield* repo.countCompleted();\n const pending = yield* repo.countPending();\n return { completed, pending, total };\n });\n\n // -----------------------------------------------------------------------\n // Public interface\n // -----------------------------------------------------------------------\n return {\n create,\n getById,\n getStats,\n list,\n move,\n remove,\n removeCompleted,\n reorder,\n toggle,\n update,\n } as const;\n }),\n }\n) {}\n","import * as Effect from \"effect/Effect\";\n\nimport type { ReviewId } from \"../schemas/review\";\nimport { CommentService } from \"../services/comment.service\";\nimport { ReviewService } from \"../services/review.service\";\nimport { TodoService } from \"../services/todo.service\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ExportService extends Effect.Service<ExportService>()(\n \"@ringi/ExportService\",\n {\n dependencies: [\n ReviewService.Default,\n CommentService.Default,\n TodoService.Default,\n ],\n effect: Effect.sync(() => {\n const exportReview = Effect.fn(\"ExportService.exportReview\")(\n function* exportReview(reviewId: ReviewId) {\n const reviewSvc = yield* ReviewService;\n const commentSvc = yield* CommentService;\n const todoSvc = yield* TodoService;\n\n const review = yield* reviewSvc.getById(reviewId);\n\n // review.repository is parsed from snapshotData\n const repo = review.repository as {\n name?: string;\n branch?: string;\n } | null;\n const repoName = repo?.name ?? \"Unknown\";\n const branch = repo?.branch ?? \"unknown\";\n\n const comments = yield* commentSvc.getByReview(reviewId);\n const commentStats = yield* commentSvc.getStats(reviewId);\n const todos = yield* todoSvc.list({ reviewId });\n\n const lines: string[] = [];\n\n // -- Header --\n lines.push(`# Code Review: ${repoName}`);\n lines.push(\"\");\n lines.push(`**Status:** ${review.status}`);\n lines.push(`**Branch:** ${branch}`);\n lines.push(`**Created:** ${review.createdAt}`);\n\n // -- Files Changed --\n if (review.files && review.files.length > 0) {\n lines.push(\"\");\n lines.push(\"## Files Changed\");\n lines.push(\"\");\n lines.push(\"| File | Status | Additions | Deletions |\");\n lines.push(\"|------|--------|-----------|-----------|\");\n for (const f of review.files) {\n const statusLabel =\n f.status === \"modified\"\n ? \"M\"\n : f.status === \"added\"\n ? \"A\"\n : f.status === \"deleted\"\n ? \"D\"\n : f.status;\n lines.push(\n `| ${f.filePath} | ${statusLabel} | +${f.additions} | -${f.deletions} |`\n );\n }\n }\n\n // -- Comments --\n if (comments.length > 0) {\n lines.push(\"\");\n lines.push(\n `## Comments (${commentStats.total} total, ${commentStats.resolved} resolved)`\n );\n\n // Group by file\n const byFile = new Map<string, (typeof comments)[number][]>();\n for (const c of comments) {\n const key = c.filePath ?? \"(general)\";\n const arr = byFile.get(key) ?? [];\n arr.push(c);\n byFile.set(key, arr);\n }\n\n for (const [filePath, fileComments] of byFile) {\n lines.push(\"\");\n lines.push(`### ${filePath}`);\n for (const c of fileComments) {\n lines.push(\"\");\n lines.push(\n `**Line ${c.lineNumber ?? \"–\"}** (${c.lineType ?? \"context\"})`\n );\n lines.push(`> ${c.content}`);\n if (c.suggestion) {\n lines.push(\"\");\n lines.push(\"```suggestion\");\n lines.push(c.suggestion);\n lines.push(\"```\");\n }\n }\n }\n }\n\n // -- Todos --\n if (todos.data.length > 0) {\n const completed = todos.data.filter((t) => t.completed).length;\n lines.push(\"\");\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(\n `## Todos (${todos.total} total, ${completed} completed)`\n );\n lines.push(\"\");\n for (const t of todos.data) {\n const check = t.completed ? \"x\" : \" \";\n lines.push(`- [${check}] ${t.content}`);\n }\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n );\n\n return { exportReview } as const;\n }),\n }\n) {}\n","import { lstat, readdir, realpath, stat } from 'node:fs/promises';\nimport { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from 'node:path';\nimport { Readable } from 'node:stream';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n highWaterMark: 4096,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\n/** Readable readdir stream, emitting new files as they're being listed. */\nexport class ReaddirpStream extends Readable {\n parents;\n reading;\n parent;\n _stat;\n _maxDepth;\n _wantsDir;\n _wantsFile;\n _wantsEverything;\n _root;\n _isDirent;\n _statsProp;\n _rdOptions;\n _fileFilter;\n _directoryFilter;\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n const { root, type } = opts;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth =\n opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;\n this._wantsDir = type ? DIR_TYPES.has(type) : false;\n this._wantsFile = type ? FILE_TYPES.has(type) : false;\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir.\n this.parents = [this._exploreDir(root, 1)];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n const awaited = await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n const entryType = await this._getEntryType(entry);\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n this.parents.push(this._exploreDir(entry.fullPath, depth + 1));\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n this.parent = await parent;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n async _formatEntry(dirent, path) {\n let entry;\n const basename = this._isDirent ? dirent.name : dirent;\n try {\n const fullPath = presolve(pjoin(path, basename));\n entry = { path: prelative(this._root, fullPath), fullPath, basename };\n entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);\n }\n catch (err) {\n this._onError(err);\n return;\n }\n return entry;\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n async _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry && this._statsProp in entry) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats && stats.isSymbolicLink()) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n return this._onError(recursiveError);\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n return '';\n }\n }\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (type)\n options.type = type;\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n options.root = root;\n return new ReaddirpStream(options);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watch as fs_watch, unwatchFile, watchFile } from 'node:fs';\nimport { realpath as fsrealpath, lstat, open, stat } from 'node:fs/promises';\nimport { type as osType } from 'node:os';\nimport * as sp from 'node:path';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n fsw;\n _boundHandleError;\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sp.dirname(path);\n const basename = sp.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sp.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sp.dirname(file);\n const basename = sp.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sp.join(directory, '');\n const throttleKey = target ? `${directory}:${target}` : directory;\n throttler = this.fsw._throttle('readdir', throttleKey, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sp.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sp.join(dir, sp.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));\n const tracked = parentDir.has(sp.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sp.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sp.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sp.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { EventEmitter } from 'node:events';\nimport { stat as statcb, Stats } from 'node:fs';\nimport { readdir, stat } from 'node:fs/promises';\nimport * as sp from 'node:path';\nimport { readdirp, ReaddirpStream } from 'readdirp';\nimport { EMPTY_FN, EVENTS as EV, isIBMi, isWindows, NodeFsHandler, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//g;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sp.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sp.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sp.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sp.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sp.isAbsolute(path) ? path : sp.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sp.isAbsolute(path)) {\n return path;\n }\n return sp.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n path;\n _removeWatcher;\n items;\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sp.dirname(dir), sp.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n fsw;\n path;\n watchPath;\n fullWatchPath;\n dirParts;\n followSymlinks;\n statMethod;\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sp.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sp.join(this.watchPath, sp.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n closed;\n options;\n _closers;\n _ignoredPaths;\n _throttled;\n _streams;\n _symlinkPaths;\n _watched;\n _pendingWrites;\n _pendingUnlinks;\n _readyCount;\n _emitReady;\n _closePromise;\n _userIgnored;\n _readyEmitted;\n _emitRaw;\n _boundRemove;\n _nodeFsHandler;\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sp.dirname(item), sp.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sp.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sp.join(cwd, path);\n path = sp.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sp.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sp.normalize(path);\n if (opts.cwd)\n path = sp.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sp.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sp.isAbsolute(path)) {\n fullPath = sp.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sp.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sp.join(directory, item);\n const fullPath = sp.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sp.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sp.dirname(path);\n this._getWatchedDir(dir).remove(sp.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch: watch, FSWatcher: FSWatcher };\n","import { platform } from \"node:os\";\nimport { relative } from \"node:path\";\n\nimport chokidar from \"chokidar\";\nimport * as Effect from \"effect/Effect\";\nimport * as Queue from \"effect/Queue\";\nimport * as Runtime from \"effect/Runtime\";\nimport * as Stream from \"effect/Stream\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type EventType = \"todos\" | \"reviews\" | \"comments\" | \"files\";\n\nexport interface SSEEvent {\n readonly type: EventType;\n readonly data?: unknown;\n readonly timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class EventService extends Effect.Service<EventService>()(\n \"@ringi/EventService\",\n {\n effect: Effect.gen(function* effect() {\n const rt = yield* Effect.runtime<never>();\n const runFork = Runtime.runFork(rt);\n const subscribers = new Set<Queue.Queue<SSEEvent>>();\n\n // -- broadcast ---------------------------------------------------------\n\n const broadcast = Effect.fn(\"EventService.broadcast\")(function* broadcast(\n type: EventType,\n data?: unknown\n ) {\n const event: SSEEvent = { data, timestamp: Date.now(), type };\n for (const queue of subscribers) {\n yield* Queue.offer(queue, event);\n }\n });\n\n // -- subscribe ---------------------------------------------------------\n\n const subscribe = Effect.fn(\"EventService.subscribe\")(\n function* subscribe() {\n const queue = yield* Queue.sliding<SSEEvent>(100);\n subscribers.add(queue);\n\n const stream = Stream.fromQueue(queue);\n\n const unsubscribe = Effect.sync(() => {\n subscribers.delete(queue);\n }).pipe(Effect.andThen(Queue.shutdown(queue)));\n\n return { stream, unsubscribe } as const;\n }\n );\n\n // -- file watcher ------------------------------------------------------\n\n const startFileWatcher = (repoPath: string) =>\n Effect.acquireRelease(\n Effect.sync(() => {\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const watcher = chokidar.watch(repoPath, {\n ignoreInitial: true,\n ignored: [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/.ringi/**\",\n \"**/dist/**\",\n ],\n persistent: true,\n ...(platform() === \"darwin\"\n ? { interval: 1000, usePolling: true }\n : {}),\n });\n\n const debouncedBroadcast = (filePath: string) => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n const rel = relative(repoPath, filePath);\n runFork(broadcast(\"files\", { path: rel }));\n }, 300);\n };\n\n watcher.on(\"add\", debouncedBroadcast);\n watcher.on(\"change\", debouncedBroadcast);\n watcher.on(\"unlink\", debouncedBroadcast);\n\n return watcher;\n }),\n (watcher) => Effect.promise(() => watcher.close())\n );\n\n // -- client count ------------------------------------------------------\n\n const getClientCount = () => Effect.sync(() => subscribers.size);\n\n return {\n broadcast,\n getClientCount,\n startFileWatcher,\n subscribe,\n } as const;\n }),\n }\n) {}\n","import * as Layer from \"effect/Layer\";\nimport * as ManagedRuntime from \"effect/ManagedRuntime\";\n\nimport { SqliteService } from \"./db/database\";\nimport { CommentRepo } from \"./repos/comment.repo\";\nimport { ReviewFileRepo } from \"./repos/review-file.repo\";\nimport { ReviewRepo } from \"./repos/review.repo\";\nimport { TodoRepo } from \"./repos/todo.repo\";\nimport { CommentService } from \"./services/comment.service\";\nimport { EventService } from \"./services/event.service\";\nimport { ExportService } from \"./services/export.service\";\nimport { GitService } from \"./services/git.service\";\nimport { ReviewService } from \"./services/review.service\";\nimport { TodoService } from \"./services/todo.service\";\n\nexport const CoreLive = Layer.mergeAll(\n ReviewService.Default,\n ReviewRepo.Default,\n ReviewFileRepo.Default,\n CommentService.Default,\n CommentRepo.Default,\n TodoService.Default,\n TodoRepo.Default,\n GitService.Default,\n EventService.Default,\n ExportService.Default,\n SqliteService.Default\n);\n\nexport const createCoreRuntime = () => ManagedRuntime.make(CoreLive);\n"],"x_google_ignoreList":[15,16,17],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.mjs","names":["parseHunks","MAX_STDOUT_BYTES","stat","presolve","pjoin","prelative","psep","osType","fs_watch","stat","fsrealpath","EV","stat","watch","chokidar"],"sources":["../../../packages/core/src/schemas/review.ts","../../../packages/core/src/schemas/todo.ts","../../../packages/core/src/db/migrations.ts","../../../packages/core/src/db/database.ts","../../../packages/core/src/repos/comment.repo.ts","../../../packages/core/src/schemas/comment.ts","../../../packages/core/src/services/comment.service.ts","../../../packages/core/src/services/diff.service.ts","../../../packages/core/src/repos/review-file.repo.ts","../../../packages/core/src/repos/review.repo.ts","../../../packages/core/src/services/git.service.ts","../../../packages/core/src/services/review.service.ts","../../../packages/core/src/repos/todo.repo.ts","../../../packages/core/src/services/todo.service.ts","../../../packages/core/src/services/export.service.ts","../../../packages/core/src/services/gh.service.ts","../../../node_modules/.pnpm/readdirp@5.0.0/node_modules/readdirp/index.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/handler.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js","../../../packages/core/src/services/event.service.ts","../../../packages/core/src/runtime.ts"],"sourcesContent":["import * as Schema from \"effect/Schema\";\n\nexport const ReviewId = Schema.String.pipe(Schema.brand(\"ReviewId\"));\nexport type ReviewId = typeof ReviewId.Type;\n\nexport const DIFF_SCOPES = [\n \"uncommitted\",\n \"staged\",\n \"unstaged\",\n \"last-commit\",\n] as const;\nexport type DiffScope = (typeof DIFF_SCOPES)[number];\n\nexport const ReviewStatus = Schema.Literals([\n \"in_progress\",\n \"approved\",\n \"changes_requested\",\n]);\nexport type ReviewStatus = typeof ReviewStatus.Type;\n\nexport const ReviewSourceType = Schema.Literals([\n \"staged\",\n \"branch\",\n \"commits\",\n \"pull_request\",\n]);\nexport type ReviewSourceType = typeof ReviewSourceType.Type;\n\nexport const Review = Schema.Struct({\n baseRef: Schema.NullOr(Schema.String),\n createdAt: Schema.String,\n id: ReviewId,\n repositoryPath: Schema.String,\n snapshotData: Schema.String,\n sourceRef: Schema.NullOr(Schema.String),\n sourceType: ReviewSourceType,\n status: ReviewStatus,\n updatedAt: Schema.String,\n});\nexport type Review = typeof Review.Type;\n\nexport const CreateReviewInput = Schema.Struct({\n sourceRef: Schema.NullOr(Schema.String).pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => null)\n ),\n sourceType: ReviewSourceType.pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => \"staged\" as const)\n ),\n});\nexport type CreateReviewInput = typeof CreateReviewInput.Type;\n\nexport const UpdateReviewInput = Schema.Struct({\n status: Schema.OptionFromNullOr(ReviewStatus).pipe(Schema.optionalKey),\n});\nexport type UpdateReviewInput = typeof UpdateReviewInput.Type;\n\nexport class ReviewNotFound extends Schema.TaggedErrorClass<ReviewNotFound>()(\n \"ReviewNotFound\",\n { id: ReviewId }\n) {}\n","import * as Schema from \"effect/Schema\";\n\nimport { ReviewId } from \"./review\";\n\nexport const TodoId = Schema.String.pipe(Schema.brand(\"TodoId\"));\nexport type TodoId = typeof TodoId.Type;\n\nexport const Todo = Schema.Struct({\n completed: Schema.Boolean,\n content: Schema.String,\n createdAt: Schema.String,\n id: TodoId,\n position: Schema.Number,\n reviewId: Schema.NullOr(ReviewId),\n updatedAt: Schema.String,\n});\nexport type Todo = typeof Todo.Type;\n\nexport const CreateTodoInput = Schema.Struct({\n content: Schema.String.pipe(Schema.check(Schema.isMinLength(1))),\n reviewId: Schema.NullOr(ReviewId).pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => null)\n ),\n});\nexport type CreateTodoInput = typeof CreateTodoInput.Type;\n\nexport const UpdateTodoInput = Schema.Struct({\n completed: Schema.OptionFromNullOr(Schema.Boolean).pipe(Schema.optionalKey),\n content: Schema.OptionFromNullOr(\n Schema.String.pipe(Schema.check(Schema.isMinLength(1)))\n ).pipe(Schema.optionalKey),\n});\nexport type UpdateTodoInput = typeof UpdateTodoInput.Type;\n\nexport class TodoNotFound extends Schema.TaggedErrorClass<TodoNotFound>()(\n \"TodoNotFound\",\n { id: TodoId }\n) {}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nconst migrations: readonly string[] = [\n // v1: reviews table\n `CREATE TABLE IF NOT EXISTS reviews (\n id TEXT PRIMARY KEY,\n repository_path TEXT NOT NULL,\n base_ref TEXT,\n snapshot_data TEXT NOT NULL,\n status TEXT DEFAULT 'in_progress',\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v2: comments table\n `CREATE TABLE IF NOT EXISTS comments (\n id TEXT PRIMARY KEY,\n review_id TEXT NOT NULL REFERENCES reviews(id) ON DELETE CASCADE,\n file_path TEXT NOT NULL,\n line_number INTEGER,\n line_type TEXT,\n content TEXT NOT NULL,\n suggestion TEXT,\n resolved INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v3: add source_type and source_ref to reviews\n `ALTER TABLE reviews ADD COLUMN source_type TEXT DEFAULT 'staged';\n ALTER TABLE reviews ADD COLUMN source_ref TEXT`,\n\n // v4: todos table\n `CREATE TABLE IF NOT EXISTS todos (\n id TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n completed INTEGER DEFAULT 0,\n review_id TEXT REFERENCES reviews(id) ON DELETE CASCADE,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n\n // v5: add position to todos\n `ALTER TABLE todos ADD COLUMN position INTEGER DEFAULT 0`,\n\n // v6: review_files table\n `CREATE TABLE IF NOT EXISTS review_files (\n id TEXT PRIMARY KEY,\n review_id TEXT NOT NULL REFERENCES reviews(id) ON DELETE CASCADE,\n file_path TEXT NOT NULL,\n old_path TEXT,\n status TEXT NOT NULL,\n additions INTEGER NOT NULL DEFAULT 0,\n deletions INTEGER NOT NULL DEFAULT 0,\n hunks_data TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n ) STRICT`,\n];\n\n/** Apply pending migrations using PRAGMA user_version as the version tracker. */\nexport const runMigrations = (db: DatabaseSync): void => {\n const currentVersion = (\n db.prepare(\"PRAGMA user_version\").get() as { user_version: number }\n ).user_version;\n\n for (let i = currentVersion; i < migrations.length; i++) {\n // v3 (and any future multi-statement migration) uses semicolons to\n // separate statements — split and execute each independently.\n const statements = migrations[i]!.split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n for (const sql of statements) {\n db.exec(sql);\n }\n\n db.exec(`PRAGMA user_version = ${i + 1}`);\n }\n};\n","import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Config from \"effect/Config\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Layer from \"effect/Layer\";\n\nimport { runMigrations } from \"./migrations\";\n\n/**\n * Wraps `body` in a SQLite transaction: BEGIN before, COMMIT on success,\n * ROLLBACK on any failure or interruption.\n */\nexport const withTransaction = <A, E, R>(\n db: DatabaseSync,\n body: Effect.Effect<A, E, R>\n): Effect.Effect<A, E, R> =>\n Effect.acquireUseRelease(\n Effect.sync(() => db.exec(\"BEGIN\")),\n () => body,\n (_, exit) =>\n Effect.sync(() => {\n if (Exit.isSuccess(exit)) {\n db.exec(\"COMMIT\");\n } else {\n db.exec(\"ROLLBACK\");\n }\n })\n );\n\nexport class SqliteService extends ServiceMap.Service<\n SqliteService,\n { readonly db: DatabaseSync }\n>()(\"@ringi/SqliteService\") {\n static readonly Default: Layer.Layer<SqliteService, Config.ConfigError> =\n Layer.effect(\n SqliteService,\n Effect.gen(function* () {\n const dbPath = yield* Config.string(\"DB_PATH\").pipe(\n Config.withDefault(\".ringi/reviews.db\")\n );\n\n mkdirSync(dirname(dbPath), { recursive: true });\n\n const db = new DatabaseSync(dbPath);\n db.exec(\"PRAGMA journal_mode=WAL\");\n db.exec(\"PRAGMA foreign_keys=ON\");\n\n runMigrations(db);\n\n return SqliteService.of({ db });\n })\n );\n}\n","import { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport { SqliteService } from \"../db/database\";\nimport type { Comment, CommentId } from \"../schemas/comment\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface CommentRow {\n id: string;\n review_id: string;\n file_path: string;\n line_number: number | null;\n line_type: string | null;\n content: string;\n suggestion: string | null;\n resolved: number; // SQLite stores booleans as 0/1\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToComment = (row: CommentRow): Comment => ({\n content: row.content,\n createdAt: row.created_at,\n filePath: row.file_path,\n id: row.id as CommentId,\n lineNumber: row.line_number,\n lineType: row.line_type as Comment[\"lineType\"],\n resolved: row.resolved === 1,\n reviewId: row.review_id as ReviewId,\n suggestion: row.suggestion,\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class CommentRepo extends ServiceMap.Service<\n CommentRepo,\n {\n findById(id: CommentId): Effect.Effect<Comment | null>;\n findByReview(reviewId: ReviewId): Effect.Effect<readonly Comment[]>;\n findByFile(\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<readonly Comment[]>;\n create(input: {\n id: CommentId;\n reviewId: ReviewId;\n filePath: string;\n lineNumber: number | null;\n lineType: string | null;\n content: string;\n suggestion: string | null;\n }): Effect.Effect<Comment>;\n update(\n id: CommentId,\n updates: { content?: string; suggestion?: string | null }\n ): Effect.Effect<Comment | null>;\n setResolved(\n id: CommentId,\n resolved: boolean\n ): Effect.Effect<Comment | null>;\n remove(id: CommentId): Effect.Effect<boolean>;\n removeByReview(reviewId: ReviewId): Effect.Effect<number>;\n countByReview(reviewId: ReviewId): Effect.Effect<{\n total: number;\n resolved: number;\n unresolved: number;\n withSuggestions: number;\n }>;\n }\n>()(\"@ringi/CommentRepo\") {\n static readonly Default: Layer.Layer<CommentRepo, never, SqliteService> =\n Layer.effect(\n CommentRepo,\n Effect.gen(function* () {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM comments WHERE id = ?\");\n const stmtFindByReview = db.prepare(\n \"SELECT * FROM comments WHERE review_id = ? ORDER BY created_at ASC\"\n );\n const stmtFindByFile = db.prepare(\n \"SELECT * FROM comments WHERE review_id = ? AND file_path = ? ORDER BY line_number ASC, created_at ASC\"\n );\n const stmtInsert = db.prepare(\n `INSERT INTO comments (id, review_id, file_path, line_number, line_type, content, suggestion, resolved, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 0, datetime('now'), datetime('now'))`\n );\n const stmtDelete = db.prepare(\"DELETE FROM comments WHERE id = ?\");\n const stmtDeleteByReview = db.prepare(\n \"DELETE FROM comments WHERE review_id = ?\"\n );\n const stmtSetResolved = db.prepare(\n \"UPDATE comments SET resolved = ?, updated_at = datetime('now') WHERE id = ?\"\n );\n const stmtCountByReview = db.prepare(\n `SELECT\n COUNT(*) as total,\n SUM(CASE WHEN resolved = 1 THEN 1 ELSE 0 END) as resolved,\n SUM(CASE WHEN resolved = 0 THEN 1 ELSE 0 END) as unresolved,\n SUM(CASE WHEN suggestion IS NOT NULL THEN 1 ELSE 0 END) as with_suggestions\n FROM comments WHERE review_id = ?`\n );\n\n const findById = (id: CommentId): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const findByReview = (\n reviewId: ReviewId\n ): Effect.Effect<readonly Comment[]> =>\n Effect.sync(() => {\n const rows = stmtFindByReview.all(\n reviewId\n ) as unknown as CommentRow[];\n return rows.map(rowToComment);\n });\n\n const findByFile = (\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<readonly Comment[]> =>\n Effect.sync(() => {\n const rows = stmtFindByFile.all(\n reviewId,\n filePath\n ) as unknown as CommentRow[];\n return rows.map(rowToComment);\n });\n\n const create = (input: {\n id: CommentId;\n reviewId: ReviewId;\n filePath: string;\n lineNumber: number | null;\n lineType: string | null;\n content: string;\n suggestion: string | null;\n }): Effect.Effect<Comment> =>\n Effect.sync(() => {\n stmtInsert.run(\n input.id,\n input.reviewId,\n input.filePath,\n input.lineNumber,\n input.lineType,\n input.content,\n input.suggestion\n );\n return rowToComment(\n stmtFindById.get(input.id) as unknown as CommentRow\n );\n });\n\n const update = (\n id: CommentId,\n updates: { content?: string; suggestion?: string | null }\n ): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n const setClauses: string[] = [];\n const params: unknown[] = [];\n\n if (updates.content !== undefined) {\n setClauses.push(\"content = ?\");\n params.push(updates.content);\n }\n if (updates.suggestion !== undefined) {\n setClauses.push(\"suggestion = ?\");\n params.push(updates.suggestion);\n }\n\n if (setClauses.length === 0) {\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n }\n\n setClauses.push(\"updated_at = datetime('now')\");\n params.push(id);\n\n db.prepare(\n `UPDATE comments SET ${setClauses.join(\", \")} WHERE id = ?`\n ).run(...(params as import(\"node:sqlite\").SQLInputValue[]));\n\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const setResolved = (\n id: CommentId,\n resolved: boolean\n ): Effect.Effect<Comment | null> =>\n Effect.sync(() => {\n stmtSetResolved.run(resolved ? 1 : 0, id);\n const row = stmtFindById.get(id) as CommentRow | undefined;\n return row ? rowToComment(row) : null;\n });\n\n const remove = (id: CommentId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const removeByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteByReview.run(reviewId);\n return Number(result.changes);\n });\n\n const countByReview = (\n reviewId: ReviewId\n ): Effect.Effect<{\n total: number;\n resolved: number;\n unresolved: number;\n withSuggestions: number;\n }> =>\n Effect.sync(() => {\n const row = stmtCountByReview.get(reviewId) as unknown as {\n total: number;\n resolved: number;\n unresolved: number;\n with_suggestions: number;\n };\n return {\n resolved: row.resolved,\n total: row.total,\n unresolved: row.unresolved,\n withSuggestions: row.with_suggestions,\n };\n });\n\n return CommentRepo.of({\n countByReview,\n create,\n findByFile,\n findById,\n findByReview,\n remove,\n removeByReview,\n setResolved,\n update,\n });\n })\n );\n}\n","import * as Schema from \"effect/Schema\";\n\nimport { ReviewId } from \"./review\";\n\nexport const CommentId = Schema.String.pipe(Schema.brand(\"CommentId\"));\nexport type CommentId = typeof CommentId.Type;\n\nexport const LineType = Schema.Literals([\"added\", \"removed\", \"context\"]);\nexport type LineType = typeof LineType.Type;\n\nexport const Comment = Schema.Struct({\n content: Schema.String,\n createdAt: Schema.String,\n filePath: Schema.String,\n id: CommentId,\n lineNumber: Schema.NullOr(Schema.Number),\n lineType: Schema.NullOr(LineType),\n resolved: Schema.Boolean,\n reviewId: ReviewId,\n suggestion: Schema.NullOr(Schema.String),\n updatedAt: Schema.String,\n});\nexport type Comment = typeof Comment.Type;\n\nexport const CreateCommentInput = Schema.Struct({\n content: Schema.String.pipe(Schema.check(Schema.isMinLength(1))),\n filePath: Schema.String.pipe(Schema.check(Schema.isMinLength(1))),\n lineNumber: Schema.NullOr(Schema.Number).pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => null)\n ),\n lineType: Schema.NullOr(LineType).pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => null)\n ),\n suggestion: Schema.NullOr(Schema.String).pipe(\n Schema.optionalKey,\n Schema.withDecodingDefaultKey(() => null)\n ),\n});\nexport type CreateCommentInput = typeof CreateCommentInput.Type;\n\nexport const UpdateCommentInput = Schema.Struct({\n content: Schema.OptionFromNullOr(\n Schema.String.pipe(Schema.check(Schema.isMinLength(1)))\n ).pipe(Schema.optionalKey),\n suggestion: Schema.OptionFromNullOr(Schema.NullOr(Schema.String)).pipe(\n Schema.optionalKey\n ),\n});\nexport type UpdateCommentInput = typeof UpdateCommentInput.Type;\n\nexport class CommentNotFound extends Schema.TaggedErrorClass<CommentNotFound>()(\n \"CommentNotFound\",\n { id: CommentId }\n) {}\n","import { randomUUID } from \"node:crypto\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\n\nimport { CommentRepo } from \"../repos/comment.repo\";\nimport type {\n CommentId,\n CreateCommentInput,\n UpdateCommentInput,\n} from \"../schemas/comment\";\nimport { CommentNotFound } from \"../schemas/comment\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class CommentService extends ServiceMap.Service<\n CommentService,\n {\n create(reviewId: ReviewId, input: CreateCommentInput): Effect.Effect<any>;\n getById(id: CommentId): Effect.Effect<any, CommentNotFound>;\n getByReview(reviewId: ReviewId): Effect.Effect<any>;\n getByFile(reviewId: ReviewId, filePath: string): Effect.Effect<any>;\n update(\n id: CommentId,\n input: UpdateCommentInput\n ): Effect.Effect<any, CommentNotFound>;\n resolve(id: CommentId): Effect.Effect<any, CommentNotFound>;\n unresolve(id: CommentId): Effect.Effect<any, CommentNotFound>;\n remove(id: CommentId): Effect.Effect<{ success: true }, CommentNotFound>;\n getStats(reviewId: ReviewId): Effect.Effect<any>;\n }\n>()(\"@ringi/CommentService\") {\n static readonly Default: Layer.Layer<CommentService, never, CommentRepo> =\n Layer.effect(\n CommentService,\n Effect.gen(function* () {\n // Capture the repo at layer-creation time\n const repo = yield* CommentRepo;\n\n const create = (reviewId: ReviewId, input: CreateCommentInput) => {\n const id = randomUUID() as CommentId;\n return repo.create({\n content: input.content,\n filePath: input.filePath,\n id,\n lineNumber: input.lineNumber ?? null,\n lineType: input.lineType ?? null,\n reviewId,\n suggestion: input.suggestion ?? null,\n });\n };\n\n const getById = (id: CommentId) =>\n Effect.gen(function* () {\n const comment = yield* repo.findById(id);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n const getByReview = (reviewId: ReviewId) => repo.findByReview(reviewId);\n\n const getByFile = (reviewId: ReviewId, filePath: string) =>\n repo.findByFile(reviewId, filePath);\n\n const update = (id: CommentId, input: UpdateCommentInput) =>\n Effect.gen(function* () {\n const updates: { content?: string; suggestion?: string | null } =\n {};\n if (input.content && Option.isSome(input.content)) {\n updates.content = input.content.value;\n }\n if (input.suggestion && Option.isSome(input.suggestion)) {\n updates.suggestion = input.suggestion.value;\n }\n\n const comment = yield* repo.update(id, updates);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n const resolve = (id: CommentId) =>\n Effect.gen(function* () {\n const comment = yield* repo.setResolved(id, true);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n const unresolve = (id: CommentId) =>\n Effect.gen(function* () {\n const comment = yield* repo.setResolved(id, false);\n if (!comment) {\n return yield* new CommentNotFound({ id });\n }\n return comment;\n });\n\n const remove = (id: CommentId) =>\n Effect.gen(function* () {\n const existed = yield* repo.remove(id);\n if (!existed) {\n return yield* new CommentNotFound({ id });\n }\n return { success: true as const };\n });\n\n const getStats = (reviewId: ReviewId) => repo.countByReview(reviewId);\n\n return CommentService.of({\n create,\n getByFile,\n getById,\n getByReview,\n getStats,\n remove,\n resolve,\n unresolve,\n update,\n });\n })\n );\n}\n","import type {\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffSummary,\n} from \"../schemas/diff\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst HUNK_HEADER = /@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/;\n\nconst splitIntoFiles = (diffText: string): readonly string[] => {\n const files: string[] = [];\n const lines = diffText.split(\"\\n\");\n let current: string[] = [];\n for (const line of lines) {\n if (line.startsWith(\"diff --git\")) {\n if (current.length > 0) {\n files.push(current.join(\"\\n\"));\n }\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) {\n files.push(current.join(\"\\n\"));\n }\n return files;\n};\n\nconst parseHunks = (lines: readonly string[]): readonly DiffHunk[] => {\n const hunks: DiffHunk[] = [];\n let currentHunk: {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n lines: DiffLine[];\n } | null = null;\n let oldLineNum = 0;\n let newLineNum = 0;\n\n for (const line of lines) {\n const match = line.match(HUNK_HEADER);\n if (match) {\n if (currentHunk) {\n hunks.push(currentHunk);\n }\n const oldStart = Number.parseInt(match[1]!, 10);\n const oldLines = Number.parseInt(match[2] ?? \"1\", 10);\n const newStart = Number.parseInt(match[3]!, 10);\n const newLines = Number.parseInt(match[4] ?? \"1\", 10);\n currentHunk = { lines: [], newLines, newStart, oldLines, oldStart };\n oldLineNum = oldStart;\n newLineNum = newStart;\n continue;\n }\n\n if (!currentHunk) {\n continue;\n }\n\n if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: newLineNum++,\n oldLineNumber: null,\n type: \"added\",\n });\n } else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: null,\n oldLineNumber: oldLineNum++,\n type: \"removed\",\n });\n } else if (line.startsWith(\" \")) {\n currentHunk.lines.push({\n content: line.slice(1),\n newLineNumber: newLineNum++,\n oldLineNumber: oldLineNum++,\n type: \"context\",\n });\n }\n // Skip '\\\', '---', '+++', 'index', mode lines\n }\n\n if (currentHunk) {\n hunks.push(currentHunk);\n }\n return hunks;\n};\n\nconst parseFileDiff = (fileDiff: string): DiffFile | null => {\n const lines = fileDiff.split(\"\\n\");\n const diffLine = lines.find((l) => l.startsWith(\"diff --git\"));\n if (!diffLine) {\n return null;\n }\n\n const pathMatch = diffLine.match(/diff --git a\\/(.+) b\\/(.+)/);\n if (!pathMatch) {\n return null;\n }\n\n const oldPath = pathMatch[1]!;\n const newPath = pathMatch[2]!;\n\n // Status detection (priority order)\n let status: DiffFile[\"status\"] = \"modified\";\n if (lines.some((l) => l.startsWith(\"deleted file mode\"))) {\n status = \"deleted\";\n } else if (lines.some((l) => l.startsWith(\"new file mode\"))) {\n status = \"added\";\n } else if (\n lines.some((l) => l.startsWith(\"rename from\")) ||\n oldPath !== newPath\n ) {\n status = \"renamed\";\n }\n\n const hunks = parseHunks(lines);\n\n let additions = 0;\n let deletions = 0;\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.type === \"added\") {\n additions++;\n } else if (line.type === \"removed\") {\n deletions++;\n }\n }\n }\n\n return { additions, deletions, hunks, newPath, oldPath, status };\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Parse a full multi-file unified diff into structured DiffFile objects. */\nexport const parseDiff = (diffText: string): readonly DiffFile[] => {\n if (!diffText.trim()) {\n return [];\n }\n const blocks = splitIntoFiles(diffText);\n const files: DiffFile[] = [];\n for (const block of blocks) {\n const parsed = parseFileDiff(block);\n if (parsed) {\n files.push(parsed);\n }\n }\n return files;\n};\n\n/** Parse a unified diff and return only the first file, or null. */\nexport const parseSingleFileDiff = (diffText: string): DiffFile | null => {\n const files = parseDiff(diffText);\n return files[0] ?? null;\n};\n\n/** Aggregate stats from already-parsed files. */\nexport const getDiffSummary = (files: readonly DiffFile[]): DiffSummary => {\n let totalAdditions = 0;\n let totalDeletions = 0;\n for (const file of files) {\n totalAdditions += file.additions;\n totalDeletions += file.deletions;\n }\n return {\n filesAdded: files.filter((f) => f.status === \"added\").length,\n filesDeleted: files.filter((f) => f.status === \"deleted\").length,\n filesModified: files.filter((f) => f.status === \"modified\").length,\n filesRenamed: files.filter((f) => f.status === \"renamed\").length,\n totalAdditions,\n totalDeletions,\n totalFiles: files.length,\n };\n};\n","import { randomUUID } from \"node:crypto\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport { SqliteService, withTransaction } from \"../db/database\";\nimport type { DiffHunk } from \"../schemas/diff\";\nimport type { ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shapes\n// ---------------------------------------------------------------------------\n\ninterface ReviewFileRow {\n id: string;\n review_id: string;\n file_path: string;\n old_path: string | null;\n status: string;\n additions: number;\n deletions: number;\n hunks_data: string | null;\n created_at: string;\n}\n\ninterface ReviewFileMetadataRow {\n id: string;\n review_id: string;\n file_path: string;\n old_path: string | null;\n status: string;\n additions: number;\n deletions: number;\n created_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input type for bulk creation\n// ---------------------------------------------------------------------------\n\nexport interface CreateReviewFileInput {\n readonly reviewId: ReviewId;\n readonly filePath: string;\n readonly oldPath: string | null;\n readonly status: string;\n readonly additions: number;\n readonly deletions: number;\n readonly hunksData: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Static helpers\n// ---------------------------------------------------------------------------\n\nexport const parseHunks = (\n hunksData: string | null\n): Effect.Effect<readonly DiffHunk[]> =>\n hunksData == null\n ? Effect.succeed([])\n : Effect.try({\n try: () => JSON.parse(hunksData) as readonly DiffHunk[],\n catch: () => [] as readonly DiffHunk[],\n }).pipe(Effect.orElseSucceed(() => [] as readonly DiffHunk[]));\n\nexport const serializeHunks = (hunks: readonly DiffHunk[]): string =>\n JSON.stringify(hunks);\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ReviewFileRepo extends ServiceMap.Service<\n ReviewFileRepo,\n {\n findByReview(\n reviewId: ReviewId\n ): Effect.Effect<readonly ReviewFileMetadataRow[]>;\n findByReviewAndPath(\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<ReviewFileRow | null>;\n createBulk(files: readonly CreateReviewFileInput[]): Effect.Effect<void>;\n deleteByReview(reviewId: ReviewId): Effect.Effect<number>;\n countByReview(reviewId: ReviewId): Effect.Effect<number>;\n }\n>()(\"@ringi/ReviewFileRepo\") {\n static readonly Default: Layer.Layer<ReviewFileRepo, never, SqliteService> =\n Layer.effect(\n ReviewFileRepo,\n Effect.gen(function* () {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements\n const stmtFindByReview = db.prepare(\n `SELECT id, review_id, file_path, old_path, status, additions, deletions, created_at\n FROM review_files WHERE review_id = ? ORDER BY file_path`\n );\n const stmtFindByReviewAndPath = db.prepare(\n \"SELECT * FROM review_files WHERE review_id = ? AND file_path = ?\"\n );\n const stmtInsert = db.prepare(\n `INSERT INTO review_files (id, review_id, file_path, old_path, status, additions, deletions, hunks_data, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`\n );\n const stmtDeleteByReview = db.prepare(\n \"DELETE FROM review_files WHERE review_id = ?\"\n );\n const stmtCountByReview = db.prepare(\n \"SELECT COUNT(*) as count FROM review_files WHERE review_id = ?\"\n );\n\n const findByReview = (\n reviewId: ReviewId\n ): Effect.Effect<readonly ReviewFileMetadataRow[]> =>\n Effect.sync(\n () =>\n stmtFindByReview.all(\n reviewId\n ) as unknown as ReviewFileMetadataRow[]\n );\n\n const findByReviewAndPath = (\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<ReviewFileRow | null> =>\n Effect.sync(() => {\n const row = stmtFindByReviewAndPath.get(\n reviewId,\n filePath\n ) as unknown as ReviewFileRow | undefined;\n return row ?? null;\n });\n\n const createBulk = (\n files: readonly CreateReviewFileInput[]\n ): Effect.Effect<void> =>\n withTransaction(\n db,\n Effect.sync(() => {\n for (const f of files) {\n stmtInsert.run(\n randomUUID(),\n f.reviewId,\n f.filePath,\n f.oldPath,\n f.status,\n f.additions,\n f.deletions,\n f.hunksData\n );\n }\n })\n );\n\n const deleteByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteByReview.run(reviewId);\n return Number(result.changes);\n });\n\n const countByReview = (reviewId: ReviewId): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountByReview.get(reviewId) as { count: number };\n return row.count;\n });\n\n return ReviewFileRepo.of({\n countByReview,\n createBulk,\n deleteByReview,\n findByReview,\n findByReviewAndPath,\n });\n })\n );\n}\n","import { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport { SqliteService } from \"../db/database\";\nimport type { Review, ReviewId } from \"../schemas/review\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface ReviewRow {\n id: string;\n repository_path: string;\n base_ref: string | null;\n source_type: string;\n source_ref: string | null;\n snapshot_data: string;\n status: string;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToReview = (row: ReviewRow): Review => ({\n baseRef: row.base_ref,\n createdAt: row.created_at,\n id: row.id as ReviewId,\n repositoryPath: row.repository_path,\n snapshotData: row.snapshot_data,\n sourceRef: row.source_ref,\n sourceType: row.source_type as Review[\"sourceType\"],\n status: row.status as Review[\"status\"],\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\ninterface FindAllOpts {\n readonly status?: string;\n readonly repositoryPath?: string;\n readonly sourceType?: string;\n readonly page?: number;\n readonly pageSize?: number;\n}\n\nexport class ReviewRepo extends ServiceMap.Service<\n ReviewRepo,\n {\n findById(id: ReviewId): Effect.Effect<Review | null>;\n findAll(\n opts?: FindAllOpts\n ): Effect.Effect<{ data: readonly Review[]; total: number }>;\n create(input: {\n id: ReviewId;\n repositoryPath: string;\n baseRef: string | null;\n sourceType: string;\n sourceRef: string | null;\n snapshotData: string;\n status: string;\n }): Effect.Effect<Review>;\n update(id: ReviewId, status: string | null): Effect.Effect<Review | null>;\n updateSnapshotData(\n id: ReviewId,\n snapshotData: string\n ): Effect.Effect<Review | null>;\n remove(id: ReviewId): Effect.Effect<boolean>;\n countAll(): Effect.Effect<number>;\n countByStatus(status: string): Effect.Effect<number>;\n }\n>()(\"@ringi/ReviewRepo\") {\n static readonly Default: Layer.Layer<ReviewRepo, never, SqliteService> =\n Layer.effect(\n ReviewRepo,\n Effect.gen(function* () {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM reviews WHERE id = ?\");\n const stmtInsert = db.prepare(\n `INSERT INTO reviews (id, repository_path, base_ref, source_type, source_ref, snapshot_data, status, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))`\n );\n const stmtUpdate = db.prepare(\n `UPDATE reviews SET status = COALESCE(?, status), updated_at = datetime('now') WHERE id = ?`\n );\n const stmtUpdateSnapshot = db.prepare(\n `UPDATE reviews SET snapshot_data = ?, updated_at = datetime('now') WHERE id = ?`\n );\n const stmtDelete = db.prepare(\"DELETE FROM reviews WHERE id = ?\");\n const stmtCountAll = db.prepare(\n \"SELECT COUNT(*) as count FROM reviews\"\n );\n const stmtCountByStatus = db.prepare(\n \"SELECT COUNT(*) as count FROM reviews WHERE status = ?\"\n );\n\n const findById = (id: ReviewId): Effect.Effect<Review | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as ReviewRow | undefined;\n return row ? rowToReview(row) : null;\n });\n\n const findAll = (\n opts: FindAllOpts = {}\n ): Effect.Effect<{ data: readonly Review[]; total: number }> =>\n Effect.sync(() => {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.status != null) {\n conditions.push(\"status = ?\");\n params.push(opts.status);\n }\n if (opts.repositoryPath != null) {\n conditions.push(\"repository_path = ?\");\n params.push(opts.repositoryPath);\n }\n if (opts.sourceType != null) {\n conditions.push(\"source_type = ?\");\n params.push(opts.sourceType);\n }\n\n const where =\n conditions.length > 0 ? ` WHERE ${conditions.join(\" AND \")}` : \"\";\n\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n const offset = (page - 1) * pageSize;\n\n const totalRow = db\n .prepare(`SELECT COUNT(*) as count FROM reviews${where}`)\n .get(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as { count: number };\n\n const rows = db\n .prepare(\n `SELECT * FROM reviews${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`\n )\n .all(\n ...(params as import(\"node:sqlite\").SQLInputValue[]),\n pageSize,\n offset\n ) as unknown as ReviewRow[];\n\n return { data: rows.map(rowToReview), total: totalRow.count };\n });\n\n const create = (input: {\n id: ReviewId;\n repositoryPath: string;\n baseRef: string | null;\n sourceType: string;\n sourceRef: string | null;\n snapshotData: string;\n status: string;\n }): Effect.Effect<Review> =>\n Effect.sync(() => {\n stmtInsert.run(\n input.id,\n input.repositoryPath,\n input.baseRef,\n input.sourceType,\n input.sourceRef,\n input.snapshotData,\n input.status\n );\n return rowToReview(\n stmtFindById.get(input.id) as unknown as ReviewRow\n );\n });\n\n const update = (\n id: ReviewId,\n status: string | null\n ): Effect.Effect<Review | null> =>\n Effect.sync(() => {\n stmtUpdate.run(status, id);\n const row = stmtFindById.get(id) as ReviewRow | undefined;\n return row ? rowToReview(row) : null;\n });\n\n const updateSnapshotData = (\n id: ReviewId,\n snapshotData: string\n ): Effect.Effect<Review | null> =>\n Effect.sync(() => {\n stmtUpdateSnapshot.run(snapshotData, id);\n const row = stmtFindById.get(id) as ReviewRow | undefined;\n return row ? rowToReview(row) : null;\n });\n\n const remove = (id: ReviewId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const countAll = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountAll.get() as { count: number };\n return row.count;\n });\n\n const countByStatus = (status: string): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountByStatus.get(status) as { count: number };\n return row.count;\n });\n\n return ReviewRepo.of({\n countAll,\n countByStatus,\n create,\n findAll,\n findById,\n remove,\n update,\n updateSnapshotData,\n });\n })\n );\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Config from \"effect/Config\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schema from \"effect/Schema\";\n\n// ---------------------------------------------------------------------------\n// Error\n// ---------------------------------------------------------------------------\n\nexport class GitError extends Schema.TaggedErrorClass<GitError>()(\"GitError\", {\n message: Schema.String,\n}) {}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Max bytes to collect from a git command before truncating (200 MB). */\nconst MAX_STDOUT_BYTES = 200 * 1024 * 1024;\n\nconst execGit = (args: readonly string[], repoPath: string) =>\n Effect.tryPromise({\n catch: (error) => new GitError({ message: String(error) }),\n try: () =>\n new Promise<string>((resolve, reject) => {\n const child = spawn(\"git\", [...args], { cwd: repoPath });\n\n const chunks: Buffer[] = [];\n let bytes = 0;\n let truncated = false;\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n if (truncated) {\n return;\n }\n bytes += chunk.length;\n if (bytes > MAX_STDOUT_BYTES) {\n truncated = true;\n child.kill();\n return;\n }\n chunks.push(chunk);\n });\n\n let stderr = \"\";\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n child.on(\"error\", reject);\n\n child.on(\"close\", (code) => {\n if (truncated) {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n return;\n }\n if (code !== 0) {\n reject(\n new Error(`git ${args[0]} exited with code ${code}: ${stderr}`)\n );\n } else {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n }\n });\n }),\n });\n\n/** Split git output into non-empty lines. */\nconst lines = (output: string): string[] =>\n output.trim().split(\"\\n\").filter(Boolean);\n\n/** Parse name-status output (e.g. `M\\tfile.ts`). */\nconst parseNameStatus = (output: string) =>\n lines(output).map((line) => {\n const [status, ...rest] = line.split(\"\\t\");\n return { path: rest.join(\"\\t\"), status: status! };\n });\n\n// ---------------------------------------------------------------------------\n// Service interface\n// ---------------------------------------------------------------------------\n\ninterface GitServiceShape {\n readonly hasCommits: Effect.Effect<boolean, GitError>;\n readonly getRepositoryInfo: Effect.Effect<\n { branch: string; name: string; path: string; remote: string | null },\n GitError\n >;\n readonly getStagedDiff: Effect.Effect<string, GitError>;\n readonly getUncommittedDiff: Effect.Effect<string, GitError>;\n readonly getUnstagedDiff: Effect.Effect<string, GitError>;\n readonly getLastCommitDiff: Effect.Effect<string, GitError>;\n getBranchDiff(branch: string): Effect.Effect<string, GitError>;\n getCommitDiff(shas: readonly string[]): Effect.Effect<string, GitError>;\n readonly getStagedFiles: Effect.Effect<\n { path: string; status: string }[],\n GitError\n >;\n readonly getUncommittedFiles: Effect.Effect<\n { path: string; status: string }[],\n GitError\n >;\n readonly getUnstagedFiles: Effect.Effect<\n { path: string; status: string }[],\n GitError\n >;\n readonly getLastCommitFiles: Effect.Effect<\n { path: string; status: string }[],\n GitError\n >;\n getFileContent(\n filePath: string,\n version: \"staged\" | \"head\" | \"working\"\n ): Effect.Effect<string, GitError>;\n getFileTree(ref: string): Effect.Effect<string[], GitError>;\n readonly getBranches: Effect.Effect<\n { current: boolean; name: string }[],\n GitError\n >;\n getCommits(opts: {\n limit?: number;\n offset?: number;\n search?: string;\n }): Effect.Effect<\n {\n commits: {\n author: string;\n date: string;\n hash: string;\n message: string;\n }[];\n hasMore: boolean;\n },\n GitError\n >;\n stageFiles(\n files: readonly string[]\n ): Effect.Effect<readonly string[], GitError>;\n readonly stageAll: Effect.Effect<string[], GitError>;\n unstageFiles(\n files: readonly string[]\n ): Effect.Effect<readonly string[], GitError>;\n readonly getRepositoryPath: Effect.Effect<string, GitError>;\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class GitService extends ServiceMap.Service<\n GitService,\n GitServiceShape\n>()(\"@ringi/GitService\") {\n static readonly Default: Layer.Layer<GitService, Config.ConfigError> =\n Layer.effect(\n GitService,\n Effect.gen(function* () {\n const repoPath = yield* Config.string(\"REPOSITORY_PATH\").pipe(\n Config.withDefault(process.cwd())\n );\n\n // -- repo state --------------------------------------------------------\n\n const hasCommits = execGit([\"rev-parse\", \"HEAD\"], repoPath).pipe(\n Effect.as(true),\n Effect.catchTag(\"GitError\", () => Effect.succeed(false)),\n Effect.withSpan(\"GitService.hasCommits\")\n );\n\n // -- repository info --------------------------------------------------\n\n const getRepositoryInfo = Effect.gen(function* () {\n const name = yield* execGit(\n [\"rev-parse\", \"--show-toplevel\"],\n repoPath\n ).pipe(Effect.map((s) => s.trim().split(\"/\").pop() ?? \"unknown\"));\n\n const branch = yield* execGit(\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n repoPath\n ).pipe(Effect.map((s) => s.trim()));\n\n const remote = yield* execGit(\n [\"config\", \"--get\", \"remote.origin.url\"],\n repoPath\n ).pipe(\n Effect.map((s) => s.trim() || null),\n Effect.catchTag(\"GitError\", () => Effect.succeed(null))\n );\n\n return { branch, name, path: repoPath, remote };\n }).pipe(Effect.withSpan(\"GitService.getRepositoryInfo\"));\n\n // -- diffs -------------------------------------------------------------\n\n const getStagedDiff = execGit(\n [\"diff\", \"--cached\", \"--no-color\", \"--unified=3\"],\n repoPath\n ).pipe(Effect.withSpan(\"GitService.getStagedDiff\"));\n\n const getUncommittedDiff = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit([\"diff\", \"HEAD\", \"--no-color\", \"--unified=3\"], repoPath)\n : Effect.succeed(\"\")\n ),\n Effect.withSpan(\"GitService.getUncommittedDiff\")\n );\n\n const getUnstagedDiff = execGit(\n [\"diff\", \"--no-color\", \"--unified=3\"],\n repoPath\n ).pipe(Effect.withSpan(\"GitService.getUnstagedDiff\"));\n\n const getLastCommitDiff = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit(\n [\"show\", \"HEAD\", \"--format=\", \"--no-color\", \"--unified=3\"],\n repoPath\n )\n : Effect.succeed(\"\")\n ),\n Effect.withSpan(\"GitService.getLastCommitDiff\")\n );\n\n const getBranchDiff = Effect.fn(\"GitService.getBranchDiff\")(function* (\n branch: string\n ) {\n return yield* execGit(\n [\"diff\", `${branch}...HEAD`, \"--no-color\", \"--unified=3\"],\n repoPath\n );\n });\n\n const getCommitDiff = Effect.fn(\"GitService.getCommitDiff\")(function* (\n shas: readonly string[]\n ) {\n if (shas.length === 1) {\n return yield* execGit(\n [\"show\", shas[0]!, \"--format=\", \"--no-color\", \"--unified=3\"],\n repoPath\n );\n }\n const first = shas.at(-1)!;\n const last = shas[0]!;\n return yield* execGit(\n [\"diff\", `${first}~1..${last}`, \"--no-color\", \"--unified=3\"],\n repoPath\n );\n });\n\n // -- file lists --------------------------------------------------------\n\n const getStagedFiles = execGit(\n [\"diff\", \"--cached\", \"--name-status\"],\n repoPath\n ).pipe(\n Effect.map(parseNameStatus),\n Effect.withSpan(\"GitService.getStagedFiles\")\n );\n\n const getUncommittedFiles = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit([\"diff\", \"HEAD\", \"--name-status\"], repoPath).pipe(\n Effect.map(parseNameStatus)\n )\n : Effect.succeed([])\n ),\n Effect.withSpan(\"GitService.getUncommittedFiles\")\n );\n\n const getUnstagedFiles = execGit(\n [\"diff\", \"--name-status\"],\n repoPath\n ).pipe(\n Effect.map(parseNameStatus),\n Effect.withSpan(\"GitService.getUnstagedFiles\")\n );\n\n const getLastCommitFiles = hasCommits.pipe(\n Effect.flatMap((has) =>\n has\n ? execGit(\n [\"show\", \"HEAD\", \"--format=\", \"--name-status\"],\n repoPath\n ).pipe(Effect.map(parseNameStatus))\n : Effect.succeed([])\n ),\n Effect.withSpan(\"GitService.getLastCommitFiles\")\n );\n\n // -- file content ------------------------------------------------------\n\n const getFileContent = Effect.fn(\"GitService.getFileContent\")(\n function* (filePath: string, version: \"staged\" | \"head\" | \"working\") {\n switch (version) {\n case \"staged\": {\n return yield* execGit([\"show\", `:${filePath}`], repoPath);\n }\n case \"head\": {\n return yield* execGit([\"show\", `HEAD:${filePath}`], repoPath);\n }\n case \"working\":\n default: {\n return yield* Effect.tryPromise({\n catch: (error) =>\n new GitError({\n message: `Failed to read ${filePath}: ${String(error)}`,\n }),\n try: () => readFile(join(repoPath, filePath), \"utf8\"),\n });\n }\n }\n }\n );\n\n // -- tree / branches / commits -----------------------------------------\n\n const getFileTree = Effect.fn(\"GitService.getFileTree\")(function* (\n ref: string\n ) {\n return yield* execGit(\n [\"ls-tree\", \"-r\", \"--name-only\", ref],\n repoPath\n ).pipe(Effect.map(lines));\n });\n\n const getBranches = execGit(\n [\"branch\", \"--format=%(refname:short)\\t%(HEAD)\"],\n repoPath\n ).pipe(\n Effect.map((output) =>\n lines(output).map((line) => {\n const [name, head] = line.split(\"\\t\");\n return { current: head === \"*\", name: name! };\n })\n ),\n Effect.withSpan(\"GitService.getBranches\")\n );\n\n const getCommits = Effect.fn(\"GitService.getCommits\")(function* (opts: {\n limit?: number;\n offset?: number;\n search?: string;\n }) {\n const limit = (opts.limit ?? 20) + 1; // +1 to detect hasMore\n const args = [\n \"log\",\n `--max-count=${limit}`,\n `--skip=${opts.offset ?? 0}`,\n \"--format=%H\\t%s\\t%an\\t%aI\",\n ];\n if (opts.search) {\n args.push(`--grep=${opts.search}`, \"-i\");\n }\n\n const output = yield* execGit(args, repoPath);\n const rows = lines(output);\n const hasMore = rows.length === limit;\n const commits = (hasMore ? rows.slice(0, -1) : rows).map((line) => {\n const [hash, message, author, date] = line.split(\"\\t\");\n return {\n author: author!,\n date: date!,\n hash: hash!,\n message: message!,\n };\n });\n return { commits, hasMore };\n });\n\n // -- staging operations ------------------------------------------------\n\n const stageFiles = Effect.fn(\"GitService.stageFiles\")(function* (\n files: readonly string[]\n ) {\n return yield* execGit([\"add\", \"--\", ...files], repoPath).pipe(\n Effect.as(files)\n );\n });\n\n const stageAll = execGit([\"add\", \"-A\"], repoPath).pipe(\n Effect.flatMap(() => getStagedFiles),\n Effect.map((files) => files.map((f) => f.path)),\n Effect.withSpan(\"GitService.stageAll\")\n );\n\n const unstageFiles = Effect.fn(\"GitService.unstageFiles\")(function* (\n files: readonly string[]\n ) {\n return yield* execGit(\n [\"reset\", \"HEAD\", \"--\", ...files],\n repoPath\n ).pipe(Effect.as(files));\n });\n\n const getRepositoryPath = execGit(\n [\"rev-parse\", \"--show-toplevel\"],\n repoPath\n ).pipe(\n Effect.map((s) => s.trim()),\n Effect.withSpan(\"GitService.getRepositoryPath\")\n );\n\n // -- public interface --------------------------------------------------\n\n return GitService.of({\n getBranchDiff,\n getBranches,\n getCommitDiff,\n getCommits,\n getFileContent,\n getFileTree,\n getLastCommitDiff,\n getLastCommitFiles,\n getRepositoryInfo,\n getRepositoryPath,\n getStagedDiff,\n getStagedFiles,\n getUncommittedDiff,\n getUncommittedFiles,\n getUnstagedDiff,\n getUnstagedFiles,\n hasCommits,\n stageAll,\n stageFiles,\n unstageFiles,\n });\n })\n );\n}\n","import { execFile } from \"node:child_process\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\n\nimport {\n ReviewFileRepo,\n parseHunks,\n serializeHunks,\n} from \"../repos/review-file.repo\";\nimport { ReviewRepo } from \"../repos/review.repo\";\nimport type { DiffFile, DiffHunk } from \"../schemas/diff\";\nimport type {\n CreateReviewInput,\n ReviewId,\n ReviewStatus,\n UpdateReviewInput,\n} from \"../schemas/review\";\nimport { ReviewNotFound } from \"../schemas/review\";\nimport { parseDiff, getDiffSummary } from \"../services/diff.service\";\nimport { GitService } from \"../services/git.service\";\n\n// ---------------------------------------------------------------------------\n// Error\n// ---------------------------------------------------------------------------\n\nexport class ReviewError extends Schema.TaggedErrorClass<ReviewError>()(\n \"ReviewError\",\n { code: Schema.String, message: Schema.String }\n) {}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst getHeadSha = (repoPath: string) =>\n Effect.tryPromise({\n catch: () =>\n new ReviewError({ code: \"GIT_ERROR\", message: \"Failed to get HEAD\" }),\n try: () =>\n new Promise<string>((resolve, reject) => {\n execFile(\n \"git\",\n [\"rev-parse\", \"HEAD\"],\n { cwd: repoPath },\n (err, stdout) => {\n if (err) {\n reject(err);\n } else {\n resolve(stdout.trim());\n }\n }\n );\n }),\n });\n\ninterface SnapshotData {\n repository?: Record<string, unknown>;\n files?: DiffFile[];\n version?: number;\n}\n\nconst parseSnapshotData = (s: string): Effect.Effect<SnapshotData> =>\n Effect.try({\n try: () => JSON.parse(s) as SnapshotData,\n catch: () => ({}) as SnapshotData,\n }).pipe(Effect.orElseSucceed((): SnapshotData => ({})));\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ReviewService extends ServiceMap.Service<\n ReviewService,\n {\n create(\n input: CreateReviewInput\n ): Effect.Effect<\n any,\n ReviewError | ReviewNotFound | import(\"./git.service\").GitError\n >;\n list(opts: {\n page?: number;\n pageSize?: number;\n status?: ReviewStatus;\n repositoryPath?: string;\n sourceType?: string;\n }): Effect.Effect<any>;\n getById(id: ReviewId): Effect.Effect<any, ReviewNotFound>;\n getFileHunks(\n reviewId: ReviewId,\n filePath: string\n ): Effect.Effect<\n readonly DiffHunk[],\n ReviewNotFound | import(\"./git.service\").GitError\n >;\n update(\n id: ReviewId,\n input: UpdateReviewInput\n ): Effect.Effect<any, ReviewNotFound>;\n remove(id: ReviewId): Effect.Effect<{ success: true }, ReviewNotFound>;\n getStats(): Effect.Effect<{\n approved: number;\n changesRequested: number;\n inProgress: number;\n total: number;\n }>;\n }\n>()(\"@ringi/ReviewService\") {\n static readonly Default: Layer.Layer<\n ReviewService,\n never,\n ReviewRepo | ReviewFileRepo | GitService\n > = Layer.effect(\n ReviewService,\n Effect.gen(function* () {\n const git = yield* GitService;\n const repo = yield* ReviewRepo;\n const fileRepo = yield* ReviewFileRepo;\n\n const create = (input: CreateReviewInput) =>\n Effect.gen(function* () {\n const repoPath = yield* git.getRepositoryPath;\n const hasCommitsResult = yield* git.hasCommits;\n if (!hasCommitsResult) {\n return yield* new ReviewError({\n code: \"NO_COMMITS\",\n message: \"Repository has no commits\",\n });\n }\n\n let diffText: string;\n let baseRef: string | null = null;\n const { sourceType, sourceRef } = input;\n\n switch (sourceType) {\n case \"staged\": {\n diffText = yield* git.getStagedDiff;\n if (!diffText.trim()) {\n return yield* new ReviewError({\n code: \"NO_STAGED_CHANGES\",\n message: \"No staged changes\",\n });\n }\n baseRef = yield* getHeadSha(repoPath);\n break;\n }\n case \"branch\": {\n if (!sourceRef) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Branch name required\",\n });\n }\n diffText = yield* git.getBranchDiff(sourceRef);\n baseRef = sourceRef;\n break;\n }\n case \"commits\": {\n if (!sourceRef) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Commit SHAs required\",\n });\n }\n const shas = sourceRef\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n if (shas.length === 0) {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"No valid commit SHAs\",\n });\n }\n diffText = yield* git.getCommitDiff(shas);\n baseRef = shas.at(-1) ?? null;\n break;\n }\n default: {\n return yield* new ReviewError({\n code: \"INVALID_SOURCE\",\n message: \"Unsupported review source\",\n });\n }\n }\n\n const files = parseDiff(diffText);\n if (files.length === 0) {\n return yield* new ReviewError({\n code: \"NO_CHANGES\",\n message: \"No changes found\",\n });\n }\n\n const repoInfo = yield* git.getRepositoryInfo;\n const reviewId = crypto.randomUUID() as ReviewId;\n const storeHunks = sourceType === \"staged\";\n\n const fileInputs = files.map((f) => ({\n additions: f.additions,\n deletions: f.deletions,\n filePath: f.newPath,\n hunksData: storeHunks\n ? serializeHunks(f.hunks as DiffHunk[])\n : null,\n oldPath: f.oldPath !== f.newPath ? f.oldPath : null,\n reviewId,\n status: f.status,\n }));\n\n const snapshotData = JSON.stringify({\n repository: repoInfo,\n version: 2,\n });\n\n const review = yield* repo.create({\n baseRef,\n id: reviewId,\n repositoryPath: repoPath,\n snapshotData,\n sourceRef: sourceRef ?? null,\n sourceType,\n status: \"in_progress\",\n });\n\n yield* fileRepo.createBulk(fileInputs);\n\n return review;\n });\n\n const list = (opts: {\n page?: number;\n pageSize?: number;\n status?: ReviewStatus;\n repositoryPath?: string;\n sourceType?: string;\n }) =>\n Effect.gen(function* () {\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n\n const result = yield* repo.findAll({\n page,\n pageSize,\n repositoryPath: opts.repositoryPath,\n sourceType: opts.sourceType,\n status: opts.status,\n });\n\n const reviews = [];\n for (const review of result.data) {\n const fileCount = yield* fileRepo.countByReview(review.id);\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n reviews.push({\n ...review,\n fileCount,\n repository: snapshot.repository ?? null,\n });\n }\n\n return {\n hasMore: page * pageSize < result.total,\n page,\n pageSize,\n reviews,\n total: result.total,\n };\n });\n\n const getById = (id: ReviewId) =>\n Effect.gen(function* () {\n const review = yield* repo.findById(id);\n if (!review) {\n return yield* new ReviewNotFound({ id });\n }\n\n const fileRows = yield* fileRepo.findByReview(id);\n const files = fileRows.map((r) => ({\n additions: r.additions,\n deletions: r.deletions,\n filePath: r.file_path,\n id: r.id,\n oldPath: r.old_path,\n status: r.status,\n }));\n\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n const summary = getDiffSummary(\n files.map((f) => ({\n additions: f.additions,\n deletions: f.deletions,\n hunks: [],\n newPath: f.filePath,\n oldPath: f.oldPath ?? f.filePath,\n status: f.status as DiffFile[\"status\"],\n }))\n );\n\n return {\n ...review,\n files,\n repository: snapshot.repository ?? null,\n summary,\n };\n });\n\n const getFileHunks = (reviewId: ReviewId, filePath: string) =>\n Effect.gen(function* () {\n const review = yield* repo.findById(reviewId);\n if (!review) {\n return yield* new ReviewNotFound({ id: reviewId });\n }\n\n const fileRecord = yield* fileRepo.findByReviewAndPath(\n reviewId,\n filePath\n );\n if (fileRecord?.hunks_data) {\n return yield* parseHunks(fileRecord.hunks_data);\n }\n\n if (review.sourceType === \"branch\" && review.sourceRef) {\n const diff = yield* git.getBranchDiff(review.sourceRef);\n const diffFiles = parseDiff(diff);\n const file = diffFiles.find((f) => f.newPath === filePath);\n return (file?.hunks ?? []) as DiffHunk[];\n }\n\n if (review.sourceType === \"commits\" && review.sourceRef) {\n const shas = review.sourceRef.split(\",\").map((s) => s.trim());\n const diff = yield* git.getCommitDiff(shas);\n const diffFiles = parseDiff(diff);\n const file = diffFiles.find((f) => f.newPath === filePath);\n return (file?.hunks ?? []) as DiffHunk[];\n }\n\n const snapshot = yield* parseSnapshotData(review.snapshotData);\n if (snapshot.files) {\n const legacyFile = snapshot.files.find(\n (f) => f.newPath === filePath\n );\n return (legacyFile?.hunks ?? []) as DiffHunk[];\n }\n\n return [] as DiffHunk[];\n });\n\n const update = (id: ReviewId, input: UpdateReviewInput) =>\n Effect.gen(function* () {\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new ReviewNotFound({ id });\n }\n\n const status = input.status ? Option.getOrNull(input.status) : null;\n const review = yield* repo.update(id, status);\n if (!review) {\n return yield* new ReviewNotFound({ id });\n }\n\n return review;\n });\n\n const remove = (id: ReviewId) =>\n Effect.gen(function* () {\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new ReviewNotFound({ id });\n }\n\n yield* fileRepo.deleteByReview(id);\n yield* repo.remove(id);\n\n return { success: true as const };\n });\n\n const getStats = () =>\n Effect.gen(function* () {\n const total = yield* repo.countAll();\n const inProgress = yield* repo.countByStatus(\"in_progress\");\n const approved = yield* repo.countByStatus(\"approved\");\n const changesRequested =\n yield* repo.countByStatus(\"changes_requested\");\n\n return { approved, changesRequested, inProgress, total };\n });\n\n return ReviewService.of({\n create,\n getById,\n getFileHunks,\n getStats,\n list,\n remove,\n update,\n });\n })\n );\n}\n","import { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport { SqliteService, withTransaction } from \"../db/database\";\nimport type { Todo, TodoId } from \"../schemas/todo\";\n\n// ---------------------------------------------------------------------------\n// Internal row shape (snake_case from SQLite)\n// ---------------------------------------------------------------------------\n\ninterface TodoRow {\n id: string;\n content: string;\n completed: number;\n review_id: string | null;\n position: number;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row → Domain\n// ---------------------------------------------------------------------------\n\nconst rowToTodo = (row: TodoRow): Todo => ({\n completed: row.completed === 1,\n content: row.content,\n createdAt: row.created_at,\n id: row.id as TodoId,\n position: row.position,\n reviewId: row.review_id as Todo[\"reviewId\"],\n updatedAt: row.updated_at,\n});\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\ninterface FindAllOpts {\n readonly reviewId?: string;\n readonly completed?: boolean;\n readonly limit?: number;\n readonly offset?: number;\n}\n\nexport class TodoRepo extends ServiceMap.Service<\n TodoRepo,\n {\n findById(id: TodoId): Effect.Effect<Todo | null>;\n findAll(\n opts?: FindAllOpts\n ): Effect.Effect<{ data: readonly Todo[]; total: number }>;\n create(input: {\n id: TodoId;\n content: string;\n reviewId: string | null;\n }): Effect.Effect<Todo>;\n update(\n id: TodoId,\n updates: { content?: string; completed?: boolean }\n ): Effect.Effect<Todo | null>;\n toggle(id: TodoId): Effect.Effect<Todo | null>;\n remove(id: TodoId): Effect.Effect<boolean>;\n removeCompleted(): Effect.Effect<number>;\n reorder(orderedIds: readonly string[]): Effect.Effect<number>;\n move(id: TodoId, newPosition: number): Effect.Effect<Todo | null>;\n countAll(): Effect.Effect<number>;\n countCompleted(): Effect.Effect<number>;\n countPending(): Effect.Effect<number>;\n }\n>()(\"@ringi/TodoRepo\") {\n static readonly Default: Layer.Layer<TodoRepo, never, SqliteService> =\n Layer.effect(\n TodoRepo,\n Effect.gen(function* () {\n const { db } = yield* SqliteService;\n\n // Cached prepared statements for static queries\n const stmtFindById = db.prepare(\"SELECT * FROM todos WHERE id = ?\");\n const stmtInsert = db.prepare(\n `INSERT INTO todos (id, content, completed, review_id, position, created_at, updated_at)\n VALUES (?, ?, 0, ?, ?, datetime('now'), datetime('now'))`\n );\n const stmtDelete = db.prepare(\"DELETE FROM todos WHERE id = ?\");\n const stmtDeleteCompleted = db.prepare(\n \"DELETE FROM todos WHERE completed = 1\"\n );\n const stmtNextPosition = db.prepare(\n \"SELECT COALESCE(MAX(position), -1) + 1 AS next_pos FROM todos\"\n );\n const stmtCountAll = db.prepare(\"SELECT COUNT(*) as count FROM todos\");\n const stmtCountCompleted = db.prepare(\n \"SELECT COUNT(*) as count FROM todos WHERE completed = 1\"\n );\n const stmtCountPending = db.prepare(\n \"SELECT COUNT(*) as count FROM todos WHERE completed = 0\"\n );\n\n const findById = (id: TodoId): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n });\n\n const findAll = (\n opts: FindAllOpts = {}\n ): Effect.Effect<{ data: readonly Todo[]; total: number }> =>\n Effect.sync(() => {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.reviewId != null) {\n conditions.push(\"review_id = ?\");\n params.push(opts.reviewId);\n }\n if (opts.completed != null) {\n conditions.push(\"completed = ?\");\n params.push(opts.completed ? 1 : 0);\n }\n\n const where =\n conditions.length > 0 ? ` WHERE ${conditions.join(\" AND \")}` : \"\";\n\n const totalRow = db\n .prepare(`SELECT COUNT(*) as count FROM todos${where}`)\n .get(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as { count: number };\n\n const limitClause = opts.limit != null ? ` LIMIT ? OFFSET ?` : \"\";\n const queryParams =\n opts.limit != null\n ? [...params, opts.limit, opts.offset ?? 0]\n : params;\n\n const rows = db\n .prepare(\n `SELECT * FROM todos${where} ORDER BY position ASC${limitClause}`\n )\n .all(\n ...(queryParams as import(\"node:sqlite\").SQLInputValue[])\n ) as unknown as TodoRow[];\n\n return { data: rows.map(rowToTodo), total: totalRow.count };\n });\n\n const create = (input: {\n id: TodoId;\n content: string;\n reviewId: string | null;\n }): Effect.Effect<Todo> =>\n Effect.sync(() => {\n const { next_pos } = stmtNextPosition.get() as unknown as {\n next_pos: number;\n };\n stmtInsert.run(input.id, input.content, input.reviewId, next_pos);\n return rowToTodo(stmtFindById.get(input.id) as unknown as TodoRow);\n });\n\n const update = (\n id: TodoId,\n updates: { content?: string; completed?: boolean }\n ): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const sets: string[] = [];\n const params: unknown[] = [];\n\n if (updates.content != null) {\n sets.push(\"content = ?\");\n params.push(updates.content);\n }\n if (updates.completed != null) {\n sets.push(\"completed = ?\");\n params.push(updates.completed ? 1 : 0);\n }\n\n if (sets.length === 0) {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n }\n\n sets.push(\"updated_at = datetime('now')\");\n params.push(id);\n\n db.prepare(`UPDATE todos SET ${sets.join(\", \")} WHERE id = ?`).run(\n ...(params as import(\"node:sqlite\").SQLInputValue[])\n );\n\n const row = stmtFindById.get(id) as TodoRow | undefined;\n return row ? rowToTodo(row) : null;\n });\n\n const toggle = (id: TodoId): Effect.Effect<Todo | null> =>\n Effect.sync(() => {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n if (!row) {\n return null;\n }\n\n const newCompleted = row.completed === 1 ? 0 : 1;\n db.prepare(\n \"UPDATE todos SET completed = ?, updated_at = datetime('now') WHERE id = ?\"\n ).run(newCompleted, id);\n\n return rowToTodo(stmtFindById.get(id) as unknown as TodoRow);\n });\n\n const remove = (id: TodoId): Effect.Effect<boolean> =>\n Effect.sync(() => {\n const result = stmtDelete.run(id);\n return Number(result.changes) > 0;\n });\n\n const removeCompleted = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const result = stmtDeleteCompleted.run();\n return Number(result.changes);\n });\n\n const reorder = (\n orderedIds: readonly string[]\n ): Effect.Effect<number> =>\n withTransaction(\n db,\n Effect.sync(() => {\n const stmt = db.prepare(\n \"UPDATE todos SET position = ?, updated_at = datetime('now') WHERE id = ?\"\n );\n let updated = 0;\n for (let i = 0; i < orderedIds.length; i++) {\n const result = stmt.run(i, orderedIds[i]!);\n updated += Number(result.changes);\n }\n return updated;\n })\n );\n\n const move = (\n id: TodoId,\n newPosition: number\n ): Effect.Effect<Todo | null> =>\n Effect.gen(function* () {\n const row = stmtFindById.get(id) as TodoRow | undefined;\n if (!row) {\n return null;\n }\n\n const oldPosition = row.position;\n\n yield* withTransaction(\n db,\n Effect.sync(() => {\n if (newPosition < oldPosition) {\n db.prepare(\n \"UPDATE todos SET position = position + 1, updated_at = datetime('now') WHERE position >= ? AND position < ? AND id != ?\"\n ).run(newPosition, oldPosition, id);\n } else if (newPosition > oldPosition) {\n db.prepare(\n \"UPDATE todos SET position = position - 1, updated_at = datetime('now') WHERE position > ? AND position <= ? AND id != ?\"\n ).run(oldPosition, newPosition, id);\n }\n\n db.prepare(\n \"UPDATE todos SET position = ?, updated_at = datetime('now') WHERE id = ?\"\n ).run(newPosition, id);\n })\n );\n\n return rowToTodo(stmtFindById.get(id) as unknown as TodoRow);\n });\n\n const countAll = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountAll.get() as { count: number };\n return row.count;\n });\n\n const countCompleted = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountCompleted.get() as { count: number };\n return row.count;\n });\n\n const countPending = (): Effect.Effect<number> =>\n Effect.sync(() => {\n const row = stmtCountPending.get() as { count: number };\n return row.count;\n });\n\n return TodoRepo.of({\n countAll,\n countCompleted,\n countPending,\n create,\n findAll,\n findById,\n move,\n remove,\n removeCompleted,\n reorder,\n toggle,\n update,\n });\n })\n );\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\n\nimport { TodoRepo } from \"../repos/todo.repo\";\nimport type { CreateTodoInput, TodoId, UpdateTodoInput } from \"../schemas/todo\";\nimport { TodoNotFound } from \"../schemas/todo\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class TodoService extends ServiceMap.Service<\n TodoService,\n {\n create(input: CreateTodoInput): Effect.Effect<any>;\n getById(id: TodoId): Effect.Effect<any, TodoNotFound>;\n list(opts?: {\n reviewId?: string;\n completed?: boolean;\n limit?: number;\n offset?: number;\n }): Effect.Effect<any>;\n update(\n id: TodoId,\n input: UpdateTodoInput\n ): Effect.Effect<any, TodoNotFound>;\n toggle(id: TodoId): Effect.Effect<any, TodoNotFound>;\n remove(id: TodoId): Effect.Effect<{ success: true }, TodoNotFound>;\n removeCompleted(): Effect.Effect<{ deleted: number }>;\n reorder(orderedIds: readonly string[]): Effect.Effect<{ updated: number }>;\n move(id: TodoId, position: number): Effect.Effect<any, TodoNotFound>;\n getStats(): Effect.Effect<{\n completed: number;\n pending: number;\n total: number;\n }>;\n }\n>()(\"@ringi/TodoService\") {\n static readonly Default: Layer.Layer<TodoService, never, TodoRepo> =\n Layer.effect(\n TodoService,\n Effect.gen(function* () {\n const repo = yield* TodoRepo;\n\n const create = (input: CreateTodoInput) => {\n const id = randomUUID() as TodoId;\n return repo.create({\n content: input.content,\n id,\n reviewId: input.reviewId ?? null,\n });\n };\n\n const getById = (id: TodoId) =>\n Effect.gen(function* () {\n const todo = yield* repo.findById(id);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n const list = (\n opts: {\n reviewId?: string;\n completed?: boolean;\n limit?: number;\n offset?: number;\n } = {}\n ) =>\n Effect.gen(function* () {\n const result = yield* repo.findAll(opts);\n return {\n data: result.data,\n limit: opts.limit ?? null,\n offset: opts.offset ?? 0,\n total: result.total,\n };\n });\n\n const update = (id: TodoId, input: UpdateTodoInput) =>\n Effect.gen(function* () {\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new TodoNotFound({ id });\n }\n\n const updates: { content?: string; completed?: boolean } = {};\n if (input.content && Option.isSome(input.content)) {\n updates.content = input.content.value;\n }\n if (input.completed && Option.isSome(input.completed)) {\n updates.completed = input.completed.value;\n }\n\n const todo = yield* repo.update(id, updates);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n\n return todo;\n });\n\n const toggle = (id: TodoId) =>\n Effect.gen(function* () {\n const todo = yield* repo.toggle(id);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n const remove = (id: TodoId) =>\n Effect.gen(function* () {\n const existing = yield* repo.findById(id);\n if (!existing) {\n return yield* new TodoNotFound({ id });\n }\n\n yield* repo.remove(id);\n return { success: true as const };\n });\n\n const removeCompleted = () =>\n Effect.gen(function* () {\n const deleted = yield* repo.removeCompleted();\n return { deleted };\n });\n\n const reorder = (orderedIds: readonly string[]) =>\n Effect.gen(function* () {\n const updated = yield* repo.reorder(orderedIds);\n return { updated };\n });\n\n const move = (id: TodoId, position: number) =>\n Effect.gen(function* () {\n const todo = yield* repo.move(id, position);\n if (!todo) {\n return yield* new TodoNotFound({ id });\n }\n return todo;\n });\n\n const getStats = () =>\n Effect.gen(function* () {\n const total = yield* repo.countAll();\n const completed = yield* repo.countCompleted();\n const pending = yield* repo.countPending();\n return { completed, pending, total };\n });\n\n return TodoService.of({\n create,\n getById,\n getStats,\n list,\n move,\n remove,\n removeCompleted,\n reorder,\n toggle,\n update,\n });\n })\n );\n}\n","import { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport type { ReviewId } from \"../schemas/review\";\nimport { CommentService } from \"../services/comment.service\";\nimport { ReviewService } from \"../services/review.service\";\nimport { TodoService } from \"../services/todo.service\";\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class ExportService extends ServiceMap.Service<\n ExportService,\n {\n exportReview(\n reviewId: ReviewId\n ): Effect.Effect<string, import(\"../schemas/review\").ReviewNotFound>;\n }\n>()(\"@ringi/ExportService\") {\n static readonly Default: Layer.Layer<\n ExportService,\n never,\n ReviewService | CommentService | TodoService\n > = Layer.effect(\n ExportService,\n Effect.gen(function* () {\n const reviewSvc = yield* ReviewService;\n const commentSvc = yield* CommentService;\n const todoSvc = yield* TodoService;\n\n const exportReview = (reviewId: ReviewId) =>\n Effect.gen(function* () {\n const review = yield* reviewSvc.getById(reviewId);\n\n const repo = review.repository as {\n name?: string;\n branch?: string;\n } | null;\n const repoName = repo?.name ?? \"Unknown\";\n const branch = repo?.branch ?? \"unknown\";\n\n const comments = yield* commentSvc.getByReview(reviewId);\n const commentStats = yield* commentSvc.getStats(reviewId);\n const todos = yield* todoSvc.list({ reviewId });\n\n const lines: string[] = [];\n\n lines.push(`# Code Review: ${repoName}`);\n lines.push(\"\");\n lines.push(`**Status:** ${review.status}`);\n lines.push(`**Branch:** ${branch}`);\n lines.push(`**Created:** ${review.createdAt}`);\n\n if (review.files && review.files.length > 0) {\n lines.push(\"\");\n lines.push(\"## Files Changed\");\n lines.push(\"\");\n lines.push(\"| File | Status | Additions | Deletions |\");\n lines.push(\"|------|--------|-----------|-----------|\");\n for (const f of review.files) {\n const statusLabel =\n f.status === \"modified\"\n ? \"M\"\n : f.status === \"added\"\n ? \"A\"\n : f.status === \"deleted\"\n ? \"D\"\n : f.status;\n lines.push(\n `| ${f.filePath} | ${statusLabel} | +${f.additions} | -${f.deletions} |`\n );\n }\n }\n\n if (comments.length > 0) {\n lines.push(\"\");\n lines.push(\n `## Comments (${commentStats.total} total, ${commentStats.resolved} resolved)`\n );\n\n const byFile = new Map<string, (typeof comments)[number][]>();\n for (const c of comments) {\n const key = c.filePath ?? \"(general)\";\n const arr = byFile.get(key) ?? [];\n arr.push(c);\n byFile.set(key, arr);\n }\n\n for (const [filePath, fileComments] of byFile) {\n lines.push(\"\");\n lines.push(`### ${filePath}`);\n for (const c of fileComments) {\n lines.push(\"\");\n lines.push(\n `**Line ${c.lineNumber ?? \"–\"}** (${c.lineType ?? \"context\"})`\n );\n lines.push(`> ${c.content}`);\n if (c.suggestion) {\n lines.push(\"\");\n lines.push(\"```suggestion\");\n lines.push(c.suggestion);\n lines.push(\"```\");\n }\n }\n }\n }\n\n if (todos.data.length > 0) {\n const completed = todos.data.filter((t: any) => t.completed).length;\n lines.push(\"\");\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(\n `## Todos (${todos.total} total, ${completed} completed)`\n );\n lines.push(\"\");\n for (const t of todos.data) {\n const check = (t as any).completed ? \"x\" : \" \";\n lines.push(`- [${check}] ${(t as any).content}`);\n }\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n });\n\n return ExportService.of({ exportReview });\n })\n );\n}\n","import { spawn } from \"node:child_process\";\n\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schema from \"effect/Schema\";\n\nimport type { PrMetadata, PrTarget } from \"../schemas/pr\";\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class GhNotInstalled extends Schema.TaggedErrorClass<GhNotInstalled>()(\n \"GhNotInstalled\",\n { message: Schema.String }\n) {}\n\nexport class GhAuthError extends Schema.TaggedErrorClass<GhAuthError>()(\n \"GhAuthError\",\n {\n host: Schema.String,\n message: Schema.String,\n }\n) {}\n\nexport class GhApiError extends Schema.TaggedErrorClass<GhApiError>()(\n \"GhApiError\",\n {\n message: Schema.String,\n statusCode: Schema.NullOr(Schema.Number),\n }\n) {}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Max bytes to collect from gh output (50 MB — PR diffs can be large). */\nconst MAX_STDOUT_BYTES = 50 * 1024 * 1024;\n\nconst execGh = (args: readonly string[]) =>\n Effect.tryPromise({\n catch: (error) =>\n new GhApiError({ message: String(error), statusCode: null }),\n try: () =>\n new Promise<string>((resolve, reject) => {\n const child = spawn(\"gh\", [...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const chunks: Buffer[] = [];\n let bytes = 0;\n let truncated = false;\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n if (truncated) return;\n bytes += chunk.length;\n if (bytes > MAX_STDOUT_BYTES) {\n truncated = true;\n child.kill();\n return;\n }\n chunks.push(chunk);\n });\n\n let stderr = \"\";\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n child.on(\"error\", (err) => {\n reject(new Error(`Failed to spawn gh: ${err.message}`));\n });\n\n child.on(\"close\", (code) => {\n if (truncated) {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n return;\n }\n if (code !== 0) {\n reject(\n new Error(`gh ${args[0]} exited with code ${code}: ${stderr}`)\n );\n } else {\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n }\n });\n }),\n });\n\n/** PR metadata fields requested from gh in a single JSON call. */\nconst PR_JSON_FIELDS = [\n \"additions\",\n \"author\",\n \"baseRefName\",\n \"baseRefOid\",\n \"body\",\n \"changedFiles\",\n \"createdAt\",\n \"deletions\",\n \"headRefName\",\n \"headRefOid\",\n \"headRepository\",\n \"isDraft\",\n \"mergeable\",\n \"number\",\n \"reviewDecision\",\n \"state\",\n \"title\",\n \"updatedAt\",\n \"url\",\n].join(\",\");\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\ninterface GhServiceShape {\n /** Verify `gh` CLI is installed and reachable. */\n readonly ensureInstalled: Effect.Effect<void, GhNotInstalled>;\n\n /** Verify authentication for a specific host. */\n ensureAuthenticated(host: string): Effect.Effect<void, GhAuthError>;\n\n /** Fetch full PR metadata as typed JSON. */\n fetchPrMetadata(target: PrTarget): Effect.Effect<PrMetadata, GhApiError>;\n\n /** Fetch PR diff as unified diff text. */\n fetchPrDiff(target: PrTarget): Effect.Effect<string, GhApiError>;\n\n /** Quick-check current head SHA without full metadata fetch. */\n fetchPrHeadOid(target: PrTarget): Effect.Effect<string, GhApiError>;\n}\n\nexport class GhService extends ServiceMap.Service<GhService, GhServiceShape>()(\n \"@ringi/GhService\"\n) {\n static readonly Default: Layer.Layer<GhService> = Layer.effect(\n GhService,\n Effect.gen(function* () {\n const ensureInstalled = execGh([\"version\"]).pipe(\n Effect.asVoid,\n Effect.mapError(\n () =>\n new GhNotInstalled({\n message:\n \"GitHub CLI (gh) not found. Install: https://cli.github.com\",\n })\n ),\n Effect.withSpan(\"GhService.ensureInstalled\")\n );\n\n const ensureAuthenticated = Effect.fn(\"GhService.ensureAuthenticated\")(\n function* (host: string) {\n yield* execGh([\"auth\", \"status\", \"--hostname\", host]).pipe(\n Effect.asVoid,\n Effect.mapError(\n () =>\n new GhAuthError({\n host,\n message: `Not authenticated to ${host}. Run: gh auth login --hostname ${host}`,\n })\n )\n );\n }\n );\n\n const fetchPrMetadata = Effect.fn(\"GhService.fetchPrMetadata\")(function* (\n target: PrTarget\n ) {\n const json = yield* execGh([\n \"pr\",\n \"view\",\n String(target.prNumber),\n \"--repo\",\n target.nwoRef,\n \"--json\",\n PR_JSON_FIELDS,\n ]);\n\n return yield* Effect.try({\n catch: () =>\n new GhApiError({\n message: \"Failed to parse PR metadata JSON from gh output\",\n statusCode: null,\n }),\n try: () => JSON.parse(json) as PrMetadata,\n });\n });\n\n const fetchPrDiff = Effect.fn(\"GhService.fetchPrDiff\")(function* (\n target: PrTarget\n ) {\n return yield* execGh([\n \"pr\",\n \"diff\",\n String(target.prNumber),\n \"--repo\",\n target.nwoRef,\n ]);\n });\n\n const fetchPrHeadOid = Effect.fn(\"GhService.fetchPrHeadOid\")(function* (\n target: PrTarget\n ) {\n const json = yield* execGh([\n \"pr\",\n \"view\",\n String(target.prNumber),\n \"--repo\",\n target.nwoRef,\n \"--json\",\n \"headRefOid\",\n ]);\n\n return yield* Effect.try({\n catch: () =>\n new GhApiError({\n message: \"Failed to parse head OID from gh output\",\n statusCode: null,\n }),\n try: () => (JSON.parse(json) as { headRefOid: string }).headRefOid,\n });\n });\n\n return GhService.of({\n ensureAuthenticated,\n ensureInstalled,\n fetchPrDiff,\n fetchPrHeadOid,\n fetchPrMetadata,\n });\n })\n );\n}\n","import { lstat, readdir, realpath, stat } from 'node:fs/promises';\nimport { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from 'node:path';\nimport { Readable } from 'node:stream';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n highWaterMark: 4096,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\n/** Readable readdir stream, emitting new files as they're being listed. */\nexport class ReaddirpStream extends Readable {\n parents;\n reading;\n parent;\n _stat;\n _maxDepth;\n _wantsDir;\n _wantsFile;\n _wantsEverything;\n _root;\n _isDirent;\n _statsProp;\n _rdOptions;\n _fileFilter;\n _directoryFilter;\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n const { root, type } = opts;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth =\n opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;\n this._wantsDir = type ? DIR_TYPES.has(type) : false;\n this._wantsFile = type ? FILE_TYPES.has(type) : false;\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir.\n this.parents = [this._exploreDir(root, 1)];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n const awaited = await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n const entryType = await this._getEntryType(entry);\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n this.parents.push(this._exploreDir(entry.fullPath, depth + 1));\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n this.parent = await parent;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n async _formatEntry(dirent, path) {\n let entry;\n const basename = this._isDirent ? dirent.name : dirent;\n try {\n const fullPath = presolve(pjoin(path, basename));\n entry = { path: prelative(this._root, fullPath), fullPath, basename };\n entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);\n }\n catch (err) {\n this._onError(err);\n return;\n }\n return entry;\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n async _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry && this._statsProp in entry) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats && stats.isSymbolicLink()) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n return this._onError(recursiveError);\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n return '';\n }\n }\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (type)\n options.type = type;\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n options.root = root;\n return new ReaddirpStream(options);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watch as fs_watch, unwatchFile, watchFile } from 'node:fs';\nimport { realpath as fsrealpath, lstat, open, stat } from 'node:fs/promises';\nimport { type as osType } from 'node:os';\nimport * as sp from 'node:path';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n fsw;\n _boundHandleError;\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sp.dirname(path);\n const basename = sp.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sp.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sp.dirname(file);\n const basename = sp.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sp.join(directory, '');\n const throttleKey = target ? `${directory}:${target}` : directory;\n throttler = this.fsw._throttle('readdir', throttleKey, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sp.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sp.join(dir, sp.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));\n const tracked = parentDir.has(sp.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sp.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sp.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sp.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { EventEmitter } from 'node:events';\nimport { stat as statcb, Stats } from 'node:fs';\nimport { readdir, stat } from 'node:fs/promises';\nimport * as sp from 'node:path';\nimport { readdirp, ReaddirpStream } from 'readdirp';\nimport { EMPTY_FN, EVENTS as EV, isIBMi, isWindows, NodeFsHandler, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//g;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sp.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sp.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sp.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sp.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sp.isAbsolute(path) ? path : sp.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sp.isAbsolute(path)) {\n return path;\n }\n return sp.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n path;\n _removeWatcher;\n items;\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sp.dirname(dir), sp.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n fsw;\n path;\n watchPath;\n fullWatchPath;\n dirParts;\n followSymlinks;\n statMethod;\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sp.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sp.join(this.watchPath, sp.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n closed;\n options;\n _closers;\n _ignoredPaths;\n _throttled;\n _streams;\n _symlinkPaths;\n _watched;\n _pendingWrites;\n _pendingUnlinks;\n _readyCount;\n _emitReady;\n _closePromise;\n _userIgnored;\n _readyEmitted;\n _emitRaw;\n _boundRemove;\n _nodeFsHandler;\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sp.dirname(item), sp.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sp.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sp.join(cwd, path);\n path = sp.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sp.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sp.normalize(path);\n if (opts.cwd)\n path = sp.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sp.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sp.isAbsolute(path)) {\n fullPath = sp.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sp.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sp.join(directory, item);\n const fullPath = sp.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sp.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sp.dirname(path);\n this._getWatchedDir(dir).remove(sp.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch: watch, FSWatcher: FSWatcher };\n","import { platform } from \"node:os\";\nimport { relative } from \"node:path\";\n\nimport chokidar from \"chokidar\";\nimport { ServiceMap } from \"effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Queue from \"effect/Queue\";\nimport type * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type EventType = \"todos\" | \"reviews\" | \"comments\" | \"files\";\n\nexport interface SSEEvent {\n readonly type: EventType;\n readonly data?: unknown;\n readonly timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class EventService extends ServiceMap.Service<\n EventService,\n {\n broadcast(type: EventType, data?: unknown): Effect.Effect<void>;\n subscribe(): Effect.Effect<{\n readonly stream: Stream.Stream<SSEEvent>;\n readonly unsubscribe: Effect.Effect<void>;\n }>;\n startFileWatcher(\n repoPath: string\n ): Effect.Effect<ReturnType<typeof chokidar.watch>, never, Scope.Scope>;\n getClientCount(): Effect.Effect<number>;\n }\n>()(\"@ringi/EventService\") {\n static readonly Default: Layer.Layer<EventService> = Layer.effect(\n EventService,\n Effect.sync(() => {\n const subscribers = new Set<Queue.Queue<SSEEvent>>();\n\n const broadcast = (type: EventType, data?: unknown) =>\n Effect.gen(function* () {\n const event: SSEEvent = { data, timestamp: Date.now(), type };\n for (const queue of subscribers) {\n yield* Queue.offer(queue, event);\n }\n });\n\n const subscribe = () =>\n Effect.gen(function* () {\n const queue = yield* Queue.sliding<SSEEvent>(100);\n subscribers.add(queue);\n\n const stream = Stream.fromQueue(queue);\n\n const unsubscribe = Effect.sync(() => {\n subscribers.delete(queue);\n }).pipe(Effect.andThen(Queue.shutdown(queue)));\n\n return { stream, unsubscribe } as const;\n });\n\n const startFileWatcher = (repoPath: string) =>\n Effect.acquireRelease(\n Effect.sync(() => {\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const watcher = chokidar.watch(repoPath, {\n ignoreInitial: true,\n ignored: [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/.ringi/**\",\n \"**/dist/**\",\n ],\n persistent: true,\n ...(platform() === \"darwin\"\n ? { interval: 1000, usePolling: true }\n : {}),\n });\n\n const debouncedBroadcast = (filePath: string) => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n const rel = relative(repoPath, filePath);\n Effect.runFork(broadcast(\"files\", { path: rel }));\n }, 300);\n };\n\n watcher.on(\"add\", debouncedBroadcast);\n watcher.on(\"change\", debouncedBroadcast);\n watcher.on(\"unlink\", debouncedBroadcast);\n\n return watcher;\n }),\n (watcher) => Effect.promise(() => watcher.close())\n );\n\n const getClientCount = () => Effect.sync(() => subscribers.size);\n\n return EventService.of({\n broadcast,\n getClientCount,\n startFileWatcher,\n subscribe,\n });\n })\n );\n}\n","import * as Layer from \"effect/Layer\";\nimport * as ManagedRuntime from \"effect/ManagedRuntime\";\n\nimport { SqliteService } from \"./db/database\";\nimport { CommentRepo } from \"./repos/comment.repo\";\nimport { ReviewFileRepo } from \"./repos/review-file.repo\";\nimport { ReviewRepo } from \"./repos/review.repo\";\nimport { TodoRepo } from \"./repos/todo.repo\";\nimport { CommentService } from \"./services/comment.service\";\nimport { EventService } from \"./services/event.service\";\nimport { ExportService } from \"./services/export.service\";\nimport { GhService } from \"./services/gh.service\";\nimport { GitService } from \"./services/git.service\";\nimport { ReviewService } from \"./services/review.service\";\nimport { TodoService } from \"./services/todo.service\";\n\n// Repos depend on SqliteService\nconst RepoLive = Layer.mergeAll(\n ReviewRepo.Default,\n ReviewFileRepo.Default,\n CommentRepo.Default,\n TodoRepo.Default\n).pipe(Layer.provide(SqliteService.Default));\n\n// Services depend on repos and other services\nconst CommentServiceLive = CommentService.Default.pipe(\n Layer.provide(CommentRepo.Default),\n Layer.provide(SqliteService.Default)\n);\n\nconst TodoServiceLive = TodoService.Default.pipe(\n Layer.provide(TodoRepo.Default),\n Layer.provide(SqliteService.Default)\n);\n\nconst ReviewServiceLive = ReviewService.Default.pipe(\n Layer.provide(ReviewRepo.Default),\n Layer.provide(ReviewFileRepo.Default),\n Layer.provide(GitService.Default),\n Layer.provide(SqliteService.Default)\n);\n\nconst ExportServiceLive = ExportService.Default.pipe(\n Layer.provide(ReviewServiceLive),\n Layer.provide(CommentServiceLive),\n Layer.provide(TodoServiceLive)\n);\n\nexport const CoreLive = Layer.mergeAll(\n ReviewServiceLive,\n CommentServiceLive,\n TodoServiceLive,\n GitService.Default,\n GhService.Default,\n EventService.Default,\n ExportServiceLive,\n RepoLive,\n SqliteService.Default\n);\n\nexport const createCoreRuntime = () => ManagedRuntime.make(CoreLive);\n"],"x_google_ignoreList":[16,17,18],"mappings":"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"}
|