grepmind-app 0.1.0-alpha
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 +190 -0
- package/dist/context.d.ts +43 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +230 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/secrets.d.ts +21 -0
- package/dist/middleware/secrets.d.ts.map +1 -0
- package/dist/middleware/secrets.js +38 -0
- package/dist/middleware/secrets.js.map +1 -0
- package/dist/routes/code.d.ts +61 -0
- package/dist/routes/code.d.ts.map +1 -0
- package/dist/routes/code.js +974 -0
- package/dist/routes/code.js.map +1 -0
- package/dist/routes/code.test.d.ts +7 -0
- package/dist/routes/code.test.d.ts.map +1 -0
- package/dist/routes/code.test.js +418 -0
- package/dist/routes/code.test.js.map +1 -0
- package/dist/routes/events.d.ts +30 -0
- package/dist/routes/events.d.ts.map +1 -0
- package/dist/routes/events.js +152 -0
- package/dist/routes/events.js.map +1 -0
- package/dist/routes/git.d.ts +47 -0
- package/dist/routes/git.d.ts.map +1 -0
- package/dist/routes/git.js +246 -0
- package/dist/routes/git.js.map +1 -0
- package/dist/routes/index.d.ts +6 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +6 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/notes.d.ts +38 -0
- package/dist/routes/notes.d.ts.map +1 -0
- package/dist/routes/notes.js +829 -0
- package/dist/routes/notes.js.map +1 -0
- package/dist/routes/project.d.ts +35 -0
- package/dist/routes/project.d.ts.map +1 -0
- package/dist/routes/project.js +675 -0
- package/dist/routes/project.js.map +1 -0
- package/dist/routes/sync-handler.d.ts +46 -0
- package/dist/routes/sync-handler.d.ts.map +1 -0
- package/dist/routes/sync-handler.js +178 -0
- package/dist/routes/sync-handler.js.map +1 -0
- package/dist/routes/sync.d.ts +31 -0
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +329 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +93 -0
- package/dist/server.js.map +1 -0
- package/dist/tesst.d.ts +2 -0
- package/dist/tesst.d.ts.map +1 -0
- package/dist/tesst.js +2 -0
- package/dist/tesst.js.map +1 -0
- package/dist/web/assets/apl-B4CMkyY2.js +2 -0
- package/dist/web/assets/apl-B4CMkyY2.js.map +1 -0
- package/dist/web/assets/asciiarmor-Df11BRmG.js +2 -0
- package/dist/web/assets/asciiarmor-Df11BRmG.js.map +1 -0
- package/dist/web/assets/asn1-EdZsLKOL.js +2 -0
- package/dist/web/assets/asn1-EdZsLKOL.js.map +1 -0
- package/dist/web/assets/asterisk-B-8jnY81.js +2 -0
- package/dist/web/assets/asterisk-B-8jnY81.js.map +1 -0
- package/dist/web/assets/brainfuck-C4LP7Hcl.js +2 -0
- package/dist/web/assets/brainfuck-C4LP7Hcl.js.map +1 -0
- package/dist/web/assets/clike-B9uivgTg.js +2 -0
- package/dist/web/assets/clike-B9uivgTg.js.map +1 -0
- package/dist/web/assets/clojure-BMjYHr_A.js +2 -0
- package/dist/web/assets/clojure-BMjYHr_A.js.map +1 -0
- package/dist/web/assets/cmake-BQqOBYOt.js +2 -0
- package/dist/web/assets/cmake-BQqOBYOt.js.map +1 -0
- package/dist/web/assets/cobol-CWcv1MsR.js +2 -0
- package/dist/web/assets/cobol-CWcv1MsR.js.map +1 -0
- package/dist/web/assets/coffeescript-S37ZYGWr.js +2 -0
- package/dist/web/assets/coffeescript-S37ZYGWr.js.map +1 -0
- package/dist/web/assets/commonlisp-DBKNyK5s.js +2 -0
- package/dist/web/assets/commonlisp-DBKNyK5s.js.map +1 -0
- package/dist/web/assets/crystal-SjHAIU92.js +2 -0
- package/dist/web/assets/crystal-SjHAIU92.js.map +1 -0
- package/dist/web/assets/css-BnMrqG3P.js +2 -0
- package/dist/web/assets/css-BnMrqG3P.js.map +1 -0
- package/dist/web/assets/cypher-C_CwsFkJ.js +2 -0
- package/dist/web/assets/cypher-C_CwsFkJ.js.map +1 -0
- package/dist/web/assets/d-pRatUO7H.js +2 -0
- package/dist/web/assets/d-pRatUO7H.js.map +1 -0
- package/dist/web/assets/diff-DbItnlRl.js +2 -0
- package/dist/web/assets/diff-DbItnlRl.js.map +1 -0
- package/dist/web/assets/dockerfile-BKs6k2Af.js +2 -0
- package/dist/web/assets/dockerfile-BKs6k2Af.js.map +1 -0
- package/dist/web/assets/dtd-DF_7sFjM.js +2 -0
- package/dist/web/assets/dtd-DF_7sFjM.js.map +1 -0
- package/dist/web/assets/dylan-DwRh75JA.js +2 -0
- package/dist/web/assets/dylan-DwRh75JA.js.map +1 -0
- package/dist/web/assets/ebnf-CDyGwa7X.js +2 -0
- package/dist/web/assets/ebnf-CDyGwa7X.js.map +1 -0
- package/dist/web/assets/ecl-Cabwm37j.js +2 -0
- package/dist/web/assets/ecl-Cabwm37j.js.map +1 -0
- package/dist/web/assets/eiffel-CnydiIhH.js +2 -0
- package/dist/web/assets/eiffel-CnydiIhH.js.map +1 -0
- package/dist/web/assets/elm-vLlmbW-K.js +2 -0
- package/dist/web/assets/elm-vLlmbW-K.js.map +1 -0
- package/dist/web/assets/erlang-BNw1qcRV.js +2 -0
- package/dist/web/assets/erlang-BNw1qcRV.js.map +1 -0
- package/dist/web/assets/factor-kuTfRLto.js +2 -0
- package/dist/web/assets/factor-kuTfRLto.js.map +1 -0
- package/dist/web/assets/fcl-Kvtd6kyn.js +2 -0
- package/dist/web/assets/fcl-Kvtd6kyn.js.map +1 -0
- package/dist/web/assets/forth-Ffai-XNe.js +2 -0
- package/dist/web/assets/forth-Ffai-XNe.js.map +1 -0
- package/dist/web/assets/fortran-DYz_wnZ1.js +2 -0
- package/dist/web/assets/fortran-DYz_wnZ1.js.map +1 -0
- package/dist/web/assets/gas-Bneqetm1.js +2 -0
- package/dist/web/assets/gas-Bneqetm1.js.map +1 -0
- package/dist/web/assets/gherkin-heZmZLOM.js +2 -0
- package/dist/web/assets/gherkin-heZmZLOM.js.map +1 -0
- package/dist/web/assets/groovy-D9Dt4D0W.js +2 -0
- package/dist/web/assets/groovy-D9Dt4D0W.js.map +1 -0
- package/dist/web/assets/haskell-BWDZoCOh.js +2 -0
- package/dist/web/assets/haskell-BWDZoCOh.js.map +1 -0
- package/dist/web/assets/haxe-H-WmDvRZ.js +2 -0
- package/dist/web/assets/haxe-H-WmDvRZ.js.map +1 -0
- package/dist/web/assets/http-DBlCnlav.js +2 -0
- package/dist/web/assets/http-DBlCnlav.js.map +1 -0
- package/dist/web/assets/idl-BEugSyMb.js +2 -0
- package/dist/web/assets/idl-BEugSyMb.js.map +1 -0
- package/dist/web/assets/index-6L7rK6RK.js +2 -0
- package/dist/web/assets/index-6L7rK6RK.js.map +1 -0
- package/dist/web/assets/index-B1YTM6Ei.js +2 -0
- package/dist/web/assets/index-B1YTM6Ei.js.map +1 -0
- package/dist/web/assets/index-B7vcMomf.js +509 -0
- package/dist/web/assets/index-B7vcMomf.js.map +1 -0
- package/dist/web/assets/index-BcZ8RTQK.js +2 -0
- package/dist/web/assets/index-BcZ8RTQK.js.map +1 -0
- package/dist/web/assets/index-C7GrfZtu.js +2 -0
- package/dist/web/assets/index-C7GrfZtu.js.map +1 -0
- package/dist/web/assets/index-C7fIfqkz.js +2 -0
- package/dist/web/assets/index-C7fIfqkz.js.map +1 -0
- package/dist/web/assets/index-C9-Eilv-.js +2 -0
- package/dist/web/assets/index-C9-Eilv-.js.map +1 -0
- package/dist/web/assets/index-CC-t7RnM.js +4 -0
- package/dist/web/assets/index-CC-t7RnM.js.map +1 -0
- package/dist/web/assets/index-CLbc4ChH.js +2 -0
- package/dist/web/assets/index-CLbc4ChH.js.map +1 -0
- package/dist/web/assets/index-CMXahjWH.js +2 -0
- package/dist/web/assets/index-CMXahjWH.js.map +1 -0
- package/dist/web/assets/index-CfYzSHJA.css +1 -0
- package/dist/web/assets/index-ClDYe_wE.js +2 -0
- package/dist/web/assets/index-ClDYe_wE.js.map +1 -0
- package/dist/web/assets/index-CxykdbB_.js +2 -0
- package/dist/web/assets/index-CxykdbB_.js.map +1 -0
- package/dist/web/assets/index-D3WXxnT1.js +2 -0
- package/dist/web/assets/index-D3WXxnT1.js.map +1 -0
- package/dist/web/assets/index-D4qNbgAX.js +2 -0
- package/dist/web/assets/index-D4qNbgAX.js.map +1 -0
- package/dist/web/assets/index-DCiUPvZt.js +2 -0
- package/dist/web/assets/index-DCiUPvZt.js.map +1 -0
- package/dist/web/assets/index-DJpCPEwr.js +3 -0
- package/dist/web/assets/index-DJpCPEwr.js.map +1 -0
- package/dist/web/assets/index-EuUS3D16.js +8 -0
- package/dist/web/assets/index-EuUS3D16.js.map +1 -0
- package/dist/web/assets/index-WATjATUO.js +2 -0
- package/dist/web/assets/index-WATjATUO.js.map +1 -0
- package/dist/web/assets/javascript-qCveANmP.js +2 -0
- package/dist/web/assets/javascript-qCveANmP.js.map +1 -0
- package/dist/web/assets/julia-DuME0IfC.js +2 -0
- package/dist/web/assets/julia-DuME0IfC.js.map +1 -0
- package/dist/web/assets/livescript-BwQOo05w.js +2 -0
- package/dist/web/assets/livescript-BwQOo05w.js.map +1 -0
- package/dist/web/assets/lua-BgMRiT3U.js +2 -0
- package/dist/web/assets/lua-BgMRiT3U.js.map +1 -0
- package/dist/web/assets/mathematica-DTrFuWx2.js +2 -0
- package/dist/web/assets/mathematica-DTrFuWx2.js.map +1 -0
- package/dist/web/assets/mbox-CNhZ1qSd.js +2 -0
- package/dist/web/assets/mbox-CNhZ1qSd.js.map +1 -0
- package/dist/web/assets/mirc-CjQqDB4T.js +2 -0
- package/dist/web/assets/mirc-CjQqDB4T.js.map +1 -0
- package/dist/web/assets/mllike-CXdrOF99.js +2 -0
- package/dist/web/assets/mllike-CXdrOF99.js.map +1 -0
- package/dist/web/assets/modelica-Dc1JOy9r.js +2 -0
- package/dist/web/assets/modelica-Dc1JOy9r.js.map +1 -0
- package/dist/web/assets/mscgen-BA5vi2Kp.js +2 -0
- package/dist/web/assets/mscgen-BA5vi2Kp.js.map +1 -0
- package/dist/web/assets/mumps-BT43cFF4.js +2 -0
- package/dist/web/assets/mumps-BT43cFF4.js.map +1 -0
- package/dist/web/assets/nginx-DdIZxoE0.js +2 -0
- package/dist/web/assets/nginx-DdIZxoE0.js.map +1 -0
- package/dist/web/assets/nsis-LdVXkNf5.js +2 -0
- package/dist/web/assets/nsis-LdVXkNf5.js.map +1 -0
- package/dist/web/assets/ntriples-BfvgReVJ.js +2 -0
- package/dist/web/assets/ntriples-BfvgReVJ.js.map +1 -0
- package/dist/web/assets/octave-Ck1zUtKM.js +2 -0
- package/dist/web/assets/octave-Ck1zUtKM.js.map +1 -0
- package/dist/web/assets/oz-BzwKVEFT.js +2 -0
- package/dist/web/assets/oz-BzwKVEFT.js.map +1 -0
- package/dist/web/assets/pascal--L3eBynH.js +2 -0
- package/dist/web/assets/pascal--L3eBynH.js.map +1 -0
- package/dist/web/assets/perl-CdXCOZ3F.js +2 -0
- package/dist/web/assets/perl-CdXCOZ3F.js.map +1 -0
- package/dist/web/assets/pig-CevX1Tat.js +2 -0
- package/dist/web/assets/pig-CevX1Tat.js.map +1 -0
- package/dist/web/assets/powershell-CFHJl5sT.js +2 -0
- package/dist/web/assets/powershell-CFHJl5sT.js.map +1 -0
- package/dist/web/assets/properties-C78fOPTZ.js +2 -0
- package/dist/web/assets/properties-C78fOPTZ.js.map +1 -0
- package/dist/web/assets/protobuf-ChK-085T.js +2 -0
- package/dist/web/assets/protobuf-ChK-085T.js.map +1 -0
- package/dist/web/assets/pug-DukmZTjD.js +2 -0
- package/dist/web/assets/pug-DukmZTjD.js.map +1 -0
- package/dist/web/assets/puppet-DMA9R1ak.js +2 -0
- package/dist/web/assets/puppet-DMA9R1ak.js.map +1 -0
- package/dist/web/assets/python-BuPzkPfP.js +2 -0
- package/dist/web/assets/python-BuPzkPfP.js.map +1 -0
- package/dist/web/assets/q-pXgVlZs6.js +2 -0
- package/dist/web/assets/q-pXgVlZs6.js.map +1 -0
- package/dist/web/assets/r-DUYO_cvP.js +2 -0
- package/dist/web/assets/r-DUYO_cvP.js.map +1 -0
- package/dist/web/assets/rpm-CTu-6PCP.js +2 -0
- package/dist/web/assets/rpm-CTu-6PCP.js.map +1 -0
- package/dist/web/assets/ruby-B2Rjki9n.js +2 -0
- package/dist/web/assets/ruby-B2Rjki9n.js.map +1 -0
- package/dist/web/assets/sas-B4kiWyti.js +2 -0
- package/dist/web/assets/sas-B4kiWyti.js.map +1 -0
- package/dist/web/assets/scheme-C41bIUwD.js +2 -0
- package/dist/web/assets/scheme-C41bIUwD.js.map +1 -0
- package/dist/web/assets/shell-CjFT_Tl9.js +2 -0
- package/dist/web/assets/shell-CjFT_Tl9.js.map +1 -0
- package/dist/web/assets/sieve-C3Gn_uJK.js +2 -0
- package/dist/web/assets/sieve-C3Gn_uJK.js.map +1 -0
- package/dist/web/assets/simple-mode-GW_nhZxv.js +2 -0
- package/dist/web/assets/simple-mode-GW_nhZxv.js.map +1 -0
- package/dist/web/assets/smalltalk-CnHTOXQT.js +2 -0
- package/dist/web/assets/smalltalk-CnHTOXQT.js.map +1 -0
- package/dist/web/assets/solr-DehyRSwq.js +2 -0
- package/dist/web/assets/solr-DehyRSwq.js.map +1 -0
- package/dist/web/assets/sparql-DkYu6x3z.js +2 -0
- package/dist/web/assets/sparql-DkYu6x3z.js.map +1 -0
- package/dist/web/assets/spreadsheet-BCZA_wO0.js +2 -0
- package/dist/web/assets/spreadsheet-BCZA_wO0.js.map +1 -0
- package/dist/web/assets/sql-D0XecflT.js +2 -0
- package/dist/web/assets/sql-D0XecflT.js.map +1 -0
- package/dist/web/assets/stex-C3f8Ysf7.js +2 -0
- package/dist/web/assets/stex-C3f8Ysf7.js.map +1 -0
- package/dist/web/assets/stylus-B533Al4x.js +2 -0
- package/dist/web/assets/stylus-B533Al4x.js.map +1 -0
- package/dist/web/assets/swift-BzpIVaGY.js +2 -0
- package/dist/web/assets/swift-BzpIVaGY.js.map +1 -0
- package/dist/web/assets/tcl-DVfN8rqt.js +2 -0
- package/dist/web/assets/tcl-DVfN8rqt.js.map +1 -0
- package/dist/web/assets/textile-CnDTJFAw.js +2 -0
- package/dist/web/assets/textile-CnDTJFAw.js.map +1 -0
- package/dist/web/assets/tiddlywiki-DO-Gjzrf.js +2 -0
- package/dist/web/assets/tiddlywiki-DO-Gjzrf.js.map +1 -0
- package/dist/web/assets/tiki-DGYXhP31.js +2 -0
- package/dist/web/assets/tiki-DGYXhP31.js.map +1 -0
- package/dist/web/assets/toml-Bm5Em-hy.js +2 -0
- package/dist/web/assets/toml-Bm5Em-hy.js.map +1 -0
- package/dist/web/assets/troff-wAsdV37c.js +2 -0
- package/dist/web/assets/troff-wAsdV37c.js.map +1 -0
- package/dist/web/assets/ttcn-CfJYG6tj.js +2 -0
- package/dist/web/assets/ttcn-CfJYG6tj.js.map +1 -0
- package/dist/web/assets/ttcn-cfg-B9xdYoR4.js +2 -0
- package/dist/web/assets/ttcn-cfg-B9xdYoR4.js.map +1 -0
- package/dist/web/assets/turtle-B1tBg_DP.js +2 -0
- package/dist/web/assets/turtle-B1tBg_DP.js.map +1 -0
- package/dist/web/assets/vb-CmGdzxic.js +2 -0
- package/dist/web/assets/vb-CmGdzxic.js.map +1 -0
- package/dist/web/assets/vbscript-BuJXcnF6.js +2 -0
- package/dist/web/assets/vbscript-BuJXcnF6.js.map +1 -0
- package/dist/web/assets/velocity-D8B20fx6.js +2 -0
- package/dist/web/assets/velocity-D8B20fx6.js.map +1 -0
- package/dist/web/assets/verilog-C6RDOZhf.js +2 -0
- package/dist/web/assets/verilog-C6RDOZhf.js.map +1 -0
- package/dist/web/assets/vhdl-lSbBsy5d.js +2 -0
- package/dist/web/assets/vhdl-lSbBsy5d.js.map +1 -0
- package/dist/web/assets/webidl-ZXfAyPTL.js +2 -0
- package/dist/web/assets/webidl-ZXfAyPTL.js.map +1 -0
- package/dist/web/assets/xquery-CQfU5ijd.js +2 -0
- package/dist/web/assets/xquery-CQfU5ijd.js.map +1 -0
- package/dist/web/assets/yacas-BJ4BC0dw.js +2 -0
- package/dist/web/assets/yacas-BJ4BC0dw.js.map +1 -0
- package/dist/web/assets/z80-Hz9HOZM7.js +2 -0
- package/dist/web/assets/z80-Hz9HOZM7.js.map +1 -0
- package/dist/web/index.html +23 -0
- package/package.json +75 -0
- package/public/.gitkeep +0 -0
- package/public/assets/apl-B4CMkyY2.js +2 -0
- package/public/assets/apl-B4CMkyY2.js.map +1 -0
- package/public/assets/asciiarmor-Df11BRmG.js +2 -0
- package/public/assets/asciiarmor-Df11BRmG.js.map +1 -0
- package/public/assets/asn1-EdZsLKOL.js +2 -0
- package/public/assets/asn1-EdZsLKOL.js.map +1 -0
- package/public/assets/asterisk-B-8jnY81.js +2 -0
- package/public/assets/asterisk-B-8jnY81.js.map +1 -0
- package/public/assets/brainfuck-C4LP7Hcl.js +2 -0
- package/public/assets/brainfuck-C4LP7Hcl.js.map +1 -0
- package/public/assets/clike-B9uivgTg.js +2 -0
- package/public/assets/clike-B9uivgTg.js.map +1 -0
- package/public/assets/clojure-BMjYHr_A.js +2 -0
- package/public/assets/clojure-BMjYHr_A.js.map +1 -0
- package/public/assets/cmake-BQqOBYOt.js +2 -0
- package/public/assets/cmake-BQqOBYOt.js.map +1 -0
- package/public/assets/cobol-CWcv1MsR.js +2 -0
- package/public/assets/cobol-CWcv1MsR.js.map +1 -0
- package/public/assets/coffeescript-S37ZYGWr.js +2 -0
- package/public/assets/coffeescript-S37ZYGWr.js.map +1 -0
- package/public/assets/commonlisp-DBKNyK5s.js +2 -0
- package/public/assets/commonlisp-DBKNyK5s.js.map +1 -0
- package/public/assets/crystal-SjHAIU92.js +2 -0
- package/public/assets/crystal-SjHAIU92.js.map +1 -0
- package/public/assets/css-BnMrqG3P.js +2 -0
- package/public/assets/css-BnMrqG3P.js.map +1 -0
- package/public/assets/cypher-C_CwsFkJ.js +2 -0
- package/public/assets/cypher-C_CwsFkJ.js.map +1 -0
- package/public/assets/d-pRatUO7H.js +2 -0
- package/public/assets/d-pRatUO7H.js.map +1 -0
- package/public/assets/diff-DbItnlRl.js +2 -0
- package/public/assets/diff-DbItnlRl.js.map +1 -0
- package/public/assets/dockerfile-BKs6k2Af.js +2 -0
- package/public/assets/dockerfile-BKs6k2Af.js.map +1 -0
- package/public/assets/dtd-DF_7sFjM.js +2 -0
- package/public/assets/dtd-DF_7sFjM.js.map +1 -0
- package/public/assets/dylan-DwRh75JA.js +2 -0
- package/public/assets/dylan-DwRh75JA.js.map +1 -0
- package/public/assets/ebnf-CDyGwa7X.js +2 -0
- package/public/assets/ebnf-CDyGwa7X.js.map +1 -0
- package/public/assets/ecl-Cabwm37j.js +2 -0
- package/public/assets/ecl-Cabwm37j.js.map +1 -0
- package/public/assets/eiffel-CnydiIhH.js +2 -0
- package/public/assets/eiffel-CnydiIhH.js.map +1 -0
- package/public/assets/elm-vLlmbW-K.js +2 -0
- package/public/assets/elm-vLlmbW-K.js.map +1 -0
- package/public/assets/erlang-BNw1qcRV.js +2 -0
- package/public/assets/erlang-BNw1qcRV.js.map +1 -0
- package/public/assets/factor-kuTfRLto.js +2 -0
- package/public/assets/factor-kuTfRLto.js.map +1 -0
- package/public/assets/fcl-Kvtd6kyn.js +2 -0
- package/public/assets/fcl-Kvtd6kyn.js.map +1 -0
- package/public/assets/forth-Ffai-XNe.js +2 -0
- package/public/assets/forth-Ffai-XNe.js.map +1 -0
- package/public/assets/fortran-DYz_wnZ1.js +2 -0
- package/public/assets/fortran-DYz_wnZ1.js.map +1 -0
- package/public/assets/gas-Bneqetm1.js +2 -0
- package/public/assets/gas-Bneqetm1.js.map +1 -0
- package/public/assets/gherkin-heZmZLOM.js +2 -0
- package/public/assets/gherkin-heZmZLOM.js.map +1 -0
- package/public/assets/groovy-D9Dt4D0W.js +2 -0
- package/public/assets/groovy-D9Dt4D0W.js.map +1 -0
- package/public/assets/haskell-BWDZoCOh.js +2 -0
- package/public/assets/haskell-BWDZoCOh.js.map +1 -0
- package/public/assets/haxe-H-WmDvRZ.js +2 -0
- package/public/assets/haxe-H-WmDvRZ.js.map +1 -0
- package/public/assets/http-DBlCnlav.js +2 -0
- package/public/assets/http-DBlCnlav.js.map +1 -0
- package/public/assets/idl-BEugSyMb.js +2 -0
- package/public/assets/idl-BEugSyMb.js.map +1 -0
- package/public/assets/index-BHi_kGSi.js +8 -0
- package/public/assets/index-BHi_kGSi.js.map +1 -0
- package/public/assets/index-BMLAwwWL.js +2 -0
- package/public/assets/index-BMLAwwWL.js.map +1 -0
- package/public/assets/index-BNSDh5mD.js +2 -0
- package/public/assets/index-BNSDh5mD.js.map +1 -0
- package/public/assets/index-BR0D24wt.js +2 -0
- package/public/assets/index-BR0D24wt.js.map +1 -0
- package/public/assets/index-BdLsiQv5.js +2 -0
- package/public/assets/index-BdLsiQv5.js.map +1 -0
- package/public/assets/index-BjnJos4J.js +2 -0
- package/public/assets/index-BjnJos4J.js.map +1 -0
- package/public/assets/index-CM3gGvbH.js +509 -0
- package/public/assets/index-CM3gGvbH.js.map +1 -0
- package/public/assets/index-CV8De3J9.js +2 -0
- package/public/assets/index-CV8De3J9.js.map +1 -0
- package/public/assets/index-ChuKVzLw.js +2 -0
- package/public/assets/index-ChuKVzLw.js.map +1 -0
- package/public/assets/index-CpfmaE2d.js +2 -0
- package/public/assets/index-CpfmaE2d.js.map +1 -0
- package/public/assets/index-D90_xI0s.js +2 -0
- package/public/assets/index-D90_xI0s.js.map +1 -0
- package/public/assets/index-DR3bJemi.js +4 -0
- package/public/assets/index-DR3bJemi.js.map +1 -0
- package/public/assets/index-DlsEbLHk.css +1 -0
- package/public/assets/index-MR5aWKcm.js +2 -0
- package/public/assets/index-MR5aWKcm.js.map +1 -0
- package/public/assets/index-MrhuDMHQ.js +2 -0
- package/public/assets/index-MrhuDMHQ.js.map +1 -0
- package/public/assets/index-NbLWR4tH.js +2 -0
- package/public/assets/index-NbLWR4tH.js.map +1 -0
- package/public/assets/index-VnBXaSng.js +3 -0
- package/public/assets/index-VnBXaSng.js.map +1 -0
- package/public/assets/index-XEgqkWdk.js +2 -0
- package/public/assets/index-XEgqkWdk.js.map +1 -0
- package/public/assets/index-zHvewZlp.js +2 -0
- package/public/assets/index-zHvewZlp.js.map +1 -0
- package/public/assets/javascript-qCveANmP.js +2 -0
- package/public/assets/javascript-qCveANmP.js.map +1 -0
- package/public/assets/julia-DuME0IfC.js +2 -0
- package/public/assets/julia-DuME0IfC.js.map +1 -0
- package/public/assets/livescript-BwQOo05w.js +2 -0
- package/public/assets/livescript-BwQOo05w.js.map +1 -0
- package/public/assets/lua-BgMRiT3U.js +2 -0
- package/public/assets/lua-BgMRiT3U.js.map +1 -0
- package/public/assets/mathematica-DTrFuWx2.js +2 -0
- package/public/assets/mathematica-DTrFuWx2.js.map +1 -0
- package/public/assets/mbox-CNhZ1qSd.js +2 -0
- package/public/assets/mbox-CNhZ1qSd.js.map +1 -0
- package/public/assets/mirc-CjQqDB4T.js +2 -0
- package/public/assets/mirc-CjQqDB4T.js.map +1 -0
- package/public/assets/mllike-CXdrOF99.js +2 -0
- package/public/assets/mllike-CXdrOF99.js.map +1 -0
- package/public/assets/modelica-Dc1JOy9r.js +2 -0
- package/public/assets/modelica-Dc1JOy9r.js.map +1 -0
- package/public/assets/mscgen-BA5vi2Kp.js +2 -0
- package/public/assets/mscgen-BA5vi2Kp.js.map +1 -0
- package/public/assets/mumps-BT43cFF4.js +2 -0
- package/public/assets/mumps-BT43cFF4.js.map +1 -0
- package/public/assets/nginx-DdIZxoE0.js +2 -0
- package/public/assets/nginx-DdIZxoE0.js.map +1 -0
- package/public/assets/nsis-LdVXkNf5.js +2 -0
- package/public/assets/nsis-LdVXkNf5.js.map +1 -0
- package/public/assets/ntriples-BfvgReVJ.js +2 -0
- package/public/assets/ntriples-BfvgReVJ.js.map +1 -0
- package/public/assets/octave-Ck1zUtKM.js +2 -0
- package/public/assets/octave-Ck1zUtKM.js.map +1 -0
- package/public/assets/oz-BzwKVEFT.js +2 -0
- package/public/assets/oz-BzwKVEFT.js.map +1 -0
- package/public/assets/pascal--L3eBynH.js +2 -0
- package/public/assets/pascal--L3eBynH.js.map +1 -0
- package/public/assets/perl-CdXCOZ3F.js +2 -0
- package/public/assets/perl-CdXCOZ3F.js.map +1 -0
- package/public/assets/pig-CevX1Tat.js +2 -0
- package/public/assets/pig-CevX1Tat.js.map +1 -0
- package/public/assets/powershell-CFHJl5sT.js +2 -0
- package/public/assets/powershell-CFHJl5sT.js.map +1 -0
- package/public/assets/properties-C78fOPTZ.js +2 -0
- package/public/assets/properties-C78fOPTZ.js.map +1 -0
- package/public/assets/protobuf-ChK-085T.js +2 -0
- package/public/assets/protobuf-ChK-085T.js.map +1 -0
- package/public/assets/pug-DukmZTjD.js +2 -0
- package/public/assets/pug-DukmZTjD.js.map +1 -0
- package/public/assets/puppet-DMA9R1ak.js +2 -0
- package/public/assets/puppet-DMA9R1ak.js.map +1 -0
- package/public/assets/python-BuPzkPfP.js +2 -0
- package/public/assets/python-BuPzkPfP.js.map +1 -0
- package/public/assets/q-pXgVlZs6.js +2 -0
- package/public/assets/q-pXgVlZs6.js.map +1 -0
- package/public/assets/r-DUYO_cvP.js +2 -0
- package/public/assets/r-DUYO_cvP.js.map +1 -0
- package/public/assets/rpm-CTu-6PCP.js +2 -0
- package/public/assets/rpm-CTu-6PCP.js.map +1 -0
- package/public/assets/ruby-B2Rjki9n.js +2 -0
- package/public/assets/ruby-B2Rjki9n.js.map +1 -0
- package/public/assets/sas-B4kiWyti.js +2 -0
- package/public/assets/sas-B4kiWyti.js.map +1 -0
- package/public/assets/scheme-C41bIUwD.js +2 -0
- package/public/assets/scheme-C41bIUwD.js.map +1 -0
- package/public/assets/shell-CjFT_Tl9.js +2 -0
- package/public/assets/shell-CjFT_Tl9.js.map +1 -0
- package/public/assets/sieve-C3Gn_uJK.js +2 -0
- package/public/assets/sieve-C3Gn_uJK.js.map +1 -0
- package/public/assets/simple-mode-GW_nhZxv.js +2 -0
- package/public/assets/simple-mode-GW_nhZxv.js.map +1 -0
- package/public/assets/smalltalk-CnHTOXQT.js +2 -0
- package/public/assets/smalltalk-CnHTOXQT.js.map +1 -0
- package/public/assets/solr-DehyRSwq.js +2 -0
- package/public/assets/solr-DehyRSwq.js.map +1 -0
- package/public/assets/sparql-DkYu6x3z.js +2 -0
- package/public/assets/sparql-DkYu6x3z.js.map +1 -0
- package/public/assets/spreadsheet-BCZA_wO0.js +2 -0
- package/public/assets/spreadsheet-BCZA_wO0.js.map +1 -0
- package/public/assets/sql-D0XecflT.js +2 -0
- package/public/assets/sql-D0XecflT.js.map +1 -0
- package/public/assets/stex-C3f8Ysf7.js +2 -0
- package/public/assets/stex-C3f8Ysf7.js.map +1 -0
- package/public/assets/stylus-B533Al4x.js +2 -0
- package/public/assets/stylus-B533Al4x.js.map +1 -0
- package/public/assets/swift-BzpIVaGY.js +2 -0
- package/public/assets/swift-BzpIVaGY.js.map +1 -0
- package/public/assets/tcl-DVfN8rqt.js +2 -0
- package/public/assets/tcl-DVfN8rqt.js.map +1 -0
- package/public/assets/textile-CnDTJFAw.js +2 -0
- package/public/assets/textile-CnDTJFAw.js.map +1 -0
- package/public/assets/tiddlywiki-DO-Gjzrf.js +2 -0
- package/public/assets/tiddlywiki-DO-Gjzrf.js.map +1 -0
- package/public/assets/tiki-DGYXhP31.js +2 -0
- package/public/assets/tiki-DGYXhP31.js.map +1 -0
- package/public/assets/toml-Bm5Em-hy.js +2 -0
- package/public/assets/toml-Bm5Em-hy.js.map +1 -0
- package/public/assets/troff-wAsdV37c.js +2 -0
- package/public/assets/troff-wAsdV37c.js.map +1 -0
- package/public/assets/ttcn-CfJYG6tj.js +2 -0
- package/public/assets/ttcn-CfJYG6tj.js.map +1 -0
- package/public/assets/ttcn-cfg-B9xdYoR4.js +2 -0
- package/public/assets/ttcn-cfg-B9xdYoR4.js.map +1 -0
- package/public/assets/turtle-B1tBg_DP.js +2 -0
- package/public/assets/turtle-B1tBg_DP.js.map +1 -0
- package/public/assets/vb-CmGdzxic.js +2 -0
- package/public/assets/vb-CmGdzxic.js.map +1 -0
- package/public/assets/vbscript-BuJXcnF6.js +2 -0
- package/public/assets/vbscript-BuJXcnF6.js.map +1 -0
- package/public/assets/velocity-D8B20fx6.js +2 -0
- package/public/assets/velocity-D8B20fx6.js.map +1 -0
- package/public/assets/verilog-C6RDOZhf.js +2 -0
- package/public/assets/verilog-C6RDOZhf.js.map +1 -0
- package/public/assets/vhdl-lSbBsy5d.js +2 -0
- package/public/assets/vhdl-lSbBsy5d.js.map +1 -0
- package/public/assets/webidl-ZXfAyPTL.js +2 -0
- package/public/assets/webidl-ZXfAyPTL.js.map +1 -0
- package/public/assets/xquery-CQfU5ijd.js +2 -0
- package/public/assets/xquery-CQfU5ijd.js.map +1 -0
- package/public/assets/yacas-BJ4BC0dw.js +2 -0
- package/public/assets/yacas-BJ4BC0dw.js.map +1 -0
- package/public/assets/z80-Hz9HOZM7.js +2 -0
- package/public/assets/z80-Hz9HOZM7.js.map +1 -0
- package/public/index.html +15 -0
|
@@ -0,0 +1,829 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notes API Routes
|
|
3
|
+
*
|
|
4
|
+
* Handles notes index operations: search, files, status, sync.
|
|
5
|
+
* All operations work on the currently active project.
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import { getCurrentProject, requireProjectContext, updateSecretsIfNeeded } from './project.js';
|
|
11
|
+
import { emitEvent } from './events.js';
|
|
12
|
+
import { createSyncHandler } from './sync-handler.js';
|
|
13
|
+
import { createGrep, isError } from 'grepmind-core';
|
|
14
|
+
import { validateSecrets } from 'grepmind-config';
|
|
15
|
+
/**
|
|
16
|
+
* Ensure a project is open, return 400 if not
|
|
17
|
+
*/
|
|
18
|
+
function requireProject(reply) {
|
|
19
|
+
const project = getCurrentProject();
|
|
20
|
+
if (!project) {
|
|
21
|
+
reply.status(400).send({
|
|
22
|
+
error: 'No project open',
|
|
23
|
+
message: 'Open a project first using POST /api/project/open',
|
|
24
|
+
});
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get vault paths for current project
|
|
31
|
+
*/
|
|
32
|
+
function getVaultPaths() {
|
|
33
|
+
const project = getCurrentProject();
|
|
34
|
+
if (!project)
|
|
35
|
+
return [];
|
|
36
|
+
const vaultRelatives = project.config.vaultPaths || ['./vault'];
|
|
37
|
+
return vaultRelatives.map((vp) => path.resolve(project.path, vp));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get primary vault path for current project (first in list)
|
|
41
|
+
*/
|
|
42
|
+
function getVaultPath() {
|
|
43
|
+
const paths = getVaultPaths();
|
|
44
|
+
return paths.length > 0 ? paths[0] : null;
|
|
45
|
+
}
|
|
46
|
+
function isPathWithinRoot(filePath, root) {
|
|
47
|
+
const normalizedRoot = path.resolve(root);
|
|
48
|
+
const normalizedPath = path.resolve(filePath);
|
|
49
|
+
return (normalizedPath === normalizedRoot ||
|
|
50
|
+
normalizedPath.startsWith(`${normalizedRoot}${path.sep}`));
|
|
51
|
+
}
|
|
52
|
+
function resolveVaultFilePath(vaultPath, relativePath) {
|
|
53
|
+
const fullPath = path.resolve(vaultPath, relativePath);
|
|
54
|
+
return isPathWithinRoot(fullPath, vaultPath) ? fullPath : null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Register notes routes
|
|
58
|
+
*/
|
|
59
|
+
export async function notesRoutes(app) {
|
|
60
|
+
/**
|
|
61
|
+
* GET /api/notes/status
|
|
62
|
+
* Get notes index status for current project
|
|
63
|
+
*/
|
|
64
|
+
app.get('/status', async (request, reply) => {
|
|
65
|
+
if (!requireProject(reply))
|
|
66
|
+
return;
|
|
67
|
+
const vaultPath = getVaultPath();
|
|
68
|
+
try {
|
|
69
|
+
const context = requireProjectContext();
|
|
70
|
+
// Get actual stats from Indexer
|
|
71
|
+
const stats = await context.indexer.getStats();
|
|
72
|
+
// Count total files in vault for comparison
|
|
73
|
+
const files = await glob('**/*.md', {
|
|
74
|
+
cwd: vaultPath,
|
|
75
|
+
nodir: true,
|
|
76
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
77
|
+
});
|
|
78
|
+
const status = {
|
|
79
|
+
totalFiles: files.length,
|
|
80
|
+
indexedFiles: stats.totalFiles,
|
|
81
|
+
totalChunks: stats.totalChunks,
|
|
82
|
+
lastSync: undefined,
|
|
83
|
+
lastSyncCommit: undefined,
|
|
84
|
+
};
|
|
85
|
+
return reply.send(status);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
app.log.error(error);
|
|
89
|
+
return reply.status(500).send({
|
|
90
|
+
error: 'Failed to get status',
|
|
91
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* GET /api/notes/files
|
|
97
|
+
* List all note files with index status
|
|
98
|
+
*/
|
|
99
|
+
app.get('/files', {
|
|
100
|
+
schema: {
|
|
101
|
+
querystring: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
properties: {
|
|
104
|
+
folder: { type: 'string' },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
}, async (request, reply) => {
|
|
109
|
+
if (!requireProject(reply))
|
|
110
|
+
return;
|
|
111
|
+
const { folder } = request.query;
|
|
112
|
+
const vaultPath = getVaultPath();
|
|
113
|
+
try {
|
|
114
|
+
const context = requireProjectContext();
|
|
115
|
+
const pattern = folder ? `${folder}/**/*.md` : '**/*.md';
|
|
116
|
+
const files = await glob(pattern, {
|
|
117
|
+
cwd: vaultPath,
|
|
118
|
+
nodir: true,
|
|
119
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
120
|
+
stat: true,
|
|
121
|
+
withFileTypes: true,
|
|
122
|
+
});
|
|
123
|
+
// Get indexed files map for status checking
|
|
124
|
+
const indexedFiles = await context.indexer.getIndexedFiles();
|
|
125
|
+
const noteFiles = await Promise.all(files.map(async (file) => {
|
|
126
|
+
const relativePath = typeof file === 'string' ? file : file.relative();
|
|
127
|
+
const fullPath = path.join(vaultPath, relativePath);
|
|
128
|
+
const stat = await fs.stat(fullPath);
|
|
129
|
+
// Check index status
|
|
130
|
+
const indexInfo = indexedFiles.get(relativePath);
|
|
131
|
+
let indexStatus = 'unindexed';
|
|
132
|
+
if (indexInfo) {
|
|
133
|
+
// File is indexed - check if modified since
|
|
134
|
+
const fileMtime = stat.mtimeMs;
|
|
135
|
+
if (fileMtime > indexInfo.indexed_at) {
|
|
136
|
+
indexStatus = 'modified';
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
indexStatus = 'indexed';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
path: fullPath,
|
|
144
|
+
name: path.basename(relativePath),
|
|
145
|
+
relativePath,
|
|
146
|
+
indexStatus,
|
|
147
|
+
chunks: indexInfo?.chunks,
|
|
148
|
+
size: stat.size,
|
|
149
|
+
lastIndexed: indexInfo ? new Date(indexInfo.indexed_at).toISOString() : undefined,
|
|
150
|
+
};
|
|
151
|
+
}));
|
|
152
|
+
return reply.send(noteFiles);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
app.log.error(error);
|
|
156
|
+
return reply.status(500).send({
|
|
157
|
+
error: 'Failed to list files',
|
|
158
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
/**
|
|
163
|
+
* GET /api/notes/search-titles
|
|
164
|
+
* Search note titles and paths for wikilink autocomplete.
|
|
165
|
+
*/
|
|
166
|
+
app.get('/search-titles', {
|
|
167
|
+
schema: {
|
|
168
|
+
querystring: {
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: {
|
|
171
|
+
q: { type: 'string' },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
}, async (request, reply) => {
|
|
176
|
+
if (!requireProject(reply))
|
|
177
|
+
return;
|
|
178
|
+
const vaultPath = getVaultPath();
|
|
179
|
+
const query = (request.query.q || '').trim().toLowerCase();
|
|
180
|
+
try {
|
|
181
|
+
const files = await glob('**/*.md', {
|
|
182
|
+
cwd: vaultPath,
|
|
183
|
+
nodir: true,
|
|
184
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
185
|
+
});
|
|
186
|
+
const matches = files
|
|
187
|
+
.map((relativePath) => ({
|
|
188
|
+
path: relativePath,
|
|
189
|
+
title: path.basename(relativePath, '.md'),
|
|
190
|
+
}))
|
|
191
|
+
.filter((note) => {
|
|
192
|
+
if (!query)
|
|
193
|
+
return true;
|
|
194
|
+
return (note.title.toLowerCase().includes(query) ||
|
|
195
|
+
note.path.toLowerCase().includes(query));
|
|
196
|
+
})
|
|
197
|
+
.slice(0, 10);
|
|
198
|
+
return reply.send({ notes: matches });
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
app.log.error(error);
|
|
202
|
+
return reply.status(500).send({
|
|
203
|
+
error: 'Failed to search titles',
|
|
204
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
/**
|
|
209
|
+
* GET /api/notes/list
|
|
210
|
+
* Alias for title search used by wikilink autocomplete clients.
|
|
211
|
+
*/
|
|
212
|
+
app.get('/list', async (request, reply) => {
|
|
213
|
+
if (!requireProject(reply))
|
|
214
|
+
return;
|
|
215
|
+
const vaultPath = getVaultPath();
|
|
216
|
+
const query = (request.query.q || '').trim().toLowerCase();
|
|
217
|
+
try {
|
|
218
|
+
const files = await glob('**/*.md', {
|
|
219
|
+
cwd: vaultPath,
|
|
220
|
+
nodir: true,
|
|
221
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
222
|
+
});
|
|
223
|
+
const matches = files
|
|
224
|
+
.map((relativePath) => ({
|
|
225
|
+
path: relativePath,
|
|
226
|
+
title: path.basename(relativePath, '.md'),
|
|
227
|
+
}))
|
|
228
|
+
.filter((note) => {
|
|
229
|
+
if (!query)
|
|
230
|
+
return true;
|
|
231
|
+
return (note.title.toLowerCase().includes(query) ||
|
|
232
|
+
note.path.toLowerCase().includes(query));
|
|
233
|
+
})
|
|
234
|
+
.slice(0, 10);
|
|
235
|
+
return reply.send({ notes: matches });
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
app.log.error(error);
|
|
239
|
+
return reply.status(500).send({
|
|
240
|
+
error: 'Failed to list notes',
|
|
241
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
/**
|
|
246
|
+
* POST /api/notes/links/check
|
|
247
|
+
* Check if wiki-link targets exist and are indexed.
|
|
248
|
+
*/
|
|
249
|
+
app.post('/links/check', {
|
|
250
|
+
schema: {
|
|
251
|
+
body: {
|
|
252
|
+
type: 'object',
|
|
253
|
+
properties: {
|
|
254
|
+
targets: {
|
|
255
|
+
type: 'array',
|
|
256
|
+
items: { type: 'string' },
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
}, async (request, reply) => {
|
|
262
|
+
if (!requireProject(reply))
|
|
263
|
+
return;
|
|
264
|
+
const targets = (request.body?.targets || [])
|
|
265
|
+
.map((target) => target.trim())
|
|
266
|
+
.filter(Boolean);
|
|
267
|
+
if (targets.length === 0) {
|
|
268
|
+
return reply.send({});
|
|
269
|
+
}
|
|
270
|
+
const vaultPath = getVaultPath();
|
|
271
|
+
try {
|
|
272
|
+
const context = requireProjectContext();
|
|
273
|
+
const files = await glob('**/*.md', {
|
|
274
|
+
cwd: vaultPath,
|
|
275
|
+
nodir: true,
|
|
276
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
277
|
+
});
|
|
278
|
+
const indexedFiles = await context.indexer.getIndexedFiles();
|
|
279
|
+
const exactPathSet = new Set(files);
|
|
280
|
+
const normalizedPathSet = new Set(files.map((relativePath) => relativePath.replace(/\.md$/i, '')));
|
|
281
|
+
const basenameSet = new Set(files.map((relativePath) => path.basename(relativePath, '.md')));
|
|
282
|
+
const indexedPathSet = new Set(indexedFiles.keys());
|
|
283
|
+
const indexedNormalizedSet = new Set(Array.from(indexedFiles.keys()).map((relativePath) => relativePath.replace(/\.md$/i, '')));
|
|
284
|
+
const result = {};
|
|
285
|
+
for (const target of targets) {
|
|
286
|
+
const normalized = target.replace(/\.md$/i, '');
|
|
287
|
+
const withExt = target.endsWith('.md') ? target : `${target}.md`;
|
|
288
|
+
const exists = exactPathSet.has(withExt) ||
|
|
289
|
+
exactPathSet.has(target) ||
|
|
290
|
+
normalizedPathSet.has(normalized) ||
|
|
291
|
+
basenameSet.has(normalized);
|
|
292
|
+
const indexed = indexedPathSet.has(withExt) ||
|
|
293
|
+
indexedPathSet.has(target) ||
|
|
294
|
+
indexedNormalizedSet.has(normalized);
|
|
295
|
+
result[target] = {
|
|
296
|
+
target,
|
|
297
|
+
exists,
|
|
298
|
+
indexed,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
return reply.send(result);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
app.log.error(error);
|
|
305
|
+
return reply.status(500).send({
|
|
306
|
+
error: 'Failed to check links',
|
|
307
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
/**
|
|
312
|
+
* POST /api/notes/assets
|
|
313
|
+
* Save an uploaded image into a local assets folder near the note.
|
|
314
|
+
*/
|
|
315
|
+
app.post('/assets', {
|
|
316
|
+
schema: {
|
|
317
|
+
body: {
|
|
318
|
+
type: 'object',
|
|
319
|
+
required: ['notePath', 'fileName', 'contentBase64'],
|
|
320
|
+
properties: {
|
|
321
|
+
notePath: { type: 'string' },
|
|
322
|
+
fileName: { type: 'string' },
|
|
323
|
+
contentBase64: { type: 'string' },
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
}, async (request, reply) => {
|
|
328
|
+
if (!requireProject(reply))
|
|
329
|
+
return;
|
|
330
|
+
const vaultPath = getVaultPath();
|
|
331
|
+
const notePath = (request.body.notePath || '').trim();
|
|
332
|
+
const rawFileName = (request.body.fileName || '').trim();
|
|
333
|
+
const contentBase64 = request.body.contentBase64 || '';
|
|
334
|
+
if (!notePath || !rawFileName || !contentBase64) {
|
|
335
|
+
return reply.status(400).send({
|
|
336
|
+
error: 'Invalid body',
|
|
337
|
+
message: 'notePath, fileName and contentBase64 are required',
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
const noteFullPath = resolveVaultFilePath(vaultPath, notePath);
|
|
341
|
+
if (!noteFullPath) {
|
|
342
|
+
return reply.status(400).send({
|
|
343
|
+
error: 'Invalid path',
|
|
344
|
+
message: 'notePath must be within vault',
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const noteDirectory = path.dirname(noteFullPath);
|
|
349
|
+
const assetsDirectory = path.join(noteDirectory, 'assets');
|
|
350
|
+
const parsed = path.parse(path.basename(rawFileName));
|
|
351
|
+
const baseName = parsed.name || 'image';
|
|
352
|
+
const extension = parsed.ext || '.png';
|
|
353
|
+
await fs.mkdir(assetsDirectory, { recursive: true });
|
|
354
|
+
let finalName = `${baseName}${extension}`;
|
|
355
|
+
let fullAssetPath = path.join(assetsDirectory, finalName);
|
|
356
|
+
let counter = 1;
|
|
357
|
+
while (true) {
|
|
358
|
+
try {
|
|
359
|
+
await fs.access(fullAssetPath);
|
|
360
|
+
finalName = `${baseName}-${counter}${extension}`;
|
|
361
|
+
fullAssetPath = path.join(assetsDirectory, finalName);
|
|
362
|
+
counter++;
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const buffer = Buffer.from(contentBase64, 'base64');
|
|
369
|
+
await fs.writeFile(fullAssetPath, buffer);
|
|
370
|
+
const relativeAssetPath = path
|
|
371
|
+
.relative(vaultPath, fullAssetPath)
|
|
372
|
+
.split(path.sep)
|
|
373
|
+
.join('/');
|
|
374
|
+
return reply.send({
|
|
375
|
+
success: true,
|
|
376
|
+
path: relativeAssetPath,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
app.log.error(error);
|
|
381
|
+
return reply.status(500).send({
|
|
382
|
+
error: 'Failed to save asset',
|
|
383
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
/**
|
|
388
|
+
* GET /api/notes/files/:path
|
|
389
|
+
* Get details for a specific note file
|
|
390
|
+
*/
|
|
391
|
+
app.get('/files/*', async (request, reply) => {
|
|
392
|
+
if (!requireProject(reply))
|
|
393
|
+
return;
|
|
394
|
+
const filePath = request.params['*'];
|
|
395
|
+
const vaultPath = getVaultPath();
|
|
396
|
+
const fullPath = resolveVaultFilePath(vaultPath, filePath);
|
|
397
|
+
try {
|
|
398
|
+
// Ensure path is within vault
|
|
399
|
+
if (!fullPath) {
|
|
400
|
+
return reply.status(400).send({
|
|
401
|
+
error: 'Invalid path',
|
|
402
|
+
message: 'Path must be within vault',
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
const context = requireProjectContext();
|
|
406
|
+
const stat = await fs.stat(fullPath);
|
|
407
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
408
|
+
// Get index info for this file
|
|
409
|
+
const indexedFiles = await context.indexer.getIndexedFiles();
|
|
410
|
+
const indexInfo = indexedFiles.get(filePath);
|
|
411
|
+
let indexStatus = 'unindexed';
|
|
412
|
+
if (indexInfo) {
|
|
413
|
+
const fileMtime = stat.mtimeMs;
|
|
414
|
+
indexStatus = fileMtime > indexInfo.indexed_at ? 'modified' : 'indexed';
|
|
415
|
+
}
|
|
416
|
+
return reply.send({
|
|
417
|
+
path: fullPath,
|
|
418
|
+
name: path.basename(filePath),
|
|
419
|
+
relativePath: filePath,
|
|
420
|
+
indexStatus,
|
|
421
|
+
size: stat.size,
|
|
422
|
+
content,
|
|
423
|
+
chunks: indexInfo?.chunks ?? 0,
|
|
424
|
+
lastIndexed: indexInfo ? new Date(indexInfo.indexed_at).toISOString() : undefined,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
if (error.code === 'ENOENT') {
|
|
429
|
+
return reply.status(404).send({
|
|
430
|
+
error: 'File not found',
|
|
431
|
+
message: `Note not found: ${filePath}`,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
app.log.error(error);
|
|
435
|
+
return reply.status(500).send({
|
|
436
|
+
error: 'Failed to get file',
|
|
437
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
/**
|
|
442
|
+
* GET /api/notes/search
|
|
443
|
+
* Semantic search in notes
|
|
444
|
+
*/
|
|
445
|
+
app.get('/search', {
|
|
446
|
+
schema: {
|
|
447
|
+
querystring: {
|
|
448
|
+
type: 'object',
|
|
449
|
+
required: ['q'],
|
|
450
|
+
properties: {
|
|
451
|
+
q: { type: 'string' },
|
|
452
|
+
limit: { type: 'number', default: 10 },
|
|
453
|
+
threshold: { type: 'number', default: 0.5 },
|
|
454
|
+
tags: { type: 'string' },
|
|
455
|
+
folder: { type: 'string' },
|
|
456
|
+
path: { type: 'string' },
|
|
457
|
+
mode: { type: 'string', enum: ['hybrid', 'semantic', 'text'], default: 'hybrid' },
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
}, async (request, reply) => {
|
|
462
|
+
if (!requireProject(reply))
|
|
463
|
+
return;
|
|
464
|
+
const { q, limit = 10, threshold = 0.5, tags, folder, path: pathFilter, mode = 'hybrid' } = request.query;
|
|
465
|
+
try {
|
|
466
|
+
// Update secrets if changed (e.g., Voyage API key added after project open)
|
|
467
|
+
await updateSecretsIfNeeded(request.secrets || {});
|
|
468
|
+
const context = requireProjectContext();
|
|
469
|
+
const parsedTags = tags ? tags.split(',').map(t => t.trim()) : undefined;
|
|
470
|
+
const folderFilter = folder ?? pathFilter;
|
|
471
|
+
let searchResults;
|
|
472
|
+
if (mode === 'text') {
|
|
473
|
+
searchResults = await context.indexer.searchFts({
|
|
474
|
+
query: q,
|
|
475
|
+
limit,
|
|
476
|
+
folder: folderFilter,
|
|
477
|
+
tags: parsedTags,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
else if (mode === 'semantic') {
|
|
481
|
+
searchResults = await context.indexer.search(q, {
|
|
482
|
+
limit,
|
|
483
|
+
threshold,
|
|
484
|
+
tags: parsedTags,
|
|
485
|
+
folder: folderFilter,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
searchResults = await context.indexer.searchHybrid({
|
|
490
|
+
query: q,
|
|
491
|
+
limit,
|
|
492
|
+
threshold,
|
|
493
|
+
tags: parsedTags,
|
|
494
|
+
folder: folderFilter,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
if (isError(searchResults)) {
|
|
498
|
+
return reply.status(500).send({
|
|
499
|
+
error: 'Search failed',
|
|
500
|
+
message: searchResults.message,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
const results = searchResults.map(r => ({
|
|
504
|
+
path: r.path,
|
|
505
|
+
section: r.section,
|
|
506
|
+
score: r.score,
|
|
507
|
+
content: r.content,
|
|
508
|
+
title: r.title,
|
|
509
|
+
tags: r.tags,
|
|
510
|
+
links: r.links,
|
|
511
|
+
}));
|
|
512
|
+
return reply.send({
|
|
513
|
+
query: q,
|
|
514
|
+
results,
|
|
515
|
+
total: results.length,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
app.log.error(error);
|
|
520
|
+
return reply.status(500).send({
|
|
521
|
+
error: 'Search failed',
|
|
522
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
/**
|
|
527
|
+
* GET /api/notes/grep
|
|
528
|
+
* Exact text search in notes
|
|
529
|
+
*/
|
|
530
|
+
app.get('/grep', {
|
|
531
|
+
schema: {
|
|
532
|
+
querystring: {
|
|
533
|
+
type: 'object',
|
|
534
|
+
required: ['pattern'],
|
|
535
|
+
properties: {
|
|
536
|
+
pattern: { type: 'string' },
|
|
537
|
+
regex: { type: 'boolean', default: false },
|
|
538
|
+
caseSensitive: { type: 'boolean', default: false },
|
|
539
|
+
limit: { type: 'number', default: 20 },
|
|
540
|
+
folder: { type: 'string' },
|
|
541
|
+
context: { type: 'number', default: 1 },
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
}, async (request, reply) => {
|
|
546
|
+
if (!requireProject(reply))
|
|
547
|
+
return;
|
|
548
|
+
const { pattern, regex = false, caseSensitive = false, limit = 20, folder, context: contextLines = 1 } = request.query;
|
|
549
|
+
try {
|
|
550
|
+
const ctx = requireProjectContext();
|
|
551
|
+
const grep = createGrep(ctx.vaultUtils);
|
|
552
|
+
const grepResult = await grep.search({
|
|
553
|
+
pattern,
|
|
554
|
+
regex,
|
|
555
|
+
caseSensitive,
|
|
556
|
+
limit,
|
|
557
|
+
folder,
|
|
558
|
+
context: contextLines,
|
|
559
|
+
});
|
|
560
|
+
// Transform to API response format
|
|
561
|
+
const results = grepResult.files.map(file => ({
|
|
562
|
+
path: file.path,
|
|
563
|
+
matches: file.matches.map(m => ({
|
|
564
|
+
line: m.lineNumber,
|
|
565
|
+
content: m.line,
|
|
566
|
+
contextBefore: m.contextBefore,
|
|
567
|
+
contextAfter: m.contextAfter,
|
|
568
|
+
})),
|
|
569
|
+
}));
|
|
570
|
+
return reply.send({
|
|
571
|
+
pattern,
|
|
572
|
+
results,
|
|
573
|
+
total: grepResult.totalMatches,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
app.log.error(error);
|
|
578
|
+
return reply.status(500).send({
|
|
579
|
+
error: 'Grep failed',
|
|
580
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
/**
|
|
585
|
+
* GET /api/notes/backlinks/:path
|
|
586
|
+
* Get notes that link to the specified note
|
|
587
|
+
*/
|
|
588
|
+
app.get('/backlinks/*', async (request, reply) => {
|
|
589
|
+
if (!requireProject(reply))
|
|
590
|
+
return;
|
|
591
|
+
const filePath = request.params['*'];
|
|
592
|
+
const vaultPath = getVaultPath();
|
|
593
|
+
try {
|
|
594
|
+
// Extract note name without extension for wiki-link matching
|
|
595
|
+
const noteName = path.basename(filePath, '.md');
|
|
596
|
+
// Escape special regex characters
|
|
597
|
+
const escapedName = noteName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
598
|
+
// Match [[noteName]] or [[noteName|alias]] - case insensitive
|
|
599
|
+
const wikiLinkPattern = new RegExp(`\\[\\[${escapedName}(\\|[^\\]]*)?\\]\\]`, 'gi');
|
|
600
|
+
const files = await glob('**/*.md', {
|
|
601
|
+
cwd: vaultPath,
|
|
602
|
+
nodir: true,
|
|
603
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
604
|
+
});
|
|
605
|
+
const backlinks = [];
|
|
606
|
+
for (const file of files) {
|
|
607
|
+
if (file === filePath)
|
|
608
|
+
continue; // Skip self
|
|
609
|
+
const fullPath = path.join(vaultPath, file);
|
|
610
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
611
|
+
const lines = content.split('\n');
|
|
612
|
+
for (let index = 0; index < lines.length; index++) {
|
|
613
|
+
const line = lines[index];
|
|
614
|
+
// Reset lastIndex before each test (required for /g flag)
|
|
615
|
+
wikiLinkPattern.lastIndex = 0;
|
|
616
|
+
if (wikiLinkPattern.test(line)) {
|
|
617
|
+
backlinks.push({
|
|
618
|
+
source: file,
|
|
619
|
+
context: line.trim(),
|
|
620
|
+
line: index + 1,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return reply.send({
|
|
626
|
+
target: filePath,
|
|
627
|
+
backlinks,
|
|
628
|
+
total: backlinks.length,
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
app.log.error(error);
|
|
633
|
+
return reply.status(500).send({
|
|
634
|
+
error: 'Failed to get backlinks',
|
|
635
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
/**
|
|
640
|
+
* POST /api/notes/sync
|
|
641
|
+
* Trigger notes sync using SyncWal for recovery and progress tracking
|
|
642
|
+
*/
|
|
643
|
+
app.post('/sync', {
|
|
644
|
+
schema: {
|
|
645
|
+
body: {
|
|
646
|
+
type: 'object',
|
|
647
|
+
properties: {
|
|
648
|
+
force: { type: 'boolean', default: false },
|
|
649
|
+
resume: { type: 'boolean', default: false },
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
}, async (request, reply) => {
|
|
654
|
+
// Update secrets if changed (e.g., Voyage API key added after project open)
|
|
655
|
+
await updateSecretsIfNeeded(request.secrets || {});
|
|
656
|
+
const handler = createSyncHandler(app, {
|
|
657
|
+
type: 'notes',
|
|
658
|
+
isEnabled: (ctx) => !!ctx.indexer,
|
|
659
|
+
notEnabledError: 'Notes indexer is not initialized for this project',
|
|
660
|
+
validate: async () => {
|
|
661
|
+
// Check if required secrets are present for the configured provider
|
|
662
|
+
const project = getCurrentProject();
|
|
663
|
+
if (!project)
|
|
664
|
+
return 'No project open';
|
|
665
|
+
const error = validateSecrets(project.config, project.secrets);
|
|
666
|
+
return error;
|
|
667
|
+
},
|
|
668
|
+
clearIndex: async (ctx) => {
|
|
669
|
+
await ctx.indexer.clearIndex();
|
|
670
|
+
},
|
|
671
|
+
runSync: async (ctx, recoveryPlan) => {
|
|
672
|
+
const result = await ctx.indexer.reindexAllWithSyncWal(recoveryPlan || undefined);
|
|
673
|
+
return { indexed: result.indexed, deleted: result.deleted };
|
|
674
|
+
},
|
|
675
|
+
});
|
|
676
|
+
return handler(request, reply);
|
|
677
|
+
});
|
|
678
|
+
/**
|
|
679
|
+
* POST /api/notes/reindex
|
|
680
|
+
* Reindex specific files or folders
|
|
681
|
+
*/
|
|
682
|
+
app.post('/reindex', {
|
|
683
|
+
schema: {
|
|
684
|
+
body: {
|
|
685
|
+
type: 'object',
|
|
686
|
+
required: ['paths'],
|
|
687
|
+
properties: {
|
|
688
|
+
paths: {
|
|
689
|
+
type: 'array',
|
|
690
|
+
items: { type: 'string' },
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
},
|
|
695
|
+
}, async (request, reply) => {
|
|
696
|
+
if (!requireProject(reply))
|
|
697
|
+
return;
|
|
698
|
+
const { paths } = request.body;
|
|
699
|
+
const project = getCurrentProject();
|
|
700
|
+
try {
|
|
701
|
+
emitEvent({
|
|
702
|
+
type: 'reindex:notes:started',
|
|
703
|
+
data: { paths },
|
|
704
|
+
});
|
|
705
|
+
// TODO: Implement actual reindexing
|
|
706
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
707
|
+
emitEvent({
|
|
708
|
+
type: 'reindex:notes:completed',
|
|
709
|
+
data: { paths },
|
|
710
|
+
});
|
|
711
|
+
return reply.send({
|
|
712
|
+
success: true,
|
|
713
|
+
message: `Reindexed ${paths.length} paths`,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
emitEvent({
|
|
718
|
+
type: 'reindex:notes:error',
|
|
719
|
+
data: {
|
|
720
|
+
paths,
|
|
721
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
722
|
+
},
|
|
723
|
+
});
|
|
724
|
+
app.log.error(error);
|
|
725
|
+
return reply.status(500).send({
|
|
726
|
+
error: 'Reindex failed',
|
|
727
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
const updateNoteHandler = async (request, reply) => {
|
|
732
|
+
if (!requireProject(reply))
|
|
733
|
+
return;
|
|
734
|
+
const filePath = request.params['*'];
|
|
735
|
+
const content = request.body?.content;
|
|
736
|
+
const vaultPath = getVaultPath();
|
|
737
|
+
const fullPath = resolveVaultFilePath(vaultPath, filePath);
|
|
738
|
+
if (!fullPath) {
|
|
739
|
+
return reply.status(400).send({
|
|
740
|
+
error: 'Invalid path',
|
|
741
|
+
message: 'Path must be within vault',
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
if (typeof content !== 'string') {
|
|
745
|
+
return reply.status(400).send({
|
|
746
|
+
error: 'Invalid body',
|
|
747
|
+
message: 'Body must include string field: content',
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
try {
|
|
751
|
+
const context = requireProjectContext();
|
|
752
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
753
|
+
await fs.writeFile(fullPath, content, 'utf-8');
|
|
754
|
+
const indexResult = await context.indexer.indexFile(filePath);
|
|
755
|
+
if (isError(indexResult)) {
|
|
756
|
+
app.log.error(indexResult);
|
|
757
|
+
return reply.status(500).send({
|
|
758
|
+
error: 'Reindex failed',
|
|
759
|
+
message: indexResult.message,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
return reply.send({
|
|
763
|
+
success: true,
|
|
764
|
+
indexed: true,
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
catch (error) {
|
|
768
|
+
app.log.error(error);
|
|
769
|
+
return reply.status(500).send({
|
|
770
|
+
error: 'Failed to update note',
|
|
771
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
/**
|
|
776
|
+
* PUT /api/notes/files/:path
|
|
777
|
+
* Update note content and reindex the file.
|
|
778
|
+
*/
|
|
779
|
+
app.put('/files/*', {
|
|
780
|
+
schema: {
|
|
781
|
+
body: {
|
|
782
|
+
type: 'object',
|
|
783
|
+
required: ['content'],
|
|
784
|
+
properties: {
|
|
785
|
+
content: { type: 'string' },
|
|
786
|
+
},
|
|
787
|
+
},
|
|
788
|
+
},
|
|
789
|
+
}, updateNoteHandler);
|
|
790
|
+
/**
|
|
791
|
+
* PUT /api/notes/:path
|
|
792
|
+
* Alias for updating note content and reindexing.
|
|
793
|
+
*/
|
|
794
|
+
app.put('/*', {
|
|
795
|
+
schema: {
|
|
796
|
+
body: {
|
|
797
|
+
type: 'object',
|
|
798
|
+
required: ['content'],
|
|
799
|
+
properties: {
|
|
800
|
+
content: { type: 'string' },
|
|
801
|
+
},
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
}, updateNoteHandler);
|
|
805
|
+
/**
|
|
806
|
+
* DELETE /api/notes/files/:path
|
|
807
|
+
* Remove a file from the index (not from disk)
|
|
808
|
+
*/
|
|
809
|
+
app.delete('/files/*', async (request, reply) => {
|
|
810
|
+
if (!requireProject(reply))
|
|
811
|
+
return;
|
|
812
|
+
const filePath = request.params['*'];
|
|
813
|
+
try {
|
|
814
|
+
// TODO: Implement actual removal from index
|
|
815
|
+
return reply.send({
|
|
816
|
+
success: true,
|
|
817
|
+
message: `Removed ${filePath} from index`,
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
catch (error) {
|
|
821
|
+
app.log.error(error);
|
|
822
|
+
return reply.status(500).send({
|
|
823
|
+
error: 'Failed to remove from index',
|
|
824
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
//# sourceMappingURL=notes.js.map
|