@pubinfo/devtools 2.0.15 → 2.1.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/dist/client/assets/abap-C4bT1QEl.js +3 -0
- package/dist/client/assets/actionscript-3-BCWJ3mFB.js +3 -0
- package/dist/client/assets/ada-BwfYJ3cr.js +3 -0
- package/dist/client/assets/andromeeda-B_6dIUNk.js +2 -0
- package/dist/client/assets/angular-html-BPWgfvBc.js +23 -0
- package/dist/client/assets/angular-html-CAmvPqke.js +5 -0
- package/dist/client/assets/angular-ts-DGzTDMev.js +24 -0
- package/dist/client/assets/apache-kfYmMYjJ.js +3 -0
- package/dist/client/assets/apex-BEradrtF.js +3 -0
- package/dist/client/assets/apl-BPuavpVx.js +16 -0
- package/dist/client/assets/applescript-CuHZw4Cf.js +3 -0
- package/dist/client/assets/ara-BkKR-TQQ.js +3 -0
- package/dist/client/assets/asciidoc-CBayNp_C.js +3 -0
- package/dist/client/assets/asm-BwfqIsue.js +3 -0
- package/dist/client/assets/astro-S5XuEH5N.js +17 -0
- package/dist/client/assets/aurora-x-BXNTnfne.js +2 -0
- package/dist/client/assets/awk-BTtzreuE.js +3 -0
- package/dist/client/assets/ayu-dark-DqipJzHd.js +2 -0
- package/dist/client/assets/ballerina-Cr0e12Uh.js +3 -0
- package/dist/client/assets/bat--mz103Th.js +3 -0
- package/dist/client/assets/beancount-CFAdYWr2.js +3 -0
- package/dist/client/assets/berry-Bzd2YdCH.js +3 -0
- package/dist/client/assets/bibtex-DT-WcF1n.js +3 -0
- package/dist/client/assets/bicep-DUXUP27W.js +3 -0
- package/dist/client/assets/blade-BD3Ti8S8.js +20 -0
- package/dist/client/assets/bsl-FJCc2ZjR.js +4 -0
- package/dist/client/assets/c-0S9FUYVg.js +2 -0
- package/dist/client/assets/c-DcdCmnmu.js +3 -0
- package/dist/client/assets/cadence-Du0qqjuO.js +3 -0
- package/dist/client/assets/cairo-CT1kFY4g.js +4 -0
- package/dist/client/assets/catppuccin-frappe-DZIny9D9.js +2 -0
- package/dist/client/assets/catppuccin-latte-HfmdJgD2.js +2 -0
- package/dist/client/assets/catppuccin-macchiato-1ffQHJ6s.js +2 -0
- package/dist/client/assets/catppuccin-mocha-DRYMSOp4.js +2 -0
- package/dist/client/assets/clarity-CW1NMBSy.js +3 -0
- package/dist/client/assets/clojure-DkHpOkH2.js +3 -0
- package/dist/client/assets/cmake-87ADX9pg.js +2 -0
- package/dist/client/assets/cmake-CXVvo3Mh.js +3 -0
- package/dist/client/assets/cobol-CE0tFF5i.js +11 -0
- package/dist/client/assets/codeowners-DYf_YsrY.js +3 -0
- package/dist/client/assets/codeql-BeSKjUdD.js +3 -0
- package/dist/client/assets/coffee-D8rtNx1a.js +4 -0
- package/dist/client/assets/common-lisp-CsedMwlK.js +3 -0
- package/dist/client/assets/coq-Cfs5oQ5z.js +3 -0
- package/dist/client/assets/cpp-B4kRV-Mr.js +6 -0
- package/dist/client/assets/cpp-C4U1u9xk.js +19 -0
- package/dist/client/assets/crystal-C51LLczf.js +17 -0
- package/dist/client/assets/csharp-CxX8v9Z1.js +2 -0
- package/dist/client/assets/csharp-DYqgfnaO.js +3 -0
- package/dist/client/assets/css-BmwDvvHL.js +2 -0
- package/dist/client/assets/css-DVW7ZXKV.js +3 -0
- package/dist/client/assets/csv-B2eUHTA8.js +2 -0
- package/dist/client/assets/csv-rLH0WuQO.js +3 -0
- package/dist/client/assets/cue-CzLrU992.js +3 -0
- package/dist/client/assets/cypher-C2RENEAP.js +3 -0
- package/dist/client/assets/d-BJOAQFpK.js +3 -0
- package/dist/client/assets/dark-plus-Db9rRSHq.js +2 -0
- package/dist/client/assets/dart-B-KTJ0-J.js +3 -0
- package/dist/client/assets/dax-B7qtS36S.js +3 -0
- package/dist/client/assets/desktop-DfgAqZ8-.js +3 -0
- package/dist/client/assets/diff-akky_HM9.js +3 -0
- package/dist/client/assets/diff-pjHYd3BC.js +2 -0
- package/dist/client/assets/docker-CRnIvYqh.js +3 -0
- package/dist/client/assets/dotenv-CwGZ7tJA.js +3 -0
- package/dist/client/assets/dracula-C0nacXF8.js +2 -0
- package/dist/client/assets/dracula-soft-wdVBcfBY.js +2 -0
- package/dist/client/assets/dream-maker-B9ezz9kX.js +3 -0
- package/dist/client/assets/edge-WSoBDjCt.js +13 -0
- package/dist/client/assets/elixir-4Bcc41kI.js +6 -0
- package/dist/client/assets/elm-DisSriNR.js +5 -0
- package/dist/client/assets/emacs-lisp-fLGPzin6.js +3 -0
- package/dist/client/assets/erb-BuJIU0wX.js +26 -0
- package/dist/client/assets/erlang-BbsDmeCk.js +4 -0
- package/dist/client/assets/everforest-dark-NN95DCJl.js +2 -0
- package/dist/client/assets/everforest-light-idPY23JU.js +2 -0
- package/dist/client/assets/fennel-CSR5Mk7N.js +3 -0
- package/dist/client/assets/fetch-CTfoU6yt.js +873 -0
- package/dist/client/assets/fish-BlTQgKCk.js +3 -0
- package/dist/client/assets/fluent-TT7fQWak.js +3 -0
- package/dist/client/assets/fortran-fixed-form-DvnLkzBN.js +4 -0
- package/dist/client/assets/fortran-free-form-B1QQVoTU.js +3 -0
- package/dist/client/assets/fortran-free-form-xkm1udFL.js +2 -0
- package/dist/client/assets/fsharp-DyWqhI4o.js +4 -0
- package/dist/client/assets/gdresource-Ddtxl8Ni.js +9 -0
- package/dist/client/assets/gdscript-DLFBRMyo.js +2 -0
- package/dist/client/assets/gdscript-DLJhaHhX.js +3 -0
- package/dist/client/assets/gdshader-BFRlv_nM.js +3 -0
- package/dist/client/assets/gdshader-tCO8fx4f.js +2 -0
- package/dist/client/assets/genie-BmogPuVq.js +3 -0
- package/dist/client/assets/gherkin-uh-Mxnsi.js +3 -0
- package/dist/client/assets/git-commit-4JodcKYl.js +4 -0
- package/dist/client/assets/git-rebase-DZ3MZg-o.js +4 -0
- package/dist/client/assets/github-dark-C6J_EBvu.js +2 -0
- package/dist/client/assets/github-dark-default-DQDadoHp.js +2 -0
- package/dist/client/assets/github-dark-dimmed-DU7K1EZq.js +2 -0
- package/dist/client/assets/github-dark-high-contrast-BfsjVJDY.js +2 -0
- package/dist/client/assets/github-light-CM4f7fBZ.js +2 -0
- package/dist/client/assets/github-light-default-B_A-12O3.js +2 -0
- package/dist/client/assets/github-light-high-contrast-BhG28-t6.js +2 -0
- package/dist/client/assets/gleam-BByYw7_b.js +3 -0
- package/dist/client/assets/glimmer-js-Dw1YG46K.js +13 -0
- package/dist/client/assets/glimmer-ts-BoTKtLAn.js +13 -0
- package/dist/client/assets/glsl-BcvqNIzr.js +4 -0
- package/dist/client/assets/glsl-D7d1_ns-.js +3 -0
- package/dist/client/assets/gnuplot-CgWtMBol.js +3 -0
- package/dist/client/assets/go-B0RP9LHI.js +3 -0
- package/dist/client/assets/go-C2ti7VbT.js +2 -0
- package/dist/client/assets/graphql-CZtSUIVW.js +13 -0
- package/dist/client/assets/graphql-CeZ4pvez.js +6 -0
- package/dist/client/assets/groovy-Bpl59neu.js +3 -0
- package/dist/client/assets/gruvbox-dark-hard-BddnLFai.js +2 -0
- package/dist/client/assets/gruvbox-dark-medium-DClLifyq.js +2 -0
- package/dist/client/assets/gruvbox-dark-soft-CoL2WoEr.js +2 -0
- package/dist/client/assets/gruvbox-light-hard-CF2FUQYG.js +2 -0
- package/dist/client/assets/gruvbox-light-medium-DdKpn-Z3.js +2 -0
- package/dist/client/assets/gruvbox-light-soft-CXnF8CjV.js +2 -0
- package/dist/client/assets/hack-BYb9BCJH.js +11 -0
- package/dist/client/assets/haml-BImF9_sT.js +9 -0
- package/dist/client/assets/haml-DW6kjLLA.js +4 -0
- package/dist/client/assets/handlebars-BioaJ5nM.js +13 -0
- package/dist/client/assets/haskell-BmWZ6TRE.js +3 -0
- package/dist/client/assets/haxe-D-HM2q7w.js +3 -0
- package/dist/client/assets/haxe-DIufun--.js +2 -0
- package/dist/client/assets/hcl-S6uG4iQ0.js +3 -0
- package/dist/client/assets/hjson-mO0ORdeS.js +3 -0
- package/dist/client/assets/hlsl-C0jZ0PCe.js +2 -0
- package/dist/client/assets/hlsl-hj232ngO.js +3 -0
- package/dist/client/assets/houston-CdK1CUz1.js +2 -0
- package/dist/client/assets/html-BLAmfzfF.js +9 -0
- package/dist/client/assets/html-BpqLChx7.js +4 -0
- package/dist/client/assets/html-derivative-D5DGRC4b.js +5 -0
- package/dist/client/assets/html-derivative-EjRHFpnu.js +4 -0
- package/dist/client/assets/http-lZvWEzFG.js +18 -0
- package/dist/client/assets/hurl-Cq9E8TWb.js +16 -0
- package/dist/client/assets/hxml-ee_Yi0Bv.js +4 -0
- package/dist/client/assets/hy-DICTrdi3.js +3 -0
- package/dist/client/assets/imba-kv1YCcqW.js +3 -0
- package/dist/client/assets/index-BSkduMKH.js +7637 -0
- package/dist/client/assets/index-Co6hzA6u.css +443 -0
- package/dist/client/assets/ini-CeoNvVsQ.js +3 -0
- package/dist/client/assets/java-BUOns_Ip.js +2 -0
- package/dist/client/assets/java-DvTil0N3.js +3 -0
- package/dist/client/assets/javascript-239S-npV.js +3 -0
- package/dist/client/assets/javascript-qk0JMc6B.js +2 -0
- package/dist/client/assets/jinja-Bg3R28jD.js +8 -0
- package/dist/client/assets/jison-BC1q7dZB.js +4 -0
- package/dist/client/assets/json-B7uypvxJ.js +2 -0
- package/dist/client/assets/json-DugJQEGz.js +3 -0
- package/dist/client/assets/json5-7yQVqemE.js +3 -0
- package/dist/client/assets/jsonc-D8JMlU2y.js +3 -0
- package/dist/client/assets/jsonl-C08qrvBf.js +3 -0
- package/dist/client/assets/jsonnet-BvmZyW4T.js +3 -0
- package/dist/client/assets/jssm-DKBgqWqY.js +3 -0
- package/dist/client/assets/jsx-CT1RQ-OJ.js +3 -0
- package/dist/client/assets/jsx-CsU_AUfl.js +2 -0
- package/dist/client/assets/julia-EKUZwWmm.js +18 -0
- package/dist/client/assets/kanagawa-dragon-CT0GKJCY.js +2 -0
- package/dist/client/assets/kanagawa-lotus-BnTLrrY2.js +2 -0
- package/dist/client/assets/kanagawa-wave-DZKSoWHj.js +2 -0
- package/dist/client/assets/kdl-DVROzgs-.js +3 -0
- package/dist/client/assets/kotlin-DccTc7ae.js +3 -0
- package/dist/client/assets/kusto-DfjJ0A2b.js +3 -0
- package/dist/client/assets/laserwave-tIFKC5tj.js +2 -0
- package/dist/client/assets/latex-CflrJF-D.js +5 -0
- package/dist/client/assets/lean-CPP8F_7u.js +3 -0
- package/dist/client/assets/less-C1zBW-s6.js +3 -0
- package/dist/client/assets/less-CICUgOj-.js +2 -0
- package/dist/client/assets/light-plus-DhWyKCGQ.js +2 -0
- package/dist/client/assets/liquid-PHiGTwj1.js +13 -0
- package/dist/client/assets/llvm-I5QJoasC.js +3 -0
- package/dist/client/assets/log-gyTYf2xU.js +3 -0
- package/dist/client/assets/logo-DfMKoOqX.js +3 -0
- package/dist/client/assets/lua-CBf0ggeL.js +4 -0
- package/dist/client/assets/lua-crOEWYZ0.js +3 -0
- package/dist/client/assets/luau-B17X0UH2.js +3 -0
- package/dist/client/assets/make-B8j2I5oP.js +3 -0
- package/dist/client/assets/markdown-BIZO6UqW.js +2 -0
- package/dist/client/assets/markdown-DVA_ZXYg.js +3 -0
- package/dist/client/assets/marko-CE_g888v.js +13 -0
- package/dist/client/assets/material-theme-CoPt-P4I.js +2 -0
- package/dist/client/assets/material-theme-darker-FEG2rAOf.js +2 -0
- package/dist/client/assets/material-theme-lighter-BF7TTIIN.js +2 -0
- package/dist/client/assets/material-theme-ocean-DLZ8d_BI.js +2 -0
- package/dist/client/assets/material-theme-palenight-DDSTuCs0.js +2 -0
- package/dist/client/assets/matlab-k1xjK_b6.js +3 -0
- package/dist/client/assets/mdc-CTYOzD1j.js +14 -0
- package/dist/client/assets/mdx-BQUZJDaf.js +3 -0
- package/dist/client/assets/mermaid-DJ04LSyL.js +3 -0
- package/dist/client/assets/min-dark-B0gHld8V.js +2 -0
- package/dist/client/assets/min-light-DsiXGiCk.js +2 -0
- package/dist/client/assets/mipsasm-eWlP57CF.js +3 -0
- package/dist/client/assets/mojo-DPKjCktn.js +3 -0
- package/dist/client/assets/monokai-wE1Oe3ZE.js +2 -0
- package/dist/client/assets/move-jfk5_q-h.js +3 -0
- package/dist/client/assets/narrat-pUgLLkv0.js +3 -0
- package/dist/client/assets/nextflow-Cc6ZMjG9.js +3 -0
- package/dist/client/assets/nginx-Dj2-Xu09.js +5 -0
- package/dist/client/assets/night-owl-Bhwe1yQ8.js +2 -0
- package/dist/client/assets/nim-Btzc76t3.js +20 -0
- package/dist/client/assets/nix-D9NfD_az.js +3 -0
- package/dist/client/assets/nord-BSQfXDuM.js +2 -0
- package/dist/client/assets/nushell-BRDcl2mr.js +3 -0
- package/dist/client/assets/objective-c-DlHl8NyP.js +3 -0
- package/dist/client/assets/objective-cpp-B0dcjsTM.js +3 -0
- package/dist/client/assets/ocaml-F3DDYO_6.js +3 -0
- package/dist/client/assets/one-dark-pro-B5HIL-pf.js +2 -0
- package/dist/client/assets/one-light-hd3TKOg4.js +2 -0
- package/dist/client/assets/pages-BPB-93sD.js +18 -0
- package/dist/client/assets/pascal-k-jf8TbO.js +3 -0
- package/dist/client/assets/perl-DLie958B.js +16 -0
- package/dist/client/assets/php-CeVstFNC.js +17 -0
- package/dist/client/assets/php-Dqyegpf1.js +9 -0
- package/dist/client/assets/pkl-CTBspQUg.js +3 -0
- package/dist/client/assets/plastic-DTqiHuTe.js +2 -0
- package/dist/client/assets/plsql-CronX4zK.js +3 -0
- package/dist/client/assets/po-DIoaMCjY.js +3 -0
- package/dist/client/assets/poimandres-Ct2BSofG.js +2 -0
- package/dist/client/assets/polar-B5raTfsD.js +3 -0
- package/dist/client/assets/postcss-4oWH01ol.js +3 -0
- package/dist/client/assets/postcss-C4klqPVI.js +2 -0
- package/dist/client/assets/powerquery-Cq13nLq4.js +3 -0
- package/dist/client/assets/powershell-u1gI72JX.js +3 -0
- package/dist/client/assets/prisma-HKQ5cqp8.js +3 -0
- package/dist/client/assets/prolog-BesjPHql.js +3 -0
- package/dist/client/assets/proto-AagVn4-5.js +3 -0
- package/dist/client/assets/pug-D9BazAbt.js +11 -0
- package/dist/client/assets/puppet-DH-RAFaa.js +3 -0
- package/dist/client/assets/purescript-DfNGfmFP.js +3 -0
- package/dist/client/assets/python-BmLHvQtk.js +2 -0
- package/dist/client/assets/python-Dn88StJc.js +3 -0
- package/dist/client/assets/qml-Dsl5qRow.js +4 -0
- package/dist/client/assets/qmldir-DDMrTfWZ.js +3 -0
- package/dist/client/assets/qss-CHdy7svE.js +3 -0
- package/dist/client/assets/r-CbolghQs.js +2 -0
- package/dist/client/assets/r-DT24G0Sx.js +3 -0
- package/dist/client/assets/racket-B79KAvJY.js +3 -0
- package/dist/client/assets/raku-CTMhaGVX.js +3 -0
- package/dist/client/assets/razor-BjH6275R.js +11 -0
- package/dist/client/assets/red-CEj0QRPt.js +2 -0
- package/dist/client/assets/reg-Cypx77mL.js +3 -0
- package/dist/client/assets/regexp-ClZtLNbS.js +3 -0
- package/dist/client/assets/regexp-DJtnbMg9.js +2 -0
- package/dist/client/assets/rel-BpE3syVu.js +3 -0
- package/dist/client/assets/riscv-DyE_5IvB.js +3 -0
- package/dist/client/assets/rose-pine-6IUiFzUI.js +2 -0
- package/dist/client/assets/rose-pine-dawn-DoRlotcg.js +2 -0
- package/dist/client/assets/rose-pine-moon-B5Df1HyW.js +2 -0
- package/dist/client/assets/rosmsg-CIAJEgNV.js +3 -0
- package/dist/client/assets/rst-Pxh4TKKn.js +35 -0
- package/dist/client/assets/ruby-CAlvFaP5.js +29 -0
- package/dist/client/assets/ruby-Y14tynbZ.js +20 -0
- package/dist/client/assets/rust-DJhGYCa5.js +3 -0
- package/dist/client/assets/sas-BQQp9-K3.js +4 -0
- package/dist/client/assets/sass-DeLGkK3L.js +3 -0
- package/dist/client/assets/scala-cReyE3Yh.js +3 -0
- package/dist/client/assets/scheme-B1Lo-75f.js +3 -0
- package/dist/client/assets/scss-BP3WrVDm.js +3 -0
- package/dist/client/assets/scss-CJyb8K_U.js +4 -0
- package/dist/client/assets/sdbl-BKlGfwqV.js +3 -0
- package/dist/client/assets/sdbl-CLmP1IYn.js +2 -0
- package/dist/client/assets/server-router-BPUoghL2.js +8930 -0
- package/dist/client/assets/server-router-BiZSSnZD.css +91 -0
- package/dist/client/assets/shaderlab-C8C8_BgV.js +4 -0
- package/dist/client/assets/shellscript-Bd0FHBYA.js +2 -0
- package/dist/client/assets/shellscript-DsF2JDJS.js +3 -0
- package/dist/client/assets/shellsession-YAJaKmo5.js +4 -0
- package/dist/client/assets/slack-dark-BmjvCrQc.js +2 -0
- package/dist/client/assets/slack-ochin-PXT7PX3o.js +2 -0
- package/dist/client/assets/smalltalk-B3peVJF-.js +3 -0
- package/dist/client/assets/snazzy-light-DJv4SeqQ.js +2 -0
- package/dist/client/assets/solarized-dark-BvCiP_16.js +2 -0
- package/dist/client/assets/solarized-light-Bcu-a8JZ.js +2 -0
- package/dist/client/assets/solidity-2avG4OxK.js +3 -0
- package/dist/client/assets/soy-BwO6v7SS.js +6 -0
- package/dist/client/assets/sparql-Ctv9JmsW.js +4 -0
- package/dist/client/assets/splunk-UTnMmJ7Q.js +3 -0
- package/dist/client/assets/sql-DJRi7-HS.js +3 -0
- package/dist/client/assets/sql-DxeQhHVR.js +2 -0
- package/dist/client/assets/ssh-config-Du7ucyU5.js +3 -0
- package/dist/client/assets/stata-CBQSMhJu.js +4 -0
- package/dist/client/assets/stylus-BcbGHyGm.js +2 -0
- package/dist/client/assets/stylus-ESl0ir-D.js +3 -0
- package/dist/client/assets/svelte-C7A5FsG_.js +13 -0
- package/dist/client/assets/swift-BEUwwDAA.js +3 -0
- package/dist/client/assets/synthwave-84-BIVTX2kK.js +2 -0
- package/dist/client/assets/system-verilog-jIIGzizp.js +3 -0
- package/dist/client/assets/systemd-Do-I7Dk6.js +3 -0
- package/dist/client/assets/talonscript-B8BQ8lUi.js +3 -0
- package/dist/client/assets/tasl-Yr56vlbD.js +3 -0
- package/dist/client/assets/tcl-DHCz_jpi.js +3 -0
- package/dist/client/assets/templ-Dan_9-H5.js +11 -0
- package/dist/client/assets/terraform-CFJJDCa4.js +3 -0
- package/dist/client/assets/tex-CrNYpU8F.js +3 -0
- package/dist/client/assets/tex-DQvqQIPT.js +4 -0
- package/dist/client/assets/tokyo-night-C-8sx9_4.js +2 -0
- package/dist/client/assets/toml-CBSc9ib7.js +3 -0
- package/dist/client/assets/ts-tags-BSSXKo8m.js +49 -0
- package/dist/client/assets/tsv-B0JD-xkP.js +3 -0
- package/dist/client/assets/tsx-BV_Ie_mt.js +3 -0
- package/dist/client/assets/tsx-BzJMQxCY.js +2 -0
- package/dist/client/assets/turtle-kxVyEHLU.js +3 -0
- package/dist/client/assets/turtle-vZsG0FWM.js +2 -0
- package/dist/client/assets/twig-CUV6hi0h.js +34 -0
- package/dist/client/assets/typescript-Crma8FE2.js +3 -0
- package/dist/client/assets/typescript-nzfneafv.js +2 -0
- package/dist/client/assets/typespec-DCuJQu6m.js +3 -0
- package/dist/client/assets/typst-BDgLoDzV.js +3 -0
- package/dist/client/assets/v-DMA-YYXE.js +3 -0
- package/dist/client/assets/vala-BtBKHkJB.js +3 -0
- package/dist/client/assets/vb-CyVTXibQ.js +3 -0
- package/dist/client/assets/verilog-CC_Yo3jQ.js +3 -0
- package/dist/client/assets/vesper-BLuvFGfg.js +2 -0
- package/dist/client/assets/vhdl-C7ADyr0o.js +3 -0
- package/dist/client/assets/viml-hax2M4w6.js +3 -0
- package/dist/client/assets/vitesse-black-58mZKXM9.js +2 -0
- package/dist/client/assets/vitesse-dark-BE2jsHp9.js +2 -0
- package/dist/client/assets/vitesse-light-Bko17iRe.js +2 -0
- package/dist/client/assets/vue-BuGHx9kw.js +8 -0
- package/dist/client/assets/vue-CahofuY8.js +29 -0
- package/dist/client/assets/vue-html-B9xEgjjB.js +14 -0
- package/dist/client/assets/vue-vine-B9sh5nZz.js +23 -0
- package/dist/client/assets/vyper-BDpDemAA.js +3 -0
- package/dist/client/assets/wasm-BuJrhBgW.js +5 -0
- package/dist/client/assets/wasm-C9wAFEif.js +3 -0
- package/dist/client/assets/wenyan-DSsQqdmG.js +3 -0
- package/dist/client/assets/wgsl-CMOam7bY.js +3 -0
- package/dist/client/assets/wikitext-BqkWeRVY.js +3 -0
- package/dist/client/assets/wit-CHHZn0fR.js +3 -0
- package/dist/client/assets/wolfram-DhJOgCbz.js +3 -0
- package/dist/client/assets/xml-dAX-08G9.js +4 -0
- package/dist/client/assets/xml-yLaOmctb.js +3 -0
- package/dist/client/assets/xsl-mTp08Xh_.js +5 -0
- package/dist/client/assets/yaml-C5_iem5C.js +2 -0
- package/dist/client/assets/yaml-CN2n3pDD.js +3 -0
- package/dist/client/assets/zenscript-BmWf_m5U.js +3 -0
- package/dist/client/assets/zig-QOlp4jTZ.js +3 -0
- package/dist/client/cloud.svg +1 -0
- package/dist/client/index.html +27 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.js +11 -0
- package/dist/dirs-BjObhKjC.js +17 -0
- package/dist/dirs.d.ts +13 -0
- package/dist/dirs.js +3 -0
- package/dist/index.d.ts +20 -3
- package/dist/index.js +581 -29
- package/dist/panel/index.d.ts +10 -0
- package/dist/panel/index.js +3852 -0
- package/package.json +35 -6
package/dist/index.js
CHANGED
|
@@ -1,40 +1,592 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as DIR_CLIENT } from "./dirs-BjObhKjC.js";
|
|
2
|
+
import { basename, dirname, extname, join, relative } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import sirv from "sirv";
|
|
5
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
6
|
+
import { readdir } from "node:fs/promises";
|
|
2
7
|
|
|
3
|
-
//#region src/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
//#region src/server/controller/api.ts
|
|
9
|
+
const REQUEST_MODULE_EXTENSIONS = [
|
|
10
|
+
".ts",
|
|
11
|
+
".mts",
|
|
12
|
+
".cts",
|
|
13
|
+
".tsx",
|
|
14
|
+
".js",
|
|
15
|
+
".mjs",
|
|
16
|
+
".cjs",
|
|
17
|
+
".jsx"
|
|
18
|
+
];
|
|
19
|
+
function escapeRegExp(value) {
|
|
20
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
21
|
+
}
|
|
22
|
+
function normalizePath(filePath) {
|
|
23
|
+
return filePath.replace(/\\/g, "/");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 构造别名解析器集合。
|
|
27
|
+
*
|
|
28
|
+
* 支持以下映射:
|
|
29
|
+
* - '@/x'、'~/x' → <root>/src/x
|
|
30
|
+
* - tsconfig.json 中 compilerOptions.paths 定义的别名(含 * 通配符)
|
|
31
|
+
*
|
|
32
|
+
* 实现采用正则表驱动:传入 specifier 后逐条匹配并映射为绝对路径字符串。
|
|
33
|
+
*/
|
|
34
|
+
function createAliasResolver(root) {
|
|
35
|
+
const entries = [{
|
|
36
|
+
match: /^@\/(.+)$/,
|
|
37
|
+
map: (match) => join(root, "src", match[1])
|
|
38
|
+
}, {
|
|
39
|
+
match: /^~\/(.+)$/,
|
|
40
|
+
map: (match) => join(root, "src", match[1])
|
|
41
|
+
}];
|
|
42
|
+
const tsconfigCandidates = [join(root, "tsconfig.json"), join(root, "tsconfig.app.json")];
|
|
43
|
+
for (const configPath of tsconfigCandidates) {
|
|
44
|
+
if (!existsSync(configPath)) continue;
|
|
45
|
+
try {
|
|
46
|
+
const compilerOptions = JSON.parse(readFileSync(configPath, "utf-8"))?.compilerOptions ?? {};
|
|
47
|
+
const baseUrl = compilerOptions.baseUrl ? join(root, compilerOptions.baseUrl) : root;
|
|
48
|
+
const paths = compilerOptions.paths;
|
|
49
|
+
if (!paths || typeof paths !== "object") continue;
|
|
50
|
+
for (const [key, values] of Object.entries(paths)) {
|
|
51
|
+
const targets = Array.isArray(values) ? values : [values];
|
|
52
|
+
const hasWildcard = key.includes("*");
|
|
53
|
+
const pattern = /* @__PURE__ */ new RegExp(`^${escapeRegExp(key).replace(/\\\*/g, "(.+)")}$`);
|
|
54
|
+
targets.forEach((targetPath) => {
|
|
55
|
+
if (typeof targetPath !== "string") return;
|
|
56
|
+
const normalizedTarget = targetPath.replace(/\\/g, "/");
|
|
57
|
+
entries.push({
|
|
58
|
+
match: pattern,
|
|
59
|
+
map: (match) => {
|
|
60
|
+
if (hasWildcard) {
|
|
61
|
+
const wildcard = match[1] ?? "";
|
|
62
|
+
return join(baseUrl, normalizedTarget.replace(/\*/g, wildcard));
|
|
63
|
+
}
|
|
64
|
+
return join(baseUrl, normalizedTarget);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
} catch {}
|
|
70
|
+
}
|
|
71
|
+
return entries;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 在若干后缀(ts/tsx/js/...)与 index 文件中尝试解析具体文件。
|
|
75
|
+
*
|
|
76
|
+
* - candidate 可能未带扩展名,函数会尝试附加扩展与目录下 index.xxx。
|
|
77
|
+
* - 仅返回存在且确认为文件的路径;失败返回 undefined。
|
|
78
|
+
*/
|
|
79
|
+
function resolveWithExtensions(candidate) {
|
|
80
|
+
const candidates = [candidate];
|
|
81
|
+
if (!/\.[^/\\]+$/.test(candidate)) REQUEST_MODULE_EXTENSIONS.forEach((ext) => {
|
|
82
|
+
candidates.push(`${candidate}${ext}`);
|
|
83
|
+
candidates.push(join(candidate, `index${ext}`));
|
|
14
84
|
});
|
|
85
|
+
for (const file of candidates) if (existsSync(file)) try {
|
|
86
|
+
if (statSync(file).isFile()) return file;
|
|
87
|
+
} catch {}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 依据导入路径与导入者位置,解析出相对于项目根目录的模块文件路径。
|
|
91
|
+
*
|
|
92
|
+
* 支持:
|
|
93
|
+
* - 相对路径(./x、../x)
|
|
94
|
+
* - 绝对路径(/x → <root>/x)
|
|
95
|
+
* - 别名(来自 createAliasResolver 的 entries)
|
|
96
|
+
* - 退化支持 '@/x' 或 '~/x' 当 paths 未配置但文件位于 <root>/src 下
|
|
97
|
+
*/
|
|
98
|
+
function resolveRequestModulePath(specifier, importerPath, root, aliasEntries) {
|
|
99
|
+
const importerDir = dirname(importerPath);
|
|
100
|
+
let absoluteCandidate;
|
|
101
|
+
if (specifier.startsWith(".")) absoluteCandidate = join(importerDir, specifier);
|
|
102
|
+
else if (specifier.startsWith("/")) absoluteCandidate = join(root, specifier.replace(/^\//, ""));
|
|
103
|
+
else for (const entry of aliasEntries) {
|
|
104
|
+
const match = entry.match.exec(specifier);
|
|
105
|
+
if (match) {
|
|
106
|
+
absoluteCandidate = entry.map(match);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!absoluteCandidate && (specifier.startsWith("@/") || specifier.startsWith("~/"))) {
|
|
111
|
+
const markerIndex = normalizePath(importerPath).lastIndexOf("/src/");
|
|
112
|
+
if (markerIndex !== -1) absoluteCandidate = join(importerPath.slice(0, markerIndex), "src", specifier.slice(2));
|
|
113
|
+
}
|
|
114
|
+
if (!absoluteCandidate) return;
|
|
115
|
+
const resolved = resolveWithExtensions(absoluteCandidate);
|
|
116
|
+
if (!resolved) return;
|
|
117
|
+
return normalizePath(relative(root, resolved));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 查找项目根目录的 OpenAPI 配置文件。
|
|
121
|
+
*
|
|
122
|
+
* 约定优于配置:默认仅查找根目录下的 `openapi.config.ts`。
|
|
123
|
+
* 如需扩展为支持更多命名/位置,可在此集中改造,避免影响调用方。
|
|
124
|
+
*
|
|
125
|
+
* @param root 项目根目录的绝对路径(即 Vite server.config.root)
|
|
126
|
+
* @returns 如果存在则返回绝对路径,否则返回 null
|
|
127
|
+
*/
|
|
128
|
+
async function findOpenapiConfig(root) {
|
|
129
|
+
const configPath = join(root, "openapi.config.ts");
|
|
130
|
+
if (existsSync(configPath)) return configPath;
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 动态加载 OpenAPI 配置文件。
|
|
135
|
+
*
|
|
136
|
+
* 之所以使用动态 import 而非 require:
|
|
137
|
+
* - 支持 ESM 项目
|
|
138
|
+
* - 避免被打包时静态分析(保持运行时可替换)
|
|
139
|
+
*
|
|
140
|
+
* 注意:此函数在 devtools 插件的 Vite 环境中执行,允许使用 file:// URL。
|
|
141
|
+
*
|
|
142
|
+
* @param configPath 配置文件的绝对路径
|
|
143
|
+
* @returns 解析后的配置对象(优先使用 module.default),失败时返回 null
|
|
144
|
+
*/
|
|
145
|
+
async function loadOpenapiConfig(configPath) {
|
|
146
|
+
try {
|
|
147
|
+
const fileUrl = pathToFileURL(configPath).href;
|
|
148
|
+
const extension = extname(configPath);
|
|
149
|
+
if (extension === ".ts" || extension === ".mts" || extension === ".cts") {
|
|
150
|
+
const { loadConfig } = await import("unconfig");
|
|
151
|
+
const result = await loadConfig({
|
|
152
|
+
cwd: dirname(configPath),
|
|
153
|
+
sources: [{
|
|
154
|
+
files: basename(configPath, extension),
|
|
155
|
+
extensions: [extension.slice(1)]
|
|
156
|
+
}],
|
|
157
|
+
merge: false
|
|
158
|
+
});
|
|
159
|
+
if (typeof result?.config === "undefined") return null;
|
|
160
|
+
return await Promise.resolve(result.config);
|
|
161
|
+
} else {
|
|
162
|
+
const module = await import(fileUrl);
|
|
163
|
+
return module.default || module;
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error(`加载配置文件失败: ${error}`);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 从 TypeScript 源文件内容中提取导出的 API 函数的元信息。
|
|
172
|
+
*
|
|
173
|
+
* 约定:
|
|
174
|
+
* - 仅识别 `export function foo(...)` 的导出形式;若有 `const foo = () => {}` 请改为函数导出或扩展正则。
|
|
175
|
+
* - 通过 JSDoc 约定读取三类元数据:
|
|
176
|
+
* - @description 文本说明
|
|
177
|
+
* - @url 接口路径(例如 /user/list)
|
|
178
|
+
* - @method 请求方法(GET/POST/...)
|
|
179
|
+
* - 通过参数签名解析类型信息:
|
|
180
|
+
* - params: API.Xxx → 视为 query
|
|
181
|
+
* - body: API.Xxx → 视为 body
|
|
182
|
+
* - 泛型参数中的 `R = API.Xxx` → 视为返回类型
|
|
183
|
+
*
|
|
184
|
+
* 限制与注意:
|
|
185
|
+
* - 该实现基于正则进行快速解析,无法覆盖所有 TS 语法边界;遇到复杂写法可改为 AST(ts-morph / @typescript-eslint/typescript-estree)。
|
|
186
|
+
* - 若同一文件存在多种导出形式,请保持上述约定以获得稳定结果。
|
|
187
|
+
*
|
|
188
|
+
* @param content 源文件文本
|
|
189
|
+
* @param filePath 相对于项目根目录的文件相对路径(用于展示)
|
|
190
|
+
* @param requestClient 若源码中以 `import { foo as request }` 形式命名的请求实例名,用于偏好匹配应用端实例
|
|
191
|
+
* @returns 解析得到的 API 函数列表
|
|
192
|
+
*/
|
|
193
|
+
function extractApiFunctions(content, filePath, requestClient, requestModulePath, requestModuleResolvedPath) {
|
|
194
|
+
const functions = [];
|
|
195
|
+
const functionRegex = /\/\*\*\s*\n([^*]*(?:\*(?!\/)[^*]*)*)\*\/\s*export\s+function\s+(\w+)[^(]*\(([^)]*)\)/g;
|
|
196
|
+
let match = functionRegex.exec(content);
|
|
197
|
+
while (match !== null) {
|
|
198
|
+
const [, jsdoc, functionName, params] = match;
|
|
199
|
+
const descMatch = /@description\s+(.+)/.exec(jsdoc);
|
|
200
|
+
const description = descMatch ? descMatch[1].trim() : void 0;
|
|
201
|
+
const urlMatch = /@url\s+(.+)/.exec(jsdoc);
|
|
202
|
+
const url = urlMatch ? urlMatch[1].trim() : "";
|
|
203
|
+
const methodMatch = /@method\s+(.+)/.exec(jsdoc);
|
|
204
|
+
const method = methodMatch ? methodMatch[1].trim() : "UNKNOWN";
|
|
205
|
+
let paramType;
|
|
206
|
+
let paramLocation;
|
|
207
|
+
const paramsMatch = /params:\s*(API\.\w+)/.exec(params);
|
|
208
|
+
const bodyMatch = /body:\s*(API\.\w+)/.exec(params);
|
|
209
|
+
if (paramsMatch) {
|
|
210
|
+
paramType = paramsMatch[1];
|
|
211
|
+
paramLocation = "query";
|
|
212
|
+
} else if (bodyMatch) {
|
|
213
|
+
paramType = bodyMatch[1];
|
|
214
|
+
paramLocation = "body";
|
|
215
|
+
}
|
|
216
|
+
let returnType;
|
|
217
|
+
const returnTypeMatch = /R\s*=\s*(API\.\w+)/.exec(params);
|
|
218
|
+
if (returnTypeMatch) returnType = returnTypeMatch[1];
|
|
219
|
+
functions.push({
|
|
220
|
+
name: functionName,
|
|
221
|
+
description,
|
|
222
|
+
url,
|
|
223
|
+
method,
|
|
224
|
+
file: filePath,
|
|
225
|
+
paramType,
|
|
226
|
+
paramLocation,
|
|
227
|
+
returnType,
|
|
228
|
+
requestClient,
|
|
229
|
+
requestModulePath,
|
|
230
|
+
requestModuleResolvedPath
|
|
231
|
+
});
|
|
232
|
+
match = functionRegex.exec(content);
|
|
233
|
+
}
|
|
234
|
+
return functions;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 将 TypeScript 类型(字面量对象类型)解析为简化的 JSON Schema 片段。
|
|
238
|
+
*
|
|
239
|
+
* 目前仅对如下简单场景做支持:
|
|
240
|
+
* - `type Xxx = { foo: string; bar?: number }`
|
|
241
|
+
* - 行内 JSDoc `/** desc *\/` 写在属性前可作为 description。
|
|
242
|
+
* - 属性类型仅做基础映射(string/number/boolean/Record/any/数组)
|
|
243
|
+
*
|
|
244
|
+
* 不支持/暂不支持:
|
|
245
|
+
* - 嵌套类型、联合/交叉、索引类型、条件类型、接口继承等复杂语法。
|
|
246
|
+
* - interface 的 body 解析(可按需扩展正则)。
|
|
247
|
+
*
|
|
248
|
+
* 若需要更完整能力,建议切换到 TS AST 或 json-schema-generator 工具链。
|
|
249
|
+
*
|
|
250
|
+
* @param content typings.d.ts 文件全文
|
|
251
|
+
* @param typeName 形如 `API.UserQuery` 的带命名空间类型名
|
|
252
|
+
* @returns 简化的 JSON Schema 对象;无法解析时返回 null
|
|
253
|
+
*/
|
|
254
|
+
function parseTypeToSchema(content, typeName) {
|
|
255
|
+
try {
|
|
256
|
+
const match = new RegExp(`type\\s+${typeName.split(".").pop()}\\s*=\\s*\\{([^}]*)\\}`, "s").exec(content);
|
|
257
|
+
if (!match) return null;
|
|
258
|
+
const typeBody = match[1];
|
|
259
|
+
const properties = {};
|
|
260
|
+
const required = [];
|
|
261
|
+
const lines = typeBody.split("\n");
|
|
262
|
+
for (const line of lines) {
|
|
263
|
+
const trimmed = line.trim();
|
|
264
|
+
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("/*")) continue;
|
|
265
|
+
const propWithComment = /^\/\*\*\s*(.+?)\s*\*\/\s*(\w+)(\??):\s*(.+?);?$/.exec(trimmed);
|
|
266
|
+
const propWithoutComment = /^(\w+)(\??):\s*(.+?);?$/.exec(trimmed);
|
|
267
|
+
if (propWithComment) {
|
|
268
|
+
const [, description, propertyName, optional, propertyType] = propWithComment;
|
|
269
|
+
const isOptional = optional === "?";
|
|
270
|
+
const prop = { type: mapTsTypeToJsonType(propertyType) };
|
|
271
|
+
if (description) prop.description = description;
|
|
272
|
+
properties[propertyName] = prop;
|
|
273
|
+
if (!isOptional) required.push(propertyName);
|
|
274
|
+
} else if (propWithoutComment) {
|
|
275
|
+
const [, propertyName, optional, propertyType] = propWithoutComment;
|
|
276
|
+
const isOptional = optional === "?";
|
|
277
|
+
properties[propertyName] = { type: mapTsTypeToJsonType(propertyType) };
|
|
278
|
+
if (!isOptional) required.push(propertyName);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
type: "object",
|
|
283
|
+
properties,
|
|
284
|
+
required: required.length > 0 ? required : void 0
|
|
285
|
+
};
|
|
286
|
+
} catch (error) {
|
|
287
|
+
console.error(`解析类型 ${typeName} 失败:`, error);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* 将常见的 TypeScript 基础类型映射为 JSON Schema 的 `type`。
|
|
293
|
+
*
|
|
294
|
+
* @param tsType TypeScript 类型字面量(如 'string' | 'number[]' | 'Record<string, any>')
|
|
295
|
+
* @returns JSON Schema 的基础类型字符串
|
|
296
|
+
*/
|
|
297
|
+
function mapTsTypeToJsonType(tsType) {
|
|
298
|
+
const type = tsType.trim();
|
|
299
|
+
if (type === "string") return "string";
|
|
300
|
+
if (type === "number") return "number";
|
|
301
|
+
if (type === "boolean") return "boolean";
|
|
302
|
+
if (type === "any" || type.startsWith("Record<")) return "object";
|
|
303
|
+
if (type.endsWith("[]")) return "array";
|
|
304
|
+
return "string";
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* 从 `typings.d.ts` 中提取类型清单(仅定位名称,不展开定义)。
|
|
308
|
+
*
|
|
309
|
+
* 约定:
|
|
310
|
+
* - 在 `declare namespace Xxx { ... }` 范围内提取 `type` 与 `interface` 的标识符。
|
|
311
|
+
* - 仅收集行首的声明行,记录其名称与文件路径,便于 UI 展示与 schema 进一步解析。
|
|
312
|
+
*
|
|
313
|
+
* @param content typings.d.ts 文件全文
|
|
314
|
+
* @param filePath 相对项目根的文件路径
|
|
315
|
+
* @returns 类型条目列表
|
|
316
|
+
*/
|
|
317
|
+
function extractTypes(content, filePath) {
|
|
318
|
+
const types = [];
|
|
319
|
+
const lines = content.split("\n");
|
|
320
|
+
let currentNamespace = "";
|
|
321
|
+
let inNamespace = false;
|
|
322
|
+
let braceCount = 0;
|
|
323
|
+
for (const line of lines) {
|
|
324
|
+
const namespaceMatch = /declare\s+namespace\s+(\w+)/.exec(line);
|
|
325
|
+
if (namespaceMatch) {
|
|
326
|
+
currentNamespace = namespaceMatch[1];
|
|
327
|
+
inNamespace = true;
|
|
328
|
+
braceCount = 0;
|
|
329
|
+
}
|
|
330
|
+
if (inNamespace) {
|
|
331
|
+
braceCount += (line.match(/\{/g) || []).length;
|
|
332
|
+
braceCount -= (line.match(/\}/g) || []).length;
|
|
333
|
+
if (braceCount === 0 && line.includes("}")) inNamespace = false;
|
|
334
|
+
}
|
|
335
|
+
if (inNamespace && currentNamespace) {
|
|
336
|
+
const typeMatch = /^\s*(type|interface)\s+(\w+)/.exec(line);
|
|
337
|
+
if (typeMatch) {
|
|
338
|
+
const typeName = typeMatch[2];
|
|
339
|
+
types.push({
|
|
340
|
+
name: `${currentNamespace}.${typeName}`,
|
|
341
|
+
file: filePath,
|
|
342
|
+
content: line.trim()
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return types;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* 递归扫描给定目录以收集 API 函数与类型定义。
|
|
351
|
+
*
|
|
352
|
+
* 扫描规则:
|
|
353
|
+
* - 识别 `typings.d.ts` → 提取类型并尝试为同目录的 API 函数生成参数/返回 schema。
|
|
354
|
+
* - 识别 `*.ts`(排除 index.ts)→ 通过 JSDoc 与参数签名提取 API 函数信息。
|
|
355
|
+
* - 递归子目录以形成模块(module.path 为相对目录)。
|
|
356
|
+
*
|
|
357
|
+
* @param dir 要扫描的目录绝对路径(通常来自配置的 output)
|
|
358
|
+
* @param root 项目根目录绝对路径,用于计算相对路径与分组
|
|
359
|
+
* @returns 模块列表,每个模块包含 functions 与 types
|
|
360
|
+
*/
|
|
361
|
+
async function scanApiDirectory(dir, root, aliasEntries) {
|
|
362
|
+
const modules = [];
|
|
363
|
+
if (!existsSync(dir)) return modules;
|
|
364
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
365
|
+
let typingsContent = null;
|
|
366
|
+
for (const entry of entries) if (entry.isFile() && entry.name === "typings.d.ts") {
|
|
367
|
+
typingsContent = readFileSync(join(dir, entry.name), "utf-8");
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
for (const entry of entries) {
|
|
371
|
+
const fullPath = join(dir, entry.name);
|
|
372
|
+
if (entry.isDirectory()) {
|
|
373
|
+
const subModules = await scanApiDirectory(fullPath, root, aliasEntries);
|
|
374
|
+
modules.push(...subModules);
|
|
375
|
+
} else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
376
|
+
const content = readFileSync(fullPath, "utf-8");
|
|
377
|
+
const relativePath = relative(root, fullPath);
|
|
378
|
+
const requestImportMatch = /import\s*\{\s*([\w$]+)\s+as\s+request\s*\}\s*from\s*['"]([^'"]+)['"]/.exec(content);
|
|
379
|
+
const requestClient = requestImportMatch ? requestImportMatch[1] : void 0;
|
|
380
|
+
const requestModulePath = requestImportMatch ? requestImportMatch[2] : void 0;
|
|
381
|
+
const requestModuleResolvedPath = requestModulePath ? resolveRequestModulePath(requestModulePath, fullPath, root, aliasEntries) : void 0;
|
|
382
|
+
if (entry.name === "typings.d.ts") {
|
|
383
|
+
const types = extractTypes(content, relativePath);
|
|
384
|
+
if (types.length > 0) {
|
|
385
|
+
const moduleDir = relative(root, dir);
|
|
386
|
+
let module = modules.find((m) => m.path === moduleDir);
|
|
387
|
+
if (!module) {
|
|
388
|
+
module = {
|
|
389
|
+
path: moduleDir,
|
|
390
|
+
functions: [],
|
|
391
|
+
types: []
|
|
392
|
+
};
|
|
393
|
+
modules.push(module);
|
|
394
|
+
}
|
|
395
|
+
module.types.push(...types);
|
|
396
|
+
}
|
|
397
|
+
} else if (entry.name !== "index.ts") {
|
|
398
|
+
const functions = extractApiFunctions(content, relativePath, requestClient, requestModulePath, requestModuleResolvedPath);
|
|
399
|
+
if (functions.length > 0) {
|
|
400
|
+
const moduleDir = relative(root, dir);
|
|
401
|
+
let module = modules.find((m) => m.path === moduleDir);
|
|
402
|
+
if (!module) {
|
|
403
|
+
module = {
|
|
404
|
+
path: moduleDir,
|
|
405
|
+
functions: [],
|
|
406
|
+
types: []
|
|
407
|
+
};
|
|
408
|
+
modules.push(module);
|
|
409
|
+
}
|
|
410
|
+
if (typingsContent) for (const func of functions) {
|
|
411
|
+
if (func.paramType) {
|
|
412
|
+
const schema = parseTypeToSchema(typingsContent, func.paramType);
|
|
413
|
+
if (schema) func.paramSchema = schema;
|
|
414
|
+
}
|
|
415
|
+
if (func.returnType) {
|
|
416
|
+
const schema = parseTypeToSchema(typingsContent, func.returnType);
|
|
417
|
+
if (schema) func.returnSchema = schema;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
module.functions.push(...functions);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return modules;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* 根据 OpenAPI 配置计算需要扫描的 API 目录集合。
|
|
429
|
+
*
|
|
430
|
+
* 兼容策略:
|
|
431
|
+
* - 当存在 `batch` 时收集每项的 `output`。
|
|
432
|
+
* - 否则尝试使用顶层 `output`。
|
|
433
|
+
* - 以上都不存在时,回退到默认 `src/api` 目录。
|
|
434
|
+
*
|
|
435
|
+
* 注意:配置中的相对路径会被解析到项目根目录下。
|
|
436
|
+
*
|
|
437
|
+
* @param config 解析后的 OpenAPI 配置对象(可能为 null)
|
|
438
|
+
* @param root 项目根目录绝对路径
|
|
439
|
+
* @returns 需要扫描的目录绝对路径数组(去重后)
|
|
440
|
+
*/
|
|
441
|
+
function extractApiDirectories(config, root) {
|
|
442
|
+
const directories = /* @__PURE__ */ new Set();
|
|
443
|
+
if (!config) {
|
|
444
|
+
directories.add(join(root, "src", "api"));
|
|
445
|
+
return Array.from(directories);
|
|
446
|
+
}
|
|
447
|
+
if (config.batch && Array.isArray(config.batch)) {
|
|
448
|
+
for (const item of config.batch) if (item.output) {
|
|
449
|
+
const fullPath = join(root, item.output.replace(/^\.\//, ""));
|
|
450
|
+
directories.add(fullPath);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (config.output) {
|
|
454
|
+
const fullPath = join(root, config.output.replace(/^\.\//, ""));
|
|
455
|
+
directories.add(fullPath);
|
|
456
|
+
}
|
|
457
|
+
if (directories.size === 0) directories.add(join(root, "src", "api"));
|
|
458
|
+
return Array.from(directories);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* 扫描项目并返回 API 概览与配置快照。
|
|
462
|
+
*
|
|
463
|
+
* 执行流程:
|
|
464
|
+
* 1) 在项目根查找并加载 `openapi.config.ts`(若存在)。
|
|
465
|
+
* 2) 基于配置解析出需要扫描的目录(支持 batch/output)。
|
|
466
|
+
* 3) 对每个目录进行递归扫描,收集 API 函数与类型信息。
|
|
467
|
+
*
|
|
468
|
+
* @param root 项目根目录绝对路径
|
|
469
|
+
* @returns {ApiScanResult} 包含配置(可能为 null)与所有模块的扫描结果
|
|
470
|
+
*/
|
|
471
|
+
async function getRequestList(root) {
|
|
472
|
+
const configPath = await findOpenapiConfig(root);
|
|
473
|
+
let config = null;
|
|
474
|
+
if (configPath) config = await loadOpenapiConfig(configPath);
|
|
475
|
+
const apiDirectories = extractApiDirectories(config, root);
|
|
476
|
+
const aliasEntries = createAliasResolver(root);
|
|
477
|
+
const allModules = [];
|
|
478
|
+
for (const apiDir of apiDirectories) {
|
|
479
|
+
const modules = await scanApiDirectory(apiDir, root, aliasEntries);
|
|
480
|
+
allModules.push(...modules);
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
config,
|
|
484
|
+
modules: allModules
|
|
485
|
+
};
|
|
15
486
|
}
|
|
16
487
|
|
|
17
488
|
//#endregion
|
|
18
|
-
//#region src/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
489
|
+
//#region src/server/utils/count-files.ts
|
|
490
|
+
/**
|
|
491
|
+
* 在统计项目文件数量时需要忽略的目录。
|
|
492
|
+
* 这些目录通常体积较大或为构建产物,对健康检查意义不大。
|
|
493
|
+
*/
|
|
494
|
+
const IGNORED_DIRECTORIES = new Set([
|
|
495
|
+
".git",
|
|
496
|
+
"dist",
|
|
497
|
+
"node_modules"
|
|
498
|
+
]);
|
|
499
|
+
/**
|
|
500
|
+
* 递归统计目录下的文件数量。
|
|
501
|
+
*
|
|
502
|
+
* - 忽略符号链接,避免循环引用与跨盘符问题。
|
|
503
|
+
* - 忽略 IGNORED_DIRECTORIES 列表中的目录。
|
|
504
|
+
* - 遇到权限错误/不可读目录时返回 0(宽松模式,不抛错)。
|
|
505
|
+
*
|
|
506
|
+
* 用途:
|
|
507
|
+
* - Devtools 首页/健康检查的一个轻量指标。
|
|
508
|
+
*
|
|
509
|
+
* @param root 目录绝对路径
|
|
510
|
+
* @returns 统计到的文件总数
|
|
511
|
+
*/
|
|
512
|
+
async function countFiles(root) {
|
|
513
|
+
let total = 0;
|
|
514
|
+
let entries;
|
|
515
|
+
try {
|
|
516
|
+
entries = await readdir(root, {
|
|
517
|
+
withFileTypes: true,
|
|
518
|
+
encoding: "utf8"
|
|
519
|
+
});
|
|
520
|
+
} catch {
|
|
521
|
+
return 0;
|
|
522
|
+
}
|
|
523
|
+
for (const entry of entries) {
|
|
524
|
+
const name = String(entry.name);
|
|
525
|
+
if (entry.isSymbolicLink()) continue;
|
|
526
|
+
if (entry.isDirectory()) {
|
|
527
|
+
if (IGNORED_DIRECTORIES.has(name)) continue;
|
|
528
|
+
total += await countFiles(join(root, name));
|
|
529
|
+
} else if (entry.isFile()) total += 1;
|
|
530
|
+
}
|
|
531
|
+
return total;
|
|
30
532
|
}
|
|
31
533
|
|
|
32
534
|
//#endregion
|
|
33
|
-
//#region src/index.ts
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
535
|
+
//#region src/server/index.ts
|
|
536
|
+
/**
|
|
537
|
+
* Pubinfo Devtools 的 Vite 插件入口。
|
|
538
|
+
*
|
|
539
|
+
* 能力概览:
|
|
540
|
+
* - 提供一个轻量 UI(iframe)静态资源服务:`/__pubinfo_devtools`。
|
|
541
|
+
* - 提供 devtools 专用的 API:`/__pubinfo_devtools_api`。
|
|
542
|
+
* - `/` → 返回项目文件数量(用于示例与健康检查)。
|
|
543
|
+
* - `/api-list` → 返回解析的 OpenAPI 配置与扫描到的 API 函数/类型清单。
|
|
544
|
+
*
|
|
545
|
+
* 注意:本插件默认以 `enforce: 'pre'` 注入,避免被其他中间件拦截。
|
|
546
|
+
* 路由均在开发服务器中间件阶段生效,不影响生产构建输出。
|
|
547
|
+
*
|
|
548
|
+
* 安全说明:这些接口仅用于本地开发环境调试,不应暴露到公网。
|
|
549
|
+
*/
|
|
550
|
+
function pubinfoDevtools() {
|
|
551
|
+
return {
|
|
552
|
+
name: "vite-plugin-client",
|
|
553
|
+
enforce: "pre",
|
|
554
|
+
configureServer(server) {
|
|
555
|
+
const baseURL = "__pubinfo_devtools";
|
|
556
|
+
server.middlewares.use(`/${baseURL}`, sirv(DIR_CLIENT, {
|
|
557
|
+
single: true,
|
|
558
|
+
dev: true
|
|
559
|
+
}));
|
|
560
|
+
server.middlewares.use(`/${baseURL}_api`, async (req, res, next) => {
|
|
561
|
+
if (!req.url) return next();
|
|
562
|
+
if (req.url === "/") {
|
|
563
|
+
const info = { count: await countFiles(server.config.root) };
|
|
564
|
+
res.setHeader("Content-Type", "application/json");
|
|
565
|
+
res.write(JSON.stringify(info));
|
|
566
|
+
res.end();
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
if (req.url.startsWith("/api-list")) {
|
|
570
|
+
try {
|
|
571
|
+
const apiList = await getRequestList(server.config.root);
|
|
572
|
+
res.setHeader("Content-Type", "application/json");
|
|
573
|
+
res.write(JSON.stringify(apiList, null, 2));
|
|
574
|
+
} catch (error) {
|
|
575
|
+
res.statusCode = 500;
|
|
576
|
+
res.setHeader("Content-Type", "application/json");
|
|
577
|
+
res.write(JSON.stringify({
|
|
578
|
+
error: "Failed to get API list",
|
|
579
|
+
message: error instanceof Error ? error.message : String(error)
|
|
580
|
+
}));
|
|
581
|
+
}
|
|
582
|
+
res.end();
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
next();
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
};
|
|
37
589
|
}
|
|
38
590
|
|
|
39
591
|
//#endregion
|
|
40
|
-
export {
|
|
592
|
+
export { pubinfoDevtools };
|