@danneillouven/remote-workspace 0.0.0-stage → 0.1.0
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/.env.example +32 -0
- package/README.md +196 -2
- package/bin/remote-workspace.mjs +29 -0
- package/dist/assets/add-project-screen-IOzaLXTc.js +1 -0
- package/dist/assets/apl-gfMMiTNf.js +1 -0
- package/dist/assets/arrow-left-B5CLiIbq.js +1 -0
- package/dist/assets/asciiarmor-C_eisQCp.js +1 -0
- package/dist/assets/asn1-DCl_8MCW.js +1 -0
- package/dist/assets/asterisk-BEn0Cwpx.js +1 -0
- package/dist/assets/brainfuck-D5EjA2JK.js +1 -0
- package/dist/assets/client-BaUFYZ28.js +63 -0
- package/dist/assets/clike-xvONpD0Z.js +1 -0
- package/dist/assets/clojure-BflJGmDX.js +1 -0
- package/dist/assets/cmake-84nbDH0I.js +1 -0
- package/dist/assets/cobol-DHLQUbN7.js +1 -0
- package/dist/assets/codemirror-DRp8cs-R.js +14 -0
- package/dist/assets/coffeescript-De_zI4J0.js +1 -0
- package/dist/assets/commonlisp-DgAKBe0r.js +1 -0
- package/dist/assets/copy-button-DlOU9KRy.js +1 -0
- package/dist/assets/corner-down-left-B7l-mMrb.js +1 -0
- package/dist/assets/crystal-Bsdphhtm.js +1 -0
- package/dist/assets/css-CnaYoQib.js +1 -0
- package/dist/assets/cypher-p9eYesGn.js +1 -0
- package/dist/assets/d-DWkQyNnU.js +1 -0
- package/dist/assets/diff-ChtP43wD.js +1 -0
- package/dist/assets/dist-3tAAASIu.js +1 -0
- package/dist/assets/dist-AXYnLL_F.js +9 -0
- package/dist/assets/dist-BGyMVrYk.js +11 -0
- package/dist/assets/dist-BN1wE2xy.js +1 -0
- package/dist/assets/dist-CDAjPDtI.js +1 -0
- package/dist/assets/dist-CJBq646Z.js +1 -0
- package/dist/assets/dist-CL_zGtiO.js +1 -0
- package/dist/assets/dist-CM8yt5f_.js +1 -0
- package/dist/assets/dist-CYNLiE2B.js +1 -0
- package/dist/assets/dist-CyOGylYO.js +1 -0
- package/dist/assets/dist-D-bo6lHS.js +1 -0
- package/dist/assets/dist-D7xXmJTH.js +1 -0
- package/dist/assets/dist-DGmHtnYo.js +6 -0
- package/dist/assets/dist-DOcORAD_.js +1 -0
- package/dist/assets/dist-DdeR5kYT.js +2 -0
- package/dist/assets/dist-DyYo49jM.js +1 -0
- package/dist/assets/dist-FOmLcFeD.js +1 -0
- package/dist/assets/dist-FUrprsRT.js +1 -0
- package/dist/assets/dist-JuM3aKGD.js +1 -0
- package/dist/assets/dist-S0tn--lj.js +1 -0
- package/dist/assets/dist-aVl135DR.js +23 -0
- package/dist/assets/dist-y7gdVNBt.js +1 -0
- package/dist/assets/dockerfile-DJkHQgkl.js +1 -0
- package/dist/assets/dtd-DTF72YNO.js +1 -0
- package/dist/assets/dylan-S7ucR4pR.js +1 -0
- package/dist/assets/ebnf-D4c0_ac3.js +1 -0
- package/dist/assets/ecl-BVIeWmwY.js +1 -0
- package/dist/assets/eiffel-BEjRio4Q.js +1 -0
- package/dist/assets/elm-Cshzl8qu.js +1 -0
- package/dist/assets/empty-state-CkET1cGs.js +1 -0
- package/dist/assets/erlang-BV0c4Hdn.js +1 -0
- package/dist/assets/eye-2RNiMHO-.js +1 -0
- package/dist/assets/factor-LKH5gN8L.js +1 -0
- package/dist/assets/fcl-ClOhbFR7.js +1 -0
- package/dist/assets/field-CYhxBv9B.js +1 -0
- package/dist/assets/forth-D6RzAl64.js +1 -0
- package/dist/assets/fortran-Bt6PBEDR.js +1 -0
- package/dist/assets/gas-BHEdbvp9.js +1 -0
- package/dist/assets/gherkin-oBAE_ms0.js +1 -0
- package/dist/assets/groovy-CUpZ7dEl.js +1 -0
- package/dist/assets/haskell-BRsoo5mP.js +1 -0
- package/dist/assets/haxe-DjVOVvNP.js +1 -0
- package/dist/assets/host-wizard-screen-Bs7pSgJk.js +1 -0
- package/dist/assets/http-CLVgA2GD.js +1 -0
- package/dist/assets/idl-BUZw3wgd.js +1 -0
- package/dist/assets/index-B5KQ4hDp.css +2 -0
- package/dist/assets/index-Cz0KzQeb.js +11 -0
- package/dist/assets/javascript-Bu8mWwtz.js +1 -0
- package/dist/assets/julia-CQfgDRfP.js +1 -0
- package/dist/assets/key-round-Cl7KguqM.js +1 -0
- package/dist/assets/layout.store-b9Rb2T9G.js +1 -0
- package/dist/assets/livescript-BXxG0Yva.js +1 -0
- package/dist/assets/login-screen-Co0lYHk4.js +1 -0
- package/dist/assets/lua-DPCEkfD_.js +1 -0
- package/dist/assets/manifest-CxKlFp1I.js +1 -0
- package/dist/assets/markdown-view-BQbaAkAk.js +29 -0
- package/dist/assets/markdown-view-aK-tdIwk.css +1 -0
- package/dist/assets/material-icon-RrSZDDw2.js +1 -0
- package/dist/assets/mathematica-u8YMmbU0.js +1 -0
- package/dist/assets/mbox-BEMVcqjs.js +1 -0
- package/dist/assets/middleware-C1xnEbcF.js +1 -0
- package/dist/assets/mirc-C9zpzAZU.js +1 -0
- package/dist/assets/mllike-B45xgp2S.js +1 -0
- package/dist/assets/modelica-CqHI_q-D.js +1 -0
- package/dist/assets/mscgen-qgSLujhx.js +1 -0
- package/dist/assets/mumps-BSzj6Xyz.js +1 -0
- package/dist/assets/nginx-8H7HVH4w.js +1 -0
- package/dist/assets/nsis-viPvXFiq.js +1 -0
- package/dist/assets/ntriples-CzMBulkp.js +1 -0
- package/dist/assets/octave-D2Q8cUp1.js +1 -0
- package/dist/assets/oz-BwTct_5T.js +1 -0
- package/dist/assets/page-shell-BSEpDNSs.js +1 -0
- package/dist/assets/pascal-Dp_KdFgX.js +1 -0
- package/dist/assets/password-input-CSjwFwJE.js +1 -0
- package/dist/assets/perl-BkSkiI9m.js +1 -0
- package/dist/assets/pig-AF4Hwhju.js +1 -0
- package/dist/assets/port-links-8g2kBRfp.js +1 -0
- package/dist/assets/powershell-D8WpQPaX.js +1 -0
- package/dist/assets/projects-screen-C3yWG8mw.js +1 -0
- package/dist/assets/properties-C357ku5U.js +1 -0
- package/dist/assets/protobuf-D1ij_kNL.js +1 -0
- package/dist/assets/pug-Dwd_FmgJ.js +1 -0
- package/dist/assets/puppet-BZyAS7I4.js +1 -0
- package/dist/assets/python-B_1Jd8HM.js +1 -0
- package/dist/assets/q-B9NhS7L_.js +1 -0
- package/dist/assets/query-D1fTvh27.js +1 -0
- package/dist/assets/r-CxDmU1I4.js +1 -0
- package/dist/assets/rpm-gpDK5sbt.js +1 -0
- package/dist/assets/ruby-ChfNwlCY.js +1 -0
- package/dist/assets/sas-C2OyD2Y6.js +1 -0
- package/dist/assets/scheme-D9qYN0V5.js +1 -0
- package/dist/assets/settings-screen-BM1Y4v3n.js +1 -0
- package/dist/assets/setup-screen--Rk5RNBd.js +1 -0
- package/dist/assets/shell-DwuoZtxw.js +1 -0
- package/dist/assets/sieve-tLWDfEkZ.js +1 -0
- package/dist/assets/simple-mode-DXiLM1-G.js +1 -0
- package/dist/assets/smalltalk-BLp5-jwC.js +1 -0
- package/dist/assets/solr-B78wSQJQ.js +1 -0
- package/dist/assets/sparkles-rMOjCpPO.js +1 -0
- package/dist/assets/sparql-Dz-mlCAC.js +1 -0
- package/dist/assets/spinner-Dhw2p8cg.js +1 -0
- package/dist/assets/spreadsheet-CTIncYxj.js +1 -0
- package/dist/assets/sql-DuQMFDvy.js +1 -0
- package/dist/assets/square-terminal-DL7ubCPR.js +1 -0
- package/dist/assets/stex-DNzd62Q_.js +1 -0
- package/dist/assets/stylus-BOVgKnng.js +1 -0
- package/dist/assets/swift-DKB6_1j6.js +1 -0
- package/dist/assets/tcl-BGfruO1u.js +1 -0
- package/dist/assets/textile-C4jVoHG1.js +1 -0
- package/dist/assets/tiddlywiki-VlUiK86J.js +1 -0
- package/dist/assets/tiki-DTszW0OQ.js +1 -0
- package/dist/assets/toml-BPTmHmyx.js +1 -0
- package/dist/assets/triangle-alert-CKXjnNZK.js +1 -0
- package/dist/assets/troff-C2dAgh7P.js +1 -0
- package/dist/assets/ttcn-PPSTk1ow.js +1 -0
- package/dist/assets/ttcn-cfg-2b4Gb5sE.js +1 -0
- package/dist/assets/turtle-Cx3rYX2g.js +1 -0
- package/dist/assets/use-visual-viewport-CHPXxqd5.js +1 -0
- package/dist/assets/useQuery-CTJ-5_ol.js +1 -0
- package/dist/assets/vb-BthdM_4N.js +1 -0
- package/dist/assets/vbscript-D9f6rSsU.js +1 -0
- package/dist/assets/velocity-CqftRsjg.js +1 -0
- package/dist/assets/verilog-CjI9Y6RI.js +1 -0
- package/dist/assets/vhdl-kS471soi.js +1 -0
- package/dist/assets/webidl-D5jiJvOU.js +1 -0
- package/dist/assets/workspace-screen-FWzP6Hvt.js +8 -0
- package/dist/assets/xquery-BKJx4mf9.js +1 -0
- package/dist/assets/xterm-BrP-ENHg.css +1 -0
- package/dist/assets/xterm-OPnvFLvt.js +22 -0
- package/dist/assets/yacas-CXXgtw0p.js +1 -0
- package/dist/assets/z80-Co3PbHdE.js +1 -0
- package/dist/favicon.svg +1 -0
- package/dist/index.html +29 -0
- package/dist/ios-viewport.js +9 -0
- package/dist/material-icons/3d.svg +1 -0
- package/dist/material-icons/abap.svg +1 -0
- package/dist/material-icons/abc.svg +1 -0
- package/dist/material-icons/actionscript.svg +1 -0
- package/dist/material-icons/ada.svg +1 -0
- package/dist/material-icons/adobe-illustrator.svg +1 -0
- package/dist/material-icons/adobe-illustrator_light.svg +1 -0
- package/dist/material-icons/adobe-photoshop.svg +1 -0
- package/dist/material-icons/adobe-photoshop_light.svg +1 -0
- package/dist/material-icons/adobe-swc.svg +1 -0
- package/dist/material-icons/adonis.svg +1 -0
- package/dist/material-icons/advpl-include.clone.svg +1 -0
- package/dist/material-icons/advpl-ptm.clone.svg +1 -0
- package/dist/material-icons/advpl-tlpp.clone.svg +1 -0
- package/dist/material-icons/advpl.svg +1 -0
- package/dist/material-icons/agent.svg +1 -0
- package/dist/material-icons/ahk2.clone.svg +1 -0
- package/dist/material-icons/amplify.svg +1 -0
- package/dist/material-icons/android.svg +1 -0
- package/dist/material-icons/angular-component.clone.svg +1 -0
- package/dist/material-icons/angular-directive.clone.svg +1 -0
- package/dist/material-icons/angular-guard.clone.svg +1 -0
- package/dist/material-icons/angular-interceptor.clone.svg +1 -0
- package/dist/material-icons/angular-pipe.clone.svg +1 -0
- package/dist/material-icons/angular-resolver.clone.svg +1 -0
- package/dist/material-icons/angular-service.clone.svg +1 -0
- package/dist/material-icons/angular.svg +1 -0
- package/dist/material-icons/antlr.svg +1 -0
- package/dist/material-icons/apiblueprint.svg +1 -0
- package/dist/material-icons/apollo.svg +1 -0
- package/dist/material-icons/applescript.svg +1 -0
- package/dist/material-icons/apps-script.svg +1 -0
- package/dist/material-icons/appveyor.svg +1 -0
- package/dist/material-icons/appwrite.svg +1 -0
- package/dist/material-icons/architecture.svg +1 -0
- package/dist/material-icons/arduino.svg +1 -0
- package/dist/material-icons/asciidoc.svg +1 -0
- package/dist/material-icons/assembly.svg +1 -0
- package/dist/material-icons/astro-config.svg +1 -0
- package/dist/material-icons/astro.svg +1 -0
- package/dist/material-icons/astyle.svg +1 -0
- package/dist/material-icons/audio.svg +1 -0
- package/dist/material-icons/aurelia.svg +1 -0
- package/dist/material-icons/authors.svg +1 -0
- package/dist/material-icons/auto.svg +1 -0
- package/dist/material-icons/auto_light.svg +1 -0
- package/dist/material-icons/autohotkey.svg +1 -0
- package/dist/material-icons/autoit.svg +1 -0
- package/dist/material-icons/azure-pipelines.svg +1 -0
- package/dist/material-icons/azure.svg +1 -0
- package/dist/material-icons/babel.svg +1 -0
- package/dist/material-icons/ballerina.svg +1 -0
- package/dist/material-icons/bashly-hook.svg +1 -0
- package/dist/material-icons/bashly-settings.clone.svg +1 -0
- package/dist/material-icons/bashly-settings_light.clone.svg +1 -0
- package/dist/material-icons/bashly-strings.clone.svg +1 -0
- package/dist/material-icons/bashly-strings_light.clone.svg +1 -0
- package/dist/material-icons/bashly.svg +1 -0
- package/dist/material-icons/bazel.svg +1 -0
- package/dist/material-icons/bbx.svg +1 -0
- package/dist/material-icons/beancount.svg +1 -0
- package/dist/material-icons/bench-js.svg +1 -0
- package/dist/material-icons/bench-jsx.svg +1 -0
- package/dist/material-icons/bench-ts.svg +1 -0
- package/dist/material-icons/bibliography.svg +1 -0
- package/dist/material-icons/bibtex-style.svg +1 -0
- package/dist/material-icons/bicep.svg +1 -0
- package/dist/material-icons/biome.svg +1 -0
- package/dist/material-icons/bitbucket.svg +1 -0
- package/dist/material-icons/bithound.svg +1 -0
- package/dist/material-icons/blender.svg +1 -0
- package/dist/material-icons/blink.svg +1 -0
- package/dist/material-icons/blink_light.svg +1 -0
- package/dist/material-icons/blitz.svg +1 -0
- package/dist/material-icons/bower.svg +1 -0
- package/dist/material-icons/brainfuck.svg +1 -0
- package/dist/material-icons/browserlist.svg +1 -0
- package/dist/material-icons/browserlist_light.svg +1 -0
- package/dist/material-icons/bruno.svg +1 -0
- package/dist/material-icons/buck.svg +1 -0
- package/dist/material-icons/bucklescript.svg +1 -0
- package/dist/material-icons/buildkite.svg +1 -0
- package/dist/material-icons/bun.svg +1 -0
- package/dist/material-icons/bun_light.svg +1 -0
- package/dist/material-icons/c.svg +1 -0
- package/dist/material-icons/c3.svg +1 -0
- package/dist/material-icons/cabal.svg +1 -0
- package/dist/material-icons/caddy.svg +1 -0
- package/dist/material-icons/cadence.svg +1 -0
- package/dist/material-icons/cairo.svg +1 -0
- package/dist/material-icons/cake.svg +1 -0
- package/dist/material-icons/capacitor.svg +1 -0
- package/dist/material-icons/capnp.svg +1 -0
- package/dist/material-icons/cbx.svg +1 -0
- package/dist/material-icons/cds.svg +1 -0
- package/dist/material-icons/certificate.svg +1 -0
- package/dist/material-icons/changelog.svg +1 -0
- package/dist/material-icons/chess.svg +1 -0
- package/dist/material-icons/chess_light.svg +1 -0
- package/dist/material-icons/chromatic.svg +1 -0
- package/dist/material-icons/chrome.svg +1 -0
- package/dist/material-icons/circleci.svg +1 -0
- package/dist/material-icons/circleci_light.svg +1 -0
- package/dist/material-icons/citation.svg +1 -0
- package/dist/material-icons/clangd.svg +1 -0
- package/dist/material-icons/claude.svg +1 -0
- package/dist/material-icons/cline.svg +1 -0
- package/dist/material-icons/clojure.svg +1 -0
- package/dist/material-icons/cloudfoundry.svg +1 -0
- package/dist/material-icons/cmake.svg +1 -0
- package/dist/material-icons/coala.svg +1 -0
- package/dist/material-icons/cobol.svg +1 -0
- package/dist/material-icons/coconut.svg +1 -0
- package/dist/material-icons/code-climate.svg +1 -0
- package/dist/material-icons/code-climate_light.svg +1 -0
- package/dist/material-icons/codecov.svg +1 -0
- package/dist/material-icons/codeowners.svg +1 -0
- package/dist/material-icons/coderabbit-ai.svg +1 -0
- package/dist/material-icons/coffee.svg +1 -0
- package/dist/material-icons/coldfusion.svg +1 -0
- package/dist/material-icons/coloredpetrinets.svg +1 -0
- package/dist/material-icons/command.svg +1 -0
- package/dist/material-icons/commitizen.svg +1 -0
- package/dist/material-icons/commitlint.svg +1 -0
- package/dist/material-icons/concourse.svg +1 -0
- package/dist/material-icons/conduct.svg +1 -0
- package/dist/material-icons/console.svg +1 -0
- package/dist/material-icons/container.clone.svg +1 -0
- package/dist/material-icons/contentlayer.svg +1 -0
- package/dist/material-icons/context.svg +1 -0
- package/dist/material-icons/contributing.svg +1 -0
- package/dist/material-icons/controller.svg +1 -0
- package/dist/material-icons/copilot.svg +1 -0
- package/dist/material-icons/copilot_light.svg +1 -0
- package/dist/material-icons/cpp.svg +1 -0
- package/dist/material-icons/craco.svg +1 -0
- package/dist/material-icons/credits.svg +1 -0
- package/dist/material-icons/crystal.svg +1 -0
- package/dist/material-icons/crystal_light.svg +1 -0
- package/dist/material-icons/csharp.svg +1 -0
- package/dist/material-icons/css-map.svg +1 -0
- package/dist/material-icons/css.svg +1 -0
- package/dist/material-icons/cucumber.svg +1 -0
- package/dist/material-icons/cuda.svg +1 -0
- package/dist/material-icons/cue.svg +1 -0
- package/dist/material-icons/cursor.svg +1 -0
- package/dist/material-icons/cursor_light.svg +1 -0
- package/dist/material-icons/cypress.svg +1 -0
- package/dist/material-icons/d.svg +1 -0
- package/dist/material-icons/dart.svg +1 -0
- package/dist/material-icons/dart_generated.svg +1 -0
- package/dist/material-icons/database.svg +1 -0
- package/dist/material-icons/deepsource.svg +1 -0
- package/dist/material-icons/denizenscript.svg +1 -0
- package/dist/material-icons/deno.svg +1 -0
- package/dist/material-icons/deno_light.svg +1 -0
- package/dist/material-icons/dependabot.svg +1 -0
- package/dist/material-icons/dependencies-update.svg +1 -0
- package/dist/material-icons/dhall.svg +1 -0
- package/dist/material-icons/diff.svg +1 -0
- package/dist/material-icons/dinophp.svg +1 -0
- package/dist/material-icons/disc.svg +1 -0
- package/dist/material-icons/django.svg +1 -0
- package/dist/material-icons/dll.svg +1 -0
- package/dist/material-icons/docker.svg +1 -0
- package/dist/material-icons/doctex-installer.svg +1 -0
- package/dist/material-icons/doctex.clone.svg +1 -0
- package/dist/material-icons/document.svg +1 -0
- package/dist/material-icons/dotjs.svg +1 -0
- package/dist/material-icons/drawio.svg +1 -0
- package/dist/material-icons/drizzle.svg +1 -0
- package/dist/material-icons/drone.svg +1 -0
- package/dist/material-icons/drone_light.svg +1 -0
- package/dist/material-icons/dtx.clone.svg +1 -0
- package/dist/material-icons/duc.svg +1 -0
- package/dist/material-icons/dune.svg +1 -0
- package/dist/material-icons/edge.svg +1 -0
- package/dist/material-icons/editorconfig.svg +1 -0
- package/dist/material-icons/ejs.svg +1 -0
- package/dist/material-icons/elixir.svg +1 -0
- package/dist/material-icons/elm.svg +1 -0
- package/dist/material-icons/email.svg +1 -0
- package/dist/material-icons/ember.svg +1 -0
- package/dist/material-icons/epub.svg +1 -0
- package/dist/material-icons/erlang.svg +1 -0
- package/dist/material-icons/esbuild.svg +1 -0
- package/dist/material-icons/eslint.svg +1 -0
- package/dist/material-icons/excalidraw.svg +1 -0
- package/dist/material-icons/exe.svg +1 -0
- package/dist/material-icons/expo.svg +1 -0
- package/dist/material-icons/expo_light.svg +1 -0
- package/dist/material-icons/fastlane.svg +1 -0
- package/dist/material-icons/favicon.svg +1 -0
- package/dist/material-icons/figma.svg +1 -0
- package/dist/material-icons/file.svg +1 -0
- package/dist/material-icons/firebase.svg +1 -0
- package/dist/material-icons/flash.svg +1 -0
- package/dist/material-icons/flow.svg +1 -0
- package/dist/material-icons/folder-admin-open.svg +1 -0
- package/dist/material-icons/folder-admin.svg +1 -0
- package/dist/material-icons/folder-android-open.svg +1 -0
- package/dist/material-icons/folder-android.svg +1 -0
- package/dist/material-icons/folder-angular-open.svg +1 -0
- package/dist/material-icons/folder-angular.svg +1 -0
- package/dist/material-icons/folder-animation-open.svg +1 -0
- package/dist/material-icons/folder-animation.svg +1 -0
- package/dist/material-icons/folder-ansible-open.svg +1 -0
- package/dist/material-icons/folder-ansible.svg +1 -0
- package/dist/material-icons/folder-api-open.svg +1 -0
- package/dist/material-icons/folder-api.svg +1 -0
- package/dist/material-icons/folder-apollo-open.svg +1 -0
- package/dist/material-icons/folder-apollo.svg +1 -0
- package/dist/material-icons/folder-app-open.svg +1 -0
- package/dist/material-icons/folder-app.svg +1 -0
- package/dist/material-icons/folder-appwrite-open.svg +1 -0
- package/dist/material-icons/folder-appwrite.svg +1 -0
- package/dist/material-icons/folder-archive-open.svg +1 -0
- package/dist/material-icons/folder-archive.svg +1 -0
- package/dist/material-icons/folder-assembly-open.svg +1 -0
- package/dist/material-icons/folder-assembly.svg +1 -0
- package/dist/material-icons/folder-astro-open.svg +1 -0
- package/dist/material-icons/folder-astro.svg +1 -0
- package/dist/material-icons/folder-atom-open.svg +1 -0
- package/dist/material-icons/folder-atom.svg +1 -0
- package/dist/material-icons/folder-attachment-open.svg +1 -0
- package/dist/material-icons/folder-attachment.svg +1 -0
- package/dist/material-icons/folder-audio-open.svg +1 -0
- package/dist/material-icons/folder-audio.svg +1 -0
- package/dist/material-icons/folder-aurelia-open.svg +1 -0
- package/dist/material-icons/folder-aurelia.svg +1 -0
- package/dist/material-icons/folder-aws-open.svg +1 -0
- package/dist/material-icons/folder-aws.svg +1 -0
- package/dist/material-icons/folder-azure-pipelines-open.svg +1 -0
- package/dist/material-icons/folder-azure-pipelines.svg +1 -0
- package/dist/material-icons/folder-backup-open.svg +1 -0
- package/dist/material-icons/folder-backup.svg +1 -0
- package/dist/material-icons/folder-base-open.svg +1 -0
- package/dist/material-icons/folder-base.svg +1 -0
- package/dist/material-icons/folder-batch-open.svg +1 -0
- package/dist/material-icons/folder-batch.svg +1 -0
- package/dist/material-icons/folder-benchmark-open.svg +1 -0
- package/dist/material-icons/folder-benchmark.svg +1 -0
- package/dist/material-icons/folder-bibliography-open.svg +1 -0
- package/dist/material-icons/folder-bibliography.svg +1 -0
- package/dist/material-icons/folder-bicep-open.svg +1 -0
- package/dist/material-icons/folder-bicep.svg +1 -0
- package/dist/material-icons/folder-blender-open.svg +1 -0
- package/dist/material-icons/folder-blender.svg +1 -0
- package/dist/material-icons/folder-bloc-open.svg +1 -0
- package/dist/material-icons/folder-bloc.svg +1 -0
- package/dist/material-icons/folder-bower-open.svg +1 -0
- package/dist/material-icons/folder-bower.svg +1 -0
- package/dist/material-icons/folder-buildkite-open.svg +1 -0
- package/dist/material-icons/folder-buildkite.svg +1 -0
- package/dist/material-icons/folder-cart-open.svg +1 -0
- package/dist/material-icons/folder-cart.svg +1 -0
- package/dist/material-icons/folder-changesets-open.svg +1 -0
- package/dist/material-icons/folder-changesets.svg +1 -0
- package/dist/material-icons/folder-ci-open.svg +1 -0
- package/dist/material-icons/folder-ci.svg +1 -0
- package/dist/material-icons/folder-circleci-open.svg +1 -0
- package/dist/material-icons/folder-circleci.svg +1 -0
- package/dist/material-icons/folder-class-open.svg +1 -0
- package/dist/material-icons/folder-class.svg +1 -0
- package/dist/material-icons/folder-claude-open.svg +1 -0
- package/dist/material-icons/folder-claude.svg +1 -0
- package/dist/material-icons/folder-client-open.svg +1 -0
- package/dist/material-icons/folder-client.svg +1 -0
- package/dist/material-icons/folder-cline-open.svg +1 -0
- package/dist/material-icons/folder-cline.svg +1 -0
- package/dist/material-icons/folder-cloud-functions-open.svg +1 -0
- package/dist/material-icons/folder-cloud-functions.svg +1 -0
- package/dist/material-icons/folder-cloudflare-open.svg +1 -0
- package/dist/material-icons/folder-cloudflare.svg +1 -0
- package/dist/material-icons/folder-cluster-open.svg +1 -0
- package/dist/material-icons/folder-cluster.svg +1 -0
- package/dist/material-icons/folder-cobol-open.svg +1 -0
- package/dist/material-icons/folder-cobol.svg +1 -0
- package/dist/material-icons/folder-command-open.svg +1 -0
- package/dist/material-icons/folder-command.svg +1 -0
- package/dist/material-icons/folder-components-open.svg +1 -0
- package/dist/material-icons/folder-components.svg +1 -0
- package/dist/material-icons/folder-config-open.svg +1 -0
- package/dist/material-icons/folder-config.svg +1 -0
- package/dist/material-icons/folder-connection-open.svg +1 -0
- package/dist/material-icons/folder-connection.svg +1 -0
- package/dist/material-icons/folder-console-open.svg +1 -0
- package/dist/material-icons/folder-console.svg +1 -0
- package/dist/material-icons/folder-constant-open.svg +1 -0
- package/dist/material-icons/folder-constant.svg +1 -0
- package/dist/material-icons/folder-container-open.svg +1 -0
- package/dist/material-icons/folder-container.svg +1 -0
- package/dist/material-icons/folder-content-open.svg +1 -0
- package/dist/material-icons/folder-content.svg +1 -0
- package/dist/material-icons/folder-context-open.svg +1 -0
- package/dist/material-icons/folder-context.svg +1 -0
- package/dist/material-icons/folder-contract-open.svg +1 -0
- package/dist/material-icons/folder-contract.svg +1 -0
- package/dist/material-icons/folder-controller-open.svg +1 -0
- package/dist/material-icons/folder-controller.svg +1 -0
- package/dist/material-icons/folder-core-open.svg +1 -0
- package/dist/material-icons/folder-core.svg +1 -0
- package/dist/material-icons/folder-coverage-open.svg +1 -0
- package/dist/material-icons/folder-coverage.svg +1 -0
- package/dist/material-icons/folder-css-open.svg +1 -0
- package/dist/material-icons/folder-css.svg +1 -0
- package/dist/material-icons/folder-cue-open.svg +1 -0
- package/dist/material-icons/folder-cue.svg +1 -0
- package/dist/material-icons/folder-cursor-open.svg +1 -0
- package/dist/material-icons/folder-cursor-open_light.svg +1 -0
- package/dist/material-icons/folder-cursor.svg +1 -0
- package/dist/material-icons/folder-cursor_light.svg +1 -0
- package/dist/material-icons/folder-custom-open.svg +1 -0
- package/dist/material-icons/folder-custom.svg +1 -0
- package/dist/material-icons/folder-cypress-open.svg +1 -0
- package/dist/material-icons/folder-cypress.svg +1 -0
- package/dist/material-icons/folder-dal-open.svg +1 -0
- package/dist/material-icons/folder-dal.svg +1 -0
- package/dist/material-icons/folder-dart-open.svg +1 -0
- package/dist/material-icons/folder-dart.svg +1 -0
- package/dist/material-icons/folder-database-open.svg +1 -0
- package/dist/material-icons/folder-database.svg +1 -0
- package/dist/material-icons/folder-debug-open.svg +1 -0
- package/dist/material-icons/folder-debug.svg +1 -0
- package/dist/material-icons/folder-decorators-open.svg +1 -0
- package/dist/material-icons/folder-decorators.svg +1 -0
- package/dist/material-icons/folder-delta-open.svg +1 -0
- package/dist/material-icons/folder-delta.svg +1 -0
- package/dist/material-icons/folder-deprecated-open.clone.svg +1 -0
- package/dist/material-icons/folder-deprecated.clone.svg +1 -0
- package/dist/material-icons/folder-desktop-open.svg +1 -0
- package/dist/material-icons/folder-desktop.svg +1 -0
- package/dist/material-icons/folder-development-open.clone.svg +1 -0
- package/dist/material-icons/folder-development.clone.svg +1 -0
- package/dist/material-icons/folder-directive-open.svg +1 -0
- package/dist/material-icons/folder-directive.svg +1 -0
- package/dist/material-icons/folder-dist-open.svg +1 -0
- package/dist/material-icons/folder-dist.svg +1 -0
- package/dist/material-icons/folder-docker-open.svg +1 -0
- package/dist/material-icons/folder-docker.svg +1 -0
- package/dist/material-icons/folder-docs-open.svg +1 -0
- package/dist/material-icons/folder-docs.svg +1 -0
- package/dist/material-icons/folder-download-open.svg +1 -0
- package/dist/material-icons/folder-download.svg +1 -0
- package/dist/material-icons/folder-drizzle-open.svg +1 -0
- package/dist/material-icons/folder-drizzle.svg +1 -0
- package/dist/material-icons/folder-dump-open.svg +1 -0
- package/dist/material-icons/folder-dump.svg +1 -0
- package/dist/material-icons/folder-eas-open.clone.svg +1 -0
- package/dist/material-icons/folder-eas.clone.svg +1 -0
- package/dist/material-icons/folder-element-open.svg +1 -0
- package/dist/material-icons/folder-element.svg +1 -0
- package/dist/material-icons/folder-enum-open.svg +1 -0
- package/dist/material-icons/folder-enum.svg +1 -0
- package/dist/material-icons/folder-environment-open.svg +1 -0
- package/dist/material-icons/folder-environment.svg +1 -0
- package/dist/material-icons/folder-error-open.svg +1 -0
- package/dist/material-icons/folder-error.svg +1 -0
- package/dist/material-icons/folder-eslint-open.svg +1 -0
- package/dist/material-icons/folder-eslint.svg +1 -0
- package/dist/material-icons/folder-event-open.svg +1 -0
- package/dist/material-icons/folder-event.svg +1 -0
- package/dist/material-icons/folder-examples-open.svg +1 -0
- package/dist/material-icons/folder-examples.svg +1 -0
- package/dist/material-icons/folder-expo-open.svg +1 -0
- package/dist/material-icons/folder-expo.svg +1 -0
- package/dist/material-icons/folder-export-open.svg +1 -0
- package/dist/material-icons/folder-export.svg +1 -0
- package/dist/material-icons/folder-fastlane-open.svg +1 -0
- package/dist/material-icons/folder-fastlane.svg +1 -0
- package/dist/material-icons/folder-favicon-open.svg +1 -0
- package/dist/material-icons/folder-favicon.svg +1 -0
- package/dist/material-icons/folder-features-open.svg +1 -0
- package/dist/material-icons/folder-features.svg +1 -0
- package/dist/material-icons/folder-filter-open.svg +1 -0
- package/dist/material-icons/folder-filter.svg +1 -0
- package/dist/material-icons/folder-firebase-open.svg +1 -0
- package/dist/material-icons/folder-firebase.svg +1 -0
- package/dist/material-icons/folder-firestore-open.svg +1 -0
- package/dist/material-icons/folder-firestore.svg +1 -0
- package/dist/material-icons/folder-flow-open.svg +1 -0
- package/dist/material-icons/folder-flow.svg +1 -0
- package/dist/material-icons/folder-flutter-open.svg +1 -0
- package/dist/material-icons/folder-flutter.svg +1 -0
- package/dist/material-icons/folder-font-open.svg +1 -0
- package/dist/material-icons/folder-font.svg +1 -0
- package/dist/material-icons/folder-forgejo-open.svg +1 -0
- package/dist/material-icons/folder-forgejo.svg +1 -0
- package/dist/material-icons/folder-form-open.svg +1 -0
- package/dist/material-icons/folder-form.svg +1 -0
- package/dist/material-icons/folder-functions-open.svg +1 -0
- package/dist/material-icons/folder-functions.svg +1 -0
- package/dist/material-icons/folder-gamemaker-open.svg +1 -0
- package/dist/material-icons/folder-gamemaker.svg +1 -0
- package/dist/material-icons/folder-gemini-ai-open.svg +1 -0
- package/dist/material-icons/folder-gemini-ai.svg +1 -0
- package/dist/material-icons/folder-generator-open.svg +1 -0
- package/dist/material-icons/folder-generator.svg +1 -0
- package/dist/material-icons/folder-gh-workflows-open.svg +1 -0
- package/dist/material-icons/folder-gh-workflows.svg +1 -0
- package/dist/material-icons/folder-git-open.svg +1 -0
- package/dist/material-icons/folder-git.svg +1 -0
- package/dist/material-icons/folder-gitea-open.svg +1 -0
- package/dist/material-icons/folder-gitea-workflows-open.clone.svg +1 -0
- package/dist/material-icons/folder-gitea-workflows.clone.svg +1 -0
- package/dist/material-icons/folder-gitea.svg +1 -0
- package/dist/material-icons/folder-github-open.svg +1 -0
- package/dist/material-icons/folder-github.svg +1 -0
- package/dist/material-icons/folder-gitlab-open.svg +1 -0
- package/dist/material-icons/folder-gitlab.svg +1 -0
- package/dist/material-icons/folder-global-open.svg +1 -0
- package/dist/material-icons/folder-global.svg +1 -0
- package/dist/material-icons/folder-go-open.svg +1 -0
- package/dist/material-icons/folder-go.svg +1 -0
- package/dist/material-icons/folder-godot-open.svg +1 -0
- package/dist/material-icons/folder-godot.svg +1 -0
- package/dist/material-icons/folder-gradle-open.svg +1 -0
- package/dist/material-icons/folder-gradle.svg +1 -0
- package/dist/material-icons/folder-graphql-open.svg +1 -0
- package/dist/material-icons/folder-graphql.svg +1 -0
- package/dist/material-icons/folder-guard-open.svg +1 -0
- package/dist/material-icons/folder-guard.svg +1 -0
- package/dist/material-icons/folder-gulp-open.svg +1 -0
- package/dist/material-icons/folder-gulp.svg +1 -0
- package/dist/material-icons/folder-helm-open.svg +1 -0
- package/dist/material-icons/folder-helm.svg +1 -0
- package/dist/material-icons/folder-helper-open.svg +1 -0
- package/dist/material-icons/folder-helper.svg +1 -0
- package/dist/material-icons/folder-home-open.svg +1 -0
- package/dist/material-icons/folder-home.svg +1 -0
- package/dist/material-icons/folder-hook-open.svg +1 -0
- package/dist/material-icons/folder-hook.svg +1 -0
- package/dist/material-icons/folder-husky-open.svg +1 -0
- package/dist/material-icons/folder-husky.svg +1 -0
- package/dist/material-icons/folder-i18n-open.svg +1 -0
- package/dist/material-icons/folder-i18n.svg +1 -0
- package/dist/material-icons/folder-images-open.svg +1 -0
- package/dist/material-icons/folder-images.svg +1 -0
- package/dist/material-icons/folder-import-open.svg +1 -0
- package/dist/material-icons/folder-import.svg +1 -0
- package/dist/material-icons/folder-include-open.svg +1 -0
- package/dist/material-icons/folder-include.svg +1 -0
- package/dist/material-icons/folder-input-open.svg +1 -0
- package/dist/material-icons/folder-input.svg +1 -0
- package/dist/material-icons/folder-instructions-open.clone.svg +1 -0
- package/dist/material-icons/folder-instructions.clone.svg +1 -0
- package/dist/material-icons/folder-intellij-open.svg +1 -0
- package/dist/material-icons/folder-intellij-open_light.svg +1 -0
- package/dist/material-icons/folder-intellij.svg +1 -0
- package/dist/material-icons/folder-intellij_light.svg +1 -0
- package/dist/material-icons/folder-interceptor-open.svg +1 -0
- package/dist/material-icons/folder-interceptor.svg +1 -0
- package/dist/material-icons/folder-interface-open.svg +1 -0
- package/dist/material-icons/folder-interface.svg +1 -0
- package/dist/material-icons/folder-ios-open.svg +1 -0
- package/dist/material-icons/folder-ios.svg +1 -0
- package/dist/material-icons/folder-java-open.svg +1 -0
- package/dist/material-icons/folder-java.svg +1 -0
- package/dist/material-icons/folder-javascript-open.svg +1 -0
- package/dist/material-icons/folder-javascript.svg +1 -0
- package/dist/material-icons/folder-jinja-open.svg +1 -0
- package/dist/material-icons/folder-jinja-open_light.svg +1 -0
- package/dist/material-icons/folder-jinja.svg +1 -0
- package/dist/material-icons/folder-jinja_light.svg +1 -0
- package/dist/material-icons/folder-job-open.svg +1 -0
- package/dist/material-icons/folder-job.svg +1 -0
- package/dist/material-icons/folder-json-open.svg +1 -0
- package/dist/material-icons/folder-json.svg +1 -0
- package/dist/material-icons/folder-jupyter-open.svg +1 -0
- package/dist/material-icons/folder-jupyter.svg +1 -0
- package/dist/material-icons/folder-keys-open.svg +1 -0
- package/dist/material-icons/folder-keys.svg +1 -0
- package/dist/material-icons/folder-kotlin-open.svg +1 -0
- package/dist/material-icons/folder-kotlin.svg +1 -0
- package/dist/material-icons/folder-kubernetes-open.svg +1 -0
- package/dist/material-icons/folder-kubernetes.svg +1 -0
- package/dist/material-icons/folder-kusto-open.svg +1 -0
- package/dist/material-icons/folder-kusto.svg +1 -0
- package/dist/material-icons/folder-layout-open.svg +1 -0
- package/dist/material-icons/folder-layout.svg +1 -0
- package/dist/material-icons/folder-lefthook-open.svg +1 -0
- package/dist/material-icons/folder-lefthook.svg +1 -0
- package/dist/material-icons/folder-less-open.svg +1 -0
- package/dist/material-icons/folder-less.svg +1 -0
- package/dist/material-icons/folder-lib-open.svg +1 -0
- package/dist/material-icons/folder-lib.svg +1 -0
- package/dist/material-icons/folder-license-open.svg +1 -0
- package/dist/material-icons/folder-license.svg +1 -0
- package/dist/material-icons/folder-link-open.svg +1 -0
- package/dist/material-icons/folder-link.svg +1 -0
- package/dist/material-icons/folder-linux-open.svg +1 -0
- package/dist/material-icons/folder-linux.svg +1 -0
- package/dist/material-icons/folder-liquibase-open.svg +1 -0
- package/dist/material-icons/folder-liquibase.svg +1 -0
- package/dist/material-icons/folder-log-open.svg +1 -0
- package/dist/material-icons/folder-log.svg +1 -0
- package/dist/material-icons/folder-lottie-open.svg +1 -0
- package/dist/material-icons/folder-lottie.svg +1 -0
- package/dist/material-icons/folder-lua-open.svg +1 -0
- package/dist/material-icons/folder-lua.svg +1 -0
- package/dist/material-icons/folder-luau-open.svg +1 -0
- package/dist/material-icons/folder-luau.svg +1 -0
- package/dist/material-icons/folder-macos-open.svg +1 -0
- package/dist/material-icons/folder-macos.svg +1 -0
- package/dist/material-icons/folder-mail-open.svg +1 -0
- package/dist/material-icons/folder-mail.svg +1 -0
- package/dist/material-icons/folder-mappings-open.svg +1 -0
- package/dist/material-icons/folder-mappings.svg +1 -0
- package/dist/material-icons/folder-markdown-open.svg +1 -0
- package/dist/material-icons/folder-markdown.svg +1 -0
- package/dist/material-icons/folder-mercurial-open.svg +1 -0
- package/dist/material-icons/folder-mercurial.svg +1 -0
- package/dist/material-icons/folder-messages-open.svg +1 -0
- package/dist/material-icons/folder-messages.svg +1 -0
- package/dist/material-icons/folder-meta-open.svg +1 -0
- package/dist/material-icons/folder-meta.svg +1 -0
- package/dist/material-icons/folder-metro-open.svg +1 -0
- package/dist/material-icons/folder-metro.svg +1 -0
- package/dist/material-icons/folder-middleware-open.svg +1 -0
- package/dist/material-icons/folder-middleware.svg +1 -0
- package/dist/material-icons/folder-migrations-open.svg +1 -0
- package/dist/material-icons/folder-migrations.svg +1 -0
- package/dist/material-icons/folder-mjml-open.svg +1 -0
- package/dist/material-icons/folder-mjml.svg +1 -0
- package/dist/material-icons/folder-mobile-open.svg +1 -0
- package/dist/material-icons/folder-mobile.svg +1 -0
- package/dist/material-icons/folder-mock-open.svg +1 -0
- package/dist/material-icons/folder-mock.svg +1 -0
- package/dist/material-icons/folder-mojo-open.svg +1 -0
- package/dist/material-icons/folder-mojo.svg +1 -0
- package/dist/material-icons/folder-molecule-open.svg +1 -0
- package/dist/material-icons/folder-molecule.svg +1 -0
- package/dist/material-icons/folder-moon-open.svg +1 -0
- package/dist/material-icons/folder-moon.svg +1 -0
- package/dist/material-icons/folder-netlify-open.svg +1 -0
- package/dist/material-icons/folder-netlify.svg +1 -0
- package/dist/material-icons/folder-next-open.svg +1 -0
- package/dist/material-icons/folder-next.svg +1 -0
- package/dist/material-icons/folder-nginx-open.svg +1 -0
- package/dist/material-icons/folder-nginx.svg +1 -0
- package/dist/material-icons/folder-ngrx-actions-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-actions.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-effects-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-effects.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-entities-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-entities.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-reducer-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-reducer.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-selectors-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-selectors.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-state-open.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-state.clone.svg +1 -0
- package/dist/material-icons/folder-ngrx-store-open.svg +1 -0
- package/dist/material-icons/folder-ngrx-store.svg +1 -0
- package/dist/material-icons/folder-node-open.svg +1 -0
- package/dist/material-icons/folder-node.svg +1 -0
- package/dist/material-icons/folder-nuxt-open.svg +1 -0
- package/dist/material-icons/folder-nuxt.svg +1 -0
- package/dist/material-icons/folder-obsidian-open.svg +1 -0
- package/dist/material-icons/folder-obsidian.svg +1 -0
- package/dist/material-icons/folder-open.svg +1 -0
- package/dist/material-icons/folder-opencode-open.svg +1 -0
- package/dist/material-icons/folder-opencode.svg +1 -0
- package/dist/material-icons/folder-organism-open.svg +1 -0
- package/dist/material-icons/folder-organism.svg +1 -0
- package/dist/material-icons/folder-other-open.svg +1 -0
- package/dist/material-icons/folder-other.svg +1 -0
- package/dist/material-icons/folder-packages-open.svg +1 -0
- package/dist/material-icons/folder-packages.svg +1 -0
- package/dist/material-icons/folder-pdf-open.svg +1 -0
- package/dist/material-icons/folder-pdf.svg +1 -0
- package/dist/material-icons/folder-pdm-open.svg +1 -0
- package/dist/material-icons/folder-pdm.svg +1 -0
- package/dist/material-icons/folder-php-open.svg +1 -0
- package/dist/material-icons/folder-php.svg +1 -0
- package/dist/material-icons/folder-phpmailer-open.svg +1 -0
- package/dist/material-icons/folder-phpmailer.svg +1 -0
- package/dist/material-icons/folder-pipe-open.svg +1 -0
- package/dist/material-icons/folder-pipe.svg +1 -0
- package/dist/material-icons/folder-plastic-open.svg +1 -0
- package/dist/material-icons/folder-plastic.svg +1 -0
- package/dist/material-icons/folder-plugin-open.svg +1 -0
- package/dist/material-icons/folder-plugin.svg +1 -0
- package/dist/material-icons/folder-policy-open.svg +1 -0
- package/dist/material-icons/folder-policy.svg +1 -0
- package/dist/material-icons/folder-postman-open.svg +1 -0
- package/dist/material-icons/folder-postman.svg +1 -0
- package/dist/material-icons/folder-powershell-open.svg +1 -0
- package/dist/material-icons/folder-powershell.svg +1 -0
- package/dist/material-icons/folder-prisma-open.svg +1 -0
- package/dist/material-icons/folder-prisma.svg +1 -0
- package/dist/material-icons/folder-private-open.svg +1 -0
- package/dist/material-icons/folder-private.svg +1 -0
- package/dist/material-icons/folder-project-open.svg +1 -0
- package/dist/material-icons/folder-project.svg +1 -0
- package/dist/material-icons/folder-prompts-open.svg +1 -0
- package/dist/material-icons/folder-prompts.svg +1 -0
- package/dist/material-icons/folder-proto-open.svg +1 -0
- package/dist/material-icons/folder-proto.svg +1 -0
- package/dist/material-icons/folder-public-open.svg +1 -0
- package/dist/material-icons/folder-public.svg +1 -0
- package/dist/material-icons/folder-python-open.svg +1 -0
- package/dist/material-icons/folder-python.svg +1 -0
- package/dist/material-icons/folder-pytorch-open.svg +1 -0
- package/dist/material-icons/folder-pytorch.svg +1 -0
- package/dist/material-icons/folder-quasar-open.svg +1 -0
- package/dist/material-icons/folder-quasar.svg +1 -0
- package/dist/material-icons/folder-queue-open.svg +1 -0
- package/dist/material-icons/folder-queue.svg +1 -0
- package/dist/material-icons/folder-r-open.svg +1 -0
- package/dist/material-icons/folder-r.svg +1 -0
- package/dist/material-icons/folder-react-components-open.svg +1 -0
- package/dist/material-icons/folder-react-components.svg +1 -0
- package/dist/material-icons/folder-redis-open.clone.svg +1 -0
- package/dist/material-icons/folder-redis.clone.svg +1 -0
- package/dist/material-icons/folder-redux-actions-open.clone.svg +1 -0
- package/dist/material-icons/folder-redux-actions.clone.svg +1 -0
- package/dist/material-icons/folder-redux-reducer-open.svg +1 -0
- package/dist/material-icons/folder-redux-reducer.svg +1 -0
- package/dist/material-icons/folder-redux-selector-open.clone.svg +1 -0
- package/dist/material-icons/folder-redux-selector.clone.svg +1 -0
- package/dist/material-icons/folder-redux-store-open.clone.svg +1 -0
- package/dist/material-icons/folder-redux-store.clone.svg +1 -0
- package/dist/material-icons/folder-redux-toolkit-open.clone.svg +1 -0
- package/dist/material-icons/folder-redux-toolkit.clone.svg +1 -0
- package/dist/material-icons/folder-repository-open.svg +1 -0
- package/dist/material-icons/folder-repository.svg +1 -0
- package/dist/material-icons/folder-resolver-open.svg +1 -0
- package/dist/material-icons/folder-resolver.svg +1 -0
- package/dist/material-icons/folder-resource-open.svg +1 -0
- package/dist/material-icons/folder-resource.svg +1 -0
- package/dist/material-icons/folder-review-open.svg +1 -0
- package/dist/material-icons/folder-review.svg +1 -0
- package/dist/material-icons/folder-robot-open.svg +1 -0
- package/dist/material-icons/folder-robot.svg +1 -0
- package/dist/material-icons/folder-root-open.svg +1 -0
- package/dist/material-icons/folder-root.svg +1 -0
- package/dist/material-icons/folder-routes-open.svg +1 -0
- package/dist/material-icons/folder-routes.svg +1 -0
- package/dist/material-icons/folder-rules-open.svg +1 -0
- package/dist/material-icons/folder-rules.svg +1 -0
- package/dist/material-icons/folder-rust-open.svg +1 -0
- package/dist/material-icons/folder-rust.svg +1 -0
- package/dist/material-icons/folder-salt-open.svg +1 -0
- package/dist/material-icons/folder-salt.svg +1 -0
- package/dist/material-icons/folder-sandbox-open.svg +1 -0
- package/dist/material-icons/folder-sandbox.svg +1 -0
- package/dist/material-icons/folder-sass-open.svg +1 -0
- package/dist/material-icons/folder-sass.svg +1 -0
- package/dist/material-icons/folder-scala-open.svg +1 -0
- package/dist/material-icons/folder-scala.svg +1 -0
- package/dist/material-icons/folder-scons-open.svg +1 -0
- package/dist/material-icons/folder-scons.svg +1 -0
- package/dist/material-icons/folder-scrap-open.clone.svg +1 -0
- package/dist/material-icons/folder-scrap.clone.svg +1 -0
- package/dist/material-icons/folder-scripts-open.svg +1 -0
- package/dist/material-icons/folder-scripts.svg +1 -0
- package/dist/material-icons/folder-secure-open.svg +1 -0
- package/dist/material-icons/folder-secure.svg +1 -0
- package/dist/material-icons/folder-seeders-open.svg +1 -0
- package/dist/material-icons/folder-seeders.svg +1 -0
- package/dist/material-icons/folder-server-open.svg +1 -0
- package/dist/material-icons/folder-server.svg +1 -0
- package/dist/material-icons/folder-serverless-open.svg +1 -0
- package/dist/material-icons/folder-serverless.svg +1 -0
- package/dist/material-icons/folder-shader-open.svg +1 -0
- package/dist/material-icons/folder-shader.svg +1 -0
- package/dist/material-icons/folder-shared-open.svg +1 -0
- package/dist/material-icons/folder-shared.svg +1 -0
- package/dist/material-icons/folder-simulations-open.svg +1 -0
- package/dist/material-icons/folder-simulations.svg +1 -0
- package/dist/material-icons/folder-skills-open.svg +1 -0
- package/dist/material-icons/folder-skills.svg +1 -0
- package/dist/material-icons/folder-snapcraft-open.svg +1 -0
- package/dist/material-icons/folder-snapcraft.svg +1 -0
- package/dist/material-icons/folder-snippet-open.svg +1 -0
- package/dist/material-icons/folder-snippet.svg +1 -0
- package/dist/material-icons/folder-src-open.svg +1 -0
- package/dist/material-icons/folder-src-tauri-open.svg +1 -0
- package/dist/material-icons/folder-src-tauri.svg +1 -0
- package/dist/material-icons/folder-src.svg +1 -0
- package/dist/material-icons/folder-stack-open.svg +1 -0
- package/dist/material-icons/folder-stack.svg +1 -0
- package/dist/material-icons/folder-stencil-open.svg +1 -0
- package/dist/material-icons/folder-stencil.svg +1 -0
- package/dist/material-icons/folder-store-open.svg +1 -0
- package/dist/material-icons/folder-store.svg +1 -0
- package/dist/material-icons/folder-storybook-open.svg +1 -0
- package/dist/material-icons/folder-storybook.svg +1 -0
- package/dist/material-icons/folder-stylus-open.svg +1 -0
- package/dist/material-icons/folder-stylus.svg +1 -0
- package/dist/material-icons/folder-sublime-open.svg +1 -0
- package/dist/material-icons/folder-sublime.svg +1 -0
- package/dist/material-icons/folder-supabase-open.svg +1 -0
- package/dist/material-icons/folder-supabase.svg +1 -0
- package/dist/material-icons/folder-svelte-open.svg +1 -0
- package/dist/material-icons/folder-svelte.svg +1 -0
- package/dist/material-icons/folder-svg-open.svg +1 -0
- package/dist/material-icons/folder-svg.svg +1 -0
- package/dist/material-icons/folder-syntax-open.svg +1 -0
- package/dist/material-icons/folder-syntax.svg +1 -0
- package/dist/material-icons/folder-target-open.svg +1 -0
- package/dist/material-icons/folder-target.svg +1 -0
- package/dist/material-icons/folder-taskfile-open.svg +1 -0
- package/dist/material-icons/folder-taskfile.svg +1 -0
- package/dist/material-icons/folder-tasks-open.svg +1 -0
- package/dist/material-icons/folder-tasks.svg +1 -0
- package/dist/material-icons/folder-television-open.svg +1 -0
- package/dist/material-icons/folder-television.svg +1 -0
- package/dist/material-icons/folder-temp-open.svg +1 -0
- package/dist/material-icons/folder-temp.svg +1 -0
- package/dist/material-icons/folder-template-open.svg +1 -0
- package/dist/material-icons/folder-template.svg +1 -0
- package/dist/material-icons/folder-terraform-open.svg +1 -0
- package/dist/material-icons/folder-terraform.svg +1 -0
- package/dist/material-icons/folder-test-open.svg +1 -0
- package/dist/material-icons/folder-test.svg +1 -0
- package/dist/material-icons/folder-theme-open.svg +1 -0
- package/dist/material-icons/folder-theme.svg +1 -0
- package/dist/material-icons/folder-toc-open.svg +1 -0
- package/dist/material-icons/folder-toc.svg +1 -0
- package/dist/material-icons/folder-tools-open.svg +1 -0
- package/dist/material-icons/folder-tools.svg +1 -0
- package/dist/material-icons/folder-trash-open.svg +1 -0
- package/dist/material-icons/folder-trash.svg +1 -0
- package/dist/material-icons/folder-trigger-open.svg +1 -0
- package/dist/material-icons/folder-trigger.svg +1 -0
- package/dist/material-icons/folder-turborepo-open.svg +1 -0
- package/dist/material-icons/folder-turborepo.svg +1 -0
- package/dist/material-icons/folder-typescript-open.svg +1 -0
- package/dist/material-icons/folder-typescript.svg +1 -0
- package/dist/material-icons/folder-ui-open.svg +1 -0
- package/dist/material-icons/folder-ui.svg +1 -0
- package/dist/material-icons/folder-unity-open.svg +1 -0
- package/dist/material-icons/folder-unity.svg +1 -0
- package/dist/material-icons/folder-update-open.svg +1 -0
- package/dist/material-icons/folder-update.svg +1 -0
- package/dist/material-icons/folder-upload-open.svg +1 -0
- package/dist/material-icons/folder-upload.svg +1 -0
- package/dist/material-icons/folder-utils-open.svg +1 -0
- package/dist/material-icons/folder-utils.svg +1 -0
- package/dist/material-icons/folder-vercel-open.svg +1 -0
- package/dist/material-icons/folder-vercel.svg +1 -0
- package/dist/material-icons/folder-verdaccio-open.svg +1 -0
- package/dist/material-icons/folder-verdaccio.svg +1 -0
- package/dist/material-icons/folder-video-open.svg +1 -0
- package/dist/material-icons/folder-video.svg +1 -0
- package/dist/material-icons/folder-views-open.svg +1 -0
- package/dist/material-icons/folder-views.svg +1 -0
- package/dist/material-icons/folder-vm-open.svg +1 -0
- package/dist/material-icons/folder-vm.svg +1 -0
- package/dist/material-icons/folder-vscode-open.svg +1 -0
- package/dist/material-icons/folder-vscode.svg +1 -0
- package/dist/material-icons/folder-vue-directives-open.svg +1 -0
- package/dist/material-icons/folder-vue-directives.svg +1 -0
- package/dist/material-icons/folder-vue-open.svg +1 -0
- package/dist/material-icons/folder-vue.svg +1 -0
- package/dist/material-icons/folder-vuepress-open.svg +1 -0
- package/dist/material-icons/folder-vuepress.svg +1 -0
- package/dist/material-icons/folder-vuex-store-open.svg +1 -0
- package/dist/material-icons/folder-vuex-store.svg +1 -0
- package/dist/material-icons/folder-wakatime-open.svg +1 -0
- package/dist/material-icons/folder-wakatime.svg +1 -0
- package/dist/material-icons/folder-webpack-open.svg +1 -0
- package/dist/material-icons/folder-webpack.svg +1 -0
- package/dist/material-icons/folder-windows-open.svg +1 -0
- package/dist/material-icons/folder-windows.svg +1 -0
- package/dist/material-icons/folder-wordpress-open.svg +1 -0
- package/dist/material-icons/folder-wordpress.svg +1 -0
- package/dist/material-icons/folder-yarn-open.svg +1 -0
- package/dist/material-icons/folder-yarn.svg +1 -0
- package/dist/material-icons/folder-zeabur-open.svg +1 -0
- package/dist/material-icons/folder-zeabur.svg +1 -0
- package/dist/material-icons/folder-zed-open.svg +1 -0
- package/dist/material-icons/folder-zed.svg +1 -0
- package/dist/material-icons/folder.svg +1 -0
- package/dist/material-icons/font.svg +1 -0
- package/dist/material-icons/forth.svg +1 -0
- package/dist/material-icons/fortran.svg +1 -0
- package/dist/material-icons/foxpro.svg +1 -0
- package/dist/material-icons/freemarker.svg +1 -0
- package/dist/material-icons/fsharp.svg +1 -0
- package/dist/material-icons/fusebox.svg +1 -0
- package/dist/material-icons/gamemaker.svg +1 -0
- package/dist/material-icons/garden.svg +1 -0
- package/dist/material-icons/gatsby.svg +1 -0
- package/dist/material-icons/gcp.svg +1 -0
- package/dist/material-icons/gemfile.svg +1 -0
- package/dist/material-icons/gemini-ai.svg +1 -0
- package/dist/material-icons/gemini.svg +1 -0
- package/dist/material-icons/git.svg +1 -0
- package/dist/material-icons/github-actions-workflow.svg +1 -0
- package/dist/material-icons/github-sponsors.svg +1 -0
- package/dist/material-icons/gitlab.svg +1 -0
- package/dist/material-icons/gitpod.svg +1 -0
- package/dist/material-icons/gleam.svg +1 -0
- package/dist/material-icons/gnuplot.svg +1 -0
- package/dist/material-icons/go-mod.svg +1 -0
- package/dist/material-icons/go.svg +1 -0
- package/dist/material-icons/go_gopher.svg +1 -0
- package/dist/material-icons/godot-assets.svg +1 -0
- package/dist/material-icons/godot.svg +1 -0
- package/dist/material-icons/google.svg +1 -0
- package/dist/material-icons/gradle.svg +1 -0
- package/dist/material-icons/grafana-alloy.svg +1 -0
- package/dist/material-icons/grain.svg +1 -0
- package/dist/material-icons/graphcool.svg +1 -0
- package/dist/material-icons/graphql.svg +1 -0
- package/dist/material-icons/gridsome.svg +1 -0
- package/dist/material-icons/groovy.svg +1 -0
- package/dist/material-icons/grunt.svg +1 -0
- package/dist/material-icons/gulp.svg +1 -0
- package/dist/material-icons/h.svg +1 -0
- package/dist/material-icons/hack.svg +1 -0
- package/dist/material-icons/hadolint.svg +1 -0
- package/dist/material-icons/haml.svg +1 -0
- package/dist/material-icons/handlebars.svg +1 -0
- package/dist/material-icons/happo.svg +1 -0
- package/dist/material-icons/hardhat.svg +1 -0
- package/dist/material-icons/harmonix.svg +1 -0
- package/dist/material-icons/haskell.svg +1 -0
- package/dist/material-icons/haxe.svg +1 -0
- package/dist/material-icons/hcl.svg +1 -0
- package/dist/material-icons/hcl_light.svg +1 -0
- package/dist/material-icons/helm.svg +1 -0
- package/dist/material-icons/heroku.svg +1 -0
- package/dist/material-icons/hex.svg +1 -0
- package/dist/material-icons/hip.svg +1 -0
- package/dist/material-icons/histoire.svg +1 -0
- package/dist/material-icons/hjson.svg +1 -0
- package/dist/material-icons/horusec.svg +1 -0
- package/dist/material-icons/hosts.svg +1 -0
- package/dist/material-icons/hosts_light.svg +1 -0
- package/dist/material-icons/hpp.svg +1 -0
- package/dist/material-icons/html.svg +1 -0
- package/dist/material-icons/http.svg +1 -0
- package/dist/material-icons/huff.svg +1 -0
- package/dist/material-icons/huff_light.svg +1 -0
- package/dist/material-icons/hurl.svg +1 -0
- package/dist/material-icons/husky.svg +1 -0
- package/dist/material-icons/i18n.svg +1 -0
- package/dist/material-icons/idris.svg +1 -0
- package/dist/material-icons/ifanr-cloud.svg +1 -0
- package/dist/material-icons/image.svg +1 -0
- package/dist/material-icons/imba.svg +1 -0
- package/dist/material-icons/installation.svg +1 -0
- package/dist/material-icons/instructions.clone.svg +1 -0
- package/dist/material-icons/ionic.svg +1 -0
- package/dist/material-icons/istanbul.svg +1 -0
- package/dist/material-icons/jar.svg +1 -0
- package/dist/material-icons/java.svg +1 -0
- package/dist/material-icons/javaclass.svg +1 -0
- package/dist/material-icons/javascript-map.svg +1 -0
- package/dist/material-icons/javascript.svg +1 -0
- package/dist/material-icons/jenkins.svg +1 -0
- package/dist/material-icons/jest.svg +1 -0
- package/dist/material-icons/jinja.svg +1 -0
- package/dist/material-icons/jinja_light.svg +1 -0
- package/dist/material-icons/jsconfig.svg +1 -0
- package/dist/material-icons/json.svg +1 -0
- package/dist/material-icons/json_schema.svg +1 -0
- package/dist/material-icons/jsr.svg +1 -0
- package/dist/material-icons/jsr_light.svg +1 -0
- package/dist/material-icons/julia.svg +1 -0
- package/dist/material-icons/jupyter.svg +1 -0
- package/dist/material-icons/just.svg +1 -0
- package/dist/material-icons/karma.svg +1 -0
- package/dist/material-icons/kcl.svg +1 -0
- package/dist/material-icons/key.svg +1 -0
- package/dist/material-icons/keystatic.svg +1 -0
- package/dist/material-icons/kivy.svg +1 -0
- package/dist/material-icons/kl.svg +1 -0
- package/dist/material-icons/knip.svg +1 -0
- package/dist/material-icons/kotlin.svg +1 -0
- package/dist/material-icons/kubernetes.svg +1 -0
- package/dist/material-icons/kusto.svg +1 -0
- package/dist/material-icons/label.svg +1 -0
- package/dist/material-icons/laravel.svg +1 -0
- package/dist/material-icons/latex-class.clone.svg +1 -0
- package/dist/material-icons/latex-package.clone.svg +1 -0
- package/dist/material-icons/latex.clone.svg +1 -0
- package/dist/material-icons/latexmk.svg +1 -0
- package/dist/material-icons/lbx.svg +1 -0
- package/dist/material-icons/lean.svg +1 -0
- package/dist/material-icons/lefthook.svg +1 -0
- package/dist/material-icons/lerna.svg +1 -0
- package/dist/material-icons/less.svg +1 -0
- package/dist/material-icons/liara.svg +1 -0
- package/dist/material-icons/lib.svg +1 -0
- package/dist/material-icons/license.svg +1 -0
- package/dist/material-icons/lighthouse.svg +1 -0
- package/dist/material-icons/lilypond.svg +1 -0
- package/dist/material-icons/lintstaged.svg +1 -0
- package/dist/material-icons/liquid.svg +1 -0
- package/dist/material-icons/lisp.svg +1 -0
- package/dist/material-icons/livescript.svg +1 -0
- package/dist/material-icons/lock.svg +1 -0
- package/dist/material-icons/log.svg +1 -0
- package/dist/material-icons/lolcode.svg +1 -0
- package/dist/material-icons/lottie.svg +1 -0
- package/dist/material-icons/lua.svg +1 -0
- package/dist/material-icons/luau.svg +1 -0
- package/dist/material-icons/lynx.svg +1 -0
- package/dist/material-icons/lyric.svg +1 -0
- package/dist/material-icons/macaulay2.svg +1 -0
- package/dist/material-icons/makefile.svg +1 -0
- package/dist/material-icons/markdoc-config.svg +1 -0
- package/dist/material-icons/markdoc.svg +1 -0
- package/dist/material-icons/markdown.svg +1 -0
- package/dist/material-icons/markdownlint.svg +1 -0
- package/dist/material-icons/markojs.svg +1 -0
- package/dist/material-icons/mathematica.svg +1 -0
- package/dist/material-icons/matlab.svg +1 -0
- package/dist/material-icons/maven.svg +1 -0
- package/dist/material-icons/mdsvex.svg +1 -0
- package/dist/material-icons/mdx.svg +1 -0
- package/dist/material-icons/mercurial.svg +1 -0
- package/dist/material-icons/merlin.svg +1 -0
- package/dist/material-icons/mermaid.svg +1 -0
- package/dist/material-icons/meson.svg +1 -0
- package/dist/material-icons/metro.svg +1 -0
- package/dist/material-icons/minecraft-fabric.svg +1 -0
- package/dist/material-icons/minecraft.svg +1 -0
- package/dist/material-icons/mint.svg +1 -0
- package/dist/material-icons/mist.clone.svg +1 -0
- package/dist/material-icons/mjml.svg +1 -0
- package/dist/material-icons/mocha.svg +1 -0
- package/dist/material-icons/modernizr.svg +1 -0
- package/dist/material-icons/mojo.svg +1 -0
- package/dist/material-icons/moon.svg +1 -0
- package/dist/material-icons/moonscript.svg +1 -0
- package/dist/material-icons/mrpack.svg +1 -0
- package/dist/material-icons/mxml.svg +1 -0
- package/dist/material-icons/nano-staged.svg +1 -0
- package/dist/material-icons/nano-staged_light.svg +1 -0
- package/dist/material-icons/ndst.svg +1 -0
- package/dist/material-icons/nest-controller.clone.svg +1 -0
- package/dist/material-icons/nest-decorator.clone.svg +1 -0
- package/dist/material-icons/nest-filter.clone.svg +1 -0
- package/dist/material-icons/nest-gateway.clone.svg +1 -0
- package/dist/material-icons/nest-guard.clone.svg +1 -0
- package/dist/material-icons/nest-interceptor.clone.svg +1 -0
- package/dist/material-icons/nest-middleware.clone.svg +1 -0
- package/dist/material-icons/nest-module.clone.svg +1 -0
- package/dist/material-icons/nest-pipe.clone.svg +1 -0
- package/dist/material-icons/nest-resolver.clone.svg +1 -0
- package/dist/material-icons/nest-service.clone.svg +1 -0
- package/dist/material-icons/nest.svg +1 -0
- package/dist/material-icons/netlify.svg +1 -0
- package/dist/material-icons/netlify_light.svg +1 -0
- package/dist/material-icons/next.svg +1 -0
- package/dist/material-icons/next_light.svg +1 -0
- package/dist/material-icons/nginx.svg +1 -0
- package/dist/material-icons/ngrx-actions.svg +1 -0
- package/dist/material-icons/ngrx-effects.svg +1 -0
- package/dist/material-icons/ngrx-entity.svg +1 -0
- package/dist/material-icons/ngrx-reducer.svg +1 -0
- package/dist/material-icons/ngrx-selectors.svg +1 -0
- package/dist/material-icons/ngrx-state.svg +1 -0
- package/dist/material-icons/nim.svg +1 -0
- package/dist/material-icons/nix.svg +1 -0
- package/dist/material-icons/nodejs.svg +1 -0
- package/dist/material-icons/nodejs_alt.svg +1 -0
- package/dist/material-icons/nodemon.svg +1 -0
- package/dist/material-icons/npm.svg +1 -0
- package/dist/material-icons/nuget.svg +1 -0
- package/dist/material-icons/nunjucks.svg +1 -0
- package/dist/material-icons/nuxt.svg +1 -0
- package/dist/material-icons/nx.svg +1 -0
- package/dist/material-icons/objective-c.svg +1 -0
- package/dist/material-icons/objective-cpp.svg +1 -0
- package/dist/material-icons/ocaml.svg +1 -0
- package/dist/material-icons/odin.svg +1 -0
- package/dist/material-icons/onnx.svg +1 -0
- package/dist/material-icons/opa.svg +1 -0
- package/dist/material-icons/opam.svg +1 -0
- package/dist/material-icons/openapi.svg +1 -0
- package/dist/material-icons/openapi_light.svg +1 -0
- package/dist/material-icons/opencode.svg +1 -0
- package/dist/material-icons/opencode_light.svg +1 -0
- package/dist/material-icons/opentofu.svg +1 -0
- package/dist/material-icons/opentofu_light.svg +1 -0
- package/dist/material-icons/otne.svg +1 -0
- package/dist/material-icons/oxc.svg +1 -0
- package/dist/material-icons/packship.svg +1 -0
- package/dist/material-icons/palette.svg +1 -0
- package/dist/material-icons/panda.svg +1 -0
- package/dist/material-icons/parcel.svg +1 -0
- package/dist/material-icons/pascal.svg +1 -0
- package/dist/material-icons/pawn.svg +1 -0
- package/dist/material-icons/payload.svg +1 -0
- package/dist/material-icons/payload_light.svg +1 -0
- package/dist/material-icons/pdf.svg +1 -0
- package/dist/material-icons/pdm.svg +1 -0
- package/dist/material-icons/percy.svg +1 -0
- package/dist/material-icons/perl.svg +1 -0
- package/dist/material-icons/php-cs-fixer.svg +1 -0
- package/dist/material-icons/php.svg +1 -0
- package/dist/material-icons/php_elephant.svg +1 -0
- package/dist/material-icons/php_elephant_pink.svg +1 -0
- package/dist/material-icons/phpstan.svg +1 -0
- package/dist/material-icons/phpunit.svg +1 -0
- package/dist/material-icons/pinejs.svg +1 -0
- package/dist/material-icons/pipeline.svg +1 -0
- package/dist/material-icons/pkl.svg +1 -0
- package/dist/material-icons/plastic.svg +1 -0
- package/dist/material-icons/playwright.svg +1 -0
- package/dist/material-icons/plop.svg +1 -0
- package/dist/material-icons/pm2-ecosystem.svg +1 -0
- package/dist/material-icons/pnpm.svg +1 -0
- package/dist/material-icons/pnpm_light.svg +1 -0
- package/dist/material-icons/poetry.svg +1 -0
- package/dist/material-icons/postcss.svg +1 -0
- package/dist/material-icons/posthtml.svg +1 -0
- package/dist/material-icons/powerpoint.svg +1 -0
- package/dist/material-icons/powershell.svg +1 -0
- package/dist/material-icons/pre-commit.svg +1 -0
- package/dist/material-icons/prettier.svg +1 -0
- package/dist/material-icons/prisma.svg +1 -0
- package/dist/material-icons/processing.svg +1 -0
- package/dist/material-icons/prolog.svg +1 -0
- package/dist/material-icons/prompt.svg +1 -0
- package/dist/material-icons/proto.svg +1 -0
- package/dist/material-icons/protractor.svg +1 -0
- package/dist/material-icons/pug.svg +1 -0
- package/dist/material-icons/puppet.svg +1 -0
- package/dist/material-icons/puppeteer.svg +1 -0
- package/dist/material-icons/purescript.svg +1 -0
- package/dist/material-icons/python-misc.svg +1 -0
- package/dist/material-icons/python.svg +1 -0
- package/dist/material-icons/pytorch.svg +1 -0
- package/dist/material-icons/qsharp.svg +1 -0
- package/dist/material-icons/quarto.svg +1 -0
- package/dist/material-icons/quasar.svg +1 -0
- package/dist/material-icons/quokka.svg +1 -0
- package/dist/material-icons/qwik.svg +1 -0
- package/dist/material-icons/r.svg +1 -0
- package/dist/material-icons/racket.svg +1 -0
- package/dist/material-icons/raml.svg +1 -0
- package/dist/material-icons/razor.svg +1 -0
- package/dist/material-icons/rbxmk.svg +1 -0
- package/dist/material-icons/rc.svg +1 -0
- package/dist/material-icons/react.svg +1 -0
- package/dist/material-icons/react_ts.svg +1 -0
- package/dist/material-icons/readme.svg +1 -0
- package/dist/material-icons/reason.svg +1 -0
- package/dist/material-icons/red.svg +1 -0
- package/dist/material-icons/redux-action.svg +1 -0
- package/dist/material-icons/redux-reducer.svg +1 -0
- package/dist/material-icons/redux-selector.svg +1 -0
- package/dist/material-icons/redux-store.svg +1 -0
- package/dist/material-icons/regedit.svg +1 -0
- package/dist/material-icons/remark.svg +1 -0
- package/dist/material-icons/remix.svg +1 -0
- package/dist/material-icons/remix_light.svg +1 -0
- package/dist/material-icons/renovate.svg +1 -0
- package/dist/material-icons/replit.svg +1 -0
- package/dist/material-icons/rescript-interface.svg +1 -0
- package/dist/material-icons/rescript.svg +1 -0
- package/dist/material-icons/restql.svg +1 -0
- package/dist/material-icons/riot.svg +1 -0
- package/dist/material-icons/roadmap.svg +1 -0
- package/dist/material-icons/roblox.svg +1 -0
- package/dist/material-icons/robot.svg +1 -0
- package/dist/material-icons/robots.svg +1 -0
- package/dist/material-icons/rocket.svg +1 -0
- package/dist/material-icons/rojo.svg +1 -0
- package/dist/material-icons/rolldown.svg +1 -0
- package/dist/material-icons/rollup.svg +1 -0
- package/dist/material-icons/rome.svg +1 -0
- package/dist/material-icons/routing.svg +1 -0
- package/dist/material-icons/rspec.svg +1 -0
- package/dist/material-icons/rstack.svg +1 -0
- package/dist/material-icons/rubocop.svg +1 -0
- package/dist/material-icons/rubocop_light.svg +1 -0
- package/dist/material-icons/ruby.svg +1 -0
- package/dist/material-icons/ruff.svg +1 -0
- package/dist/material-icons/rust.svg +1 -0
- package/dist/material-icons/salesforce.svg +1 -0
- package/dist/material-icons/salt.svg +1 -0
- package/dist/material-icons/san.svg +1 -0
- package/dist/material-icons/sas.svg +1 -0
- package/dist/material-icons/sass.svg +1 -0
- package/dist/material-icons/sbt.svg +1 -0
- package/dist/material-icons/scala.svg +1 -0
- package/dist/material-icons/scheme.svg +1 -0
- package/dist/material-icons/scons.svg +1 -0
- package/dist/material-icons/scons_light.svg +1 -0
- package/dist/material-icons/screwdriver.svg +1 -0
- package/dist/material-icons/search.svg +1 -0
- package/dist/material-icons/semantic-release.svg +1 -0
- package/dist/material-icons/semantic-release_light.svg +1 -0
- package/dist/material-icons/semgrep.svg +1 -0
- package/dist/material-icons/sentry.svg +1 -0
- package/dist/material-icons/sequelize.svg +1 -0
- package/dist/material-icons/serverless.svg +1 -0
- package/dist/material-icons/settings.svg +1 -0
- package/dist/material-icons/shader.svg +1 -0
- package/dist/material-icons/shellcheck.svg +1 -0
- package/dist/material-icons/shellcheck_light.svg +1 -0
- package/dist/material-icons/silverstripe.svg +1 -0
- package/dist/material-icons/simulink.svg +1 -0
- package/dist/material-icons/siyuan.svg +1 -0
- package/dist/material-icons/sketch.svg +1 -0
- package/dist/material-icons/skill.svg +1 -0
- package/dist/material-icons/slim.svg +1 -0
- package/dist/material-icons/slint.svg +1 -0
- package/dist/material-icons/slug.svg +1 -0
- package/dist/material-icons/smarty.svg +1 -0
- package/dist/material-icons/sml.svg +1 -0
- package/dist/material-icons/snakemake.svg +1 -0
- package/dist/material-icons/snapcraft.svg +1 -0
- package/dist/material-icons/snowpack.svg +1 -0
- package/dist/material-icons/snowpack_light.svg +1 -0
- package/dist/material-icons/snyk.svg +1 -0
- package/dist/material-icons/solidity.svg +1 -0
- package/dist/material-icons/sonarcloud.svg +1 -0
- package/dist/material-icons/spwn.svg +1 -0
- package/dist/material-icons/stackblitz.svg +1 -0
- package/dist/material-icons/stan.svg +1 -0
- package/dist/material-icons/steadybit.svg +1 -0
- package/dist/material-icons/stencil.svg +1 -0
- package/dist/material-icons/stitches.svg +1 -0
- package/dist/material-icons/stitches_light.svg +1 -0
- package/dist/material-icons/storybook.svg +1 -0
- package/dist/material-icons/stryker.svg +1 -0
- package/dist/material-icons/sty.clone.svg +1 -0
- package/dist/material-icons/stylable.svg +1 -0
- package/dist/material-icons/stylelint.svg +1 -0
- package/dist/material-icons/stylelint_light.svg +1 -0
- package/dist/material-icons/stylus.svg +1 -0
- package/dist/material-icons/sublime.svg +1 -0
- package/dist/material-icons/subtitles.svg +1 -0
- package/dist/material-icons/supabase.svg +1 -0
- package/dist/material-icons/svelte.svg +1 -0
- package/dist/material-icons/svelte_js.clone.svg +1 -0
- package/dist/material-icons/svelte_ts.clone.svg +1 -0
- package/dist/material-icons/svg.svg +1 -0
- package/dist/material-icons/svgo.svg +1 -0
- package/dist/material-icons/svgr.svg +1 -0
- package/dist/material-icons/swagger.svg +1 -0
- package/dist/material-icons/sway.svg +1 -0
- package/dist/material-icons/swc.svg +1 -0
- package/dist/material-icons/swift.svg +1 -0
- package/dist/material-icons/syncpack.svg +1 -0
- package/dist/material-icons/systemd.svg +1 -0
- package/dist/material-icons/systemd_light.svg +1 -0
- package/dist/material-icons/table.svg +1 -0
- package/dist/material-icons/tailwindcss.svg +1 -0
- package/dist/material-icons/tape.clone.svg +1 -0
- package/dist/material-icons/taskfile.svg +1 -0
- package/dist/material-icons/tauri.svg +1 -0
- package/dist/material-icons/taze.svg +1 -0
- package/dist/material-icons/tcl.svg +1 -0
- package/dist/material-icons/teal.svg +1 -0
- package/dist/material-icons/templ.svg +1 -0
- package/dist/material-icons/template.svg +1 -0
- package/dist/material-icons/terraform.svg +1 -0
- package/dist/material-icons/test-js.svg +1 -0
- package/dist/material-icons/test-jsx.svg +1 -0
- package/dist/material-icons/test-ts.svg +1 -0
- package/dist/material-icons/tex.svg +1 -0
- package/dist/material-icons/textlint.svg +1 -0
- package/dist/material-icons/tilt.svg +1 -0
- package/dist/material-icons/tldraw.svg +1 -0
- package/dist/material-icons/tldraw_light.svg +1 -0
- package/dist/material-icons/tobi.svg +1 -0
- package/dist/material-icons/tobimake.svg +1 -0
- package/dist/material-icons/toc.svg +1 -0
- package/dist/material-icons/todo.svg +1 -0
- package/dist/material-icons/toml.svg +1 -0
- package/dist/material-icons/toml_light.svg +1 -0
- package/dist/material-icons/toon.svg +1 -0
- package/dist/material-icons/travis.svg +1 -0
- package/dist/material-icons/tree.svg +1 -0
- package/dist/material-icons/trigger.svg +1 -0
- package/dist/material-icons/tsconfig.svg +1 -0
- package/dist/material-icons/tsdoc.svg +1 -0
- package/dist/material-icons/tsdown.svg +1 -0
- package/dist/material-icons/tsil.svg +1 -0
- package/dist/material-icons/tune.svg +1 -0
- package/dist/material-icons/turborepo.svg +1 -0
- package/dist/material-icons/turborepo_light.svg +1 -0
- package/dist/material-icons/twig.svg +1 -0
- package/dist/material-icons/twine.svg +1 -0
- package/dist/material-icons/typedoc.svg +1 -0
- package/dist/material-icons/typescript-def.svg +1 -0
- package/dist/material-icons/typescript.svg +1 -0
- package/dist/material-icons/typst.svg +1 -0
- package/dist/material-icons/uiua.svg +1 -0
- package/dist/material-icons/umi.svg +1 -0
- package/dist/material-icons/uml.svg +1 -0
- package/dist/material-icons/uml_light.svg +1 -0
- package/dist/material-icons/unity.svg +1 -0
- package/dist/material-icons/unlicense.svg +1 -0
- package/dist/material-icons/unocss.svg +1 -0
- package/dist/material-icons/url.svg +1 -0
- package/dist/material-icons/uv.svg +1 -0
- package/dist/material-icons/vagrant.svg +1 -0
- package/dist/material-icons/vala.svg +1 -0
- package/dist/material-icons/vanilla-extract.svg +1 -0
- package/dist/material-icons/varnish.svg +1 -0
- package/dist/material-icons/vedic.svg +1 -0
- package/dist/material-icons/velite.svg +1 -0
- package/dist/material-icons/velocity.svg +1 -0
- package/dist/material-icons/vercel.svg +1 -0
- package/dist/material-icons/vercel_light.svg +1 -0
- package/dist/material-icons/verdaccio.svg +1 -0
- package/dist/material-icons/verified.svg +1 -0
- package/dist/material-icons/verilog.svg +1 -0
- package/dist/material-icons/verse.svg +1 -0
- package/dist/material-icons/verse_light.svg +1 -0
- package/dist/material-icons/vfl.svg +1 -0
- package/dist/material-icons/video.svg +1 -0
- package/dist/material-icons/vim.svg +1 -0
- package/dist/material-icons/virtual.svg +1 -0
- package/dist/material-icons/visualstudio.svg +1 -0
- package/dist/material-icons/vite.svg +1 -0
- package/dist/material-icons/vitest.svg +1 -0
- package/dist/material-icons/vlang.svg +1 -0
- package/dist/material-icons/vscode.svg +1 -0
- package/dist/material-icons/vue-config.svg +1 -0
- package/dist/material-icons/vue.svg +1 -0
- package/dist/material-icons/vuex-store.svg +1 -0
- package/dist/material-icons/wakatime.svg +1 -0
- package/dist/material-icons/wakatime_light.svg +1 -0
- package/dist/material-icons/wallaby.svg +1 -0
- package/dist/material-icons/wally.svg +1 -0
- package/dist/material-icons/warp.svg +1 -0
- package/dist/material-icons/warp_light.svg +1 -0
- package/dist/material-icons/watchman.svg +1 -0
- package/dist/material-icons/webassembly.svg +1 -0
- package/dist/material-icons/webhint.svg +1 -0
- package/dist/material-icons/webpack.svg +1 -0
- package/dist/material-icons/wepy.svg +1 -0
- package/dist/material-icons/werf.svg +1 -0
- package/dist/material-icons/windicss.svg +1 -0
- package/dist/material-icons/wolframlanguage.svg +1 -0
- package/dist/material-icons/word.svg +1 -0
- package/dist/material-icons/wrangler.svg +1 -0
- package/dist/material-icons/wxt.svg +1 -0
- package/dist/material-icons/xaml.svg +1 -0
- package/dist/material-icons/xmake.svg +1 -0
- package/dist/material-icons/xml.svg +1 -0
- package/dist/material-icons/yaml.svg +1 -0
- package/dist/material-icons/yang.svg +1 -0
- package/dist/material-icons/yarn.svg +1 -0
- package/dist/material-icons/zeabur.svg +1 -0
- package/dist/material-icons/zeabur_light.svg +1 -0
- package/dist/material-icons/zig.svg +1 -0
- package/dist/material-icons/zip.svg +1 -0
- package/dist/theme-init.js +10 -0
- package/docs/architecture.md +311 -0
- package/docs/configuration.md +141 -0
- package/docs/deployment.md +117 -0
- package/docs/security-upgrade.md +35 -0
- package/package.json +81 -4
- package/runtime/server/src/app.js +71 -0
- package/runtime/server/src/config/config.js +173 -0
- package/runtime/server/src/lib/concurrency.js +44 -0
- package/runtime/server/src/lib/errors.js +39 -0
- package/runtime/server/src/lib/http-range.js +27 -0
- package/runtime/server/src/lib/shell-quote.js +14 -0
- package/runtime/server/src/lib/validation.js +11 -0
- package/runtime/server/src/main.js +70 -0
- package/runtime/server/src/modules/auth/auth-security.js +104 -0
- package/runtime/server/src/modules/auth/auth-service.js +96 -0
- package/runtime/server/src/modules/auth/auth.routes.js +108 -0
- package/runtime/server/src/modules/auth/login-limiter.js +40 -0
- package/runtime/server/src/modules/auth/password.js +29 -0
- package/runtime/server/src/modules/auth/session-tokens.js +90 -0
- package/runtime/server/src/modules/commit-message/commit-message-generator.js +203 -0
- package/runtime/server/src/modules/commit-message/occ-config.js +53 -0
- package/runtime/server/src/modules/exec/command-runner.js +91 -0
- package/runtime/server/src/modules/filesystem/file-system-driver.js +1 -0
- package/runtime/server/src/modules/filesystem/local-driver.js +95 -0
- package/runtime/server/src/modules/filesystem/restricted-driver.js +114 -0
- package/runtime/server/src/modules/filesystem/sftp-driver.js +105 -0
- package/runtime/server/src/modules/filesystem/workspace-file-service.js +328 -0
- package/runtime/server/src/modules/filesystem/workspace-path.js +31 -0
- package/runtime/server/src/modules/git/git-parsers.js +229 -0
- package/runtime/server/src/modules/git/git-service.js +597 -0
- package/runtime/server/src/modules/git/git.routes.js +68 -0
- package/runtime/server/src/modules/hosts/directory-browser.js +36 -0
- package/runtime/server/src/modules/hosts/host-service.js +260 -0
- package/runtime/server/src/modules/hosts/host.routes.js +31 -0
- package/runtime/server/src/modules/hosts/key-installer.js +58 -0
- package/runtime/server/src/modules/ssh/host-key-probe.js +64 -0
- package/runtime/server/src/modules/ssh/host-key-verifier.js +153 -0
- package/runtime/server/src/modules/ssh/ssh-config.js +1 -0
- package/runtime/server/src/modules/ssh/ssh-connection-manager.js +190 -0
- package/runtime/server/src/modules/ssh/ssh-connection.js +93 -0
- package/runtime/server/src/modules/store/app-store.js +138 -0
- package/runtime/server/src/modules/terminal/output-buffer.js +54 -0
- package/runtime/server/src/modules/terminal/pty.js +1 -0
- package/runtime/server/src/modules/terminal/ssh-pty-provider.js +91 -0
- package/runtime/server/src/modules/terminal/terminal-manager.js +70 -0
- package/runtime/server/src/modules/terminal/terminal-session.js +124 -0
- package/runtime/server/src/modules/terminal/terminal-socket.js +170 -0
- package/runtime/server/src/modules/terminal/terminal.routes.js +19 -0
- package/runtime/server/src/modules/workspace/workspace-registry.js +231 -0
- package/runtime/server/src/modules/workspace/workspace.routes.js +97 -0
- package/runtime/server/src/scripts/reset-password.js +21 -0
- package/runtime/server/src/services.js +35 -0
- package/runtime/src/schema/api.js +30 -0
- package/runtime/src/schema/auth.js +20 -0
- package/runtime/src/schema/git.js +233 -0
- package/runtime/src/schema/hosts.js +115 -0
- package/runtime/src/schema/terminal.js +48 -0
- package/runtime/src/schema/workspace.js +151 -0
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { AppError } from "../../lib/errors.js";
|
|
3
|
+
import { normalizeWorkspacePath } from "../filesystem/workspace-path.js";
|
|
4
|
+
import { isBinaryDiff, LOG_FORMAT, parseLog, parseNameStatus, parseNumstat, parsePorcelainV2, splitDiffHunks } from "./git-parsers.js";
|
|
5
|
+
const STATUS_MAX_BYTES = 16 * 1024 * 1024;
|
|
6
|
+
// Nested repositories: how deep to look below the project folder, how many to report,
|
|
7
|
+
// and directories that never hold the user's own repositories but can be huge.
|
|
8
|
+
const NESTED_MAX_DEPTH = 6;
|
|
9
|
+
const NESTED_MAX_REPOSITORIES = 30;
|
|
10
|
+
const NESTED_SKIP_DIRS = ['node_modules', '.venv', 'venv', '.cache', '.next', '.nuxt', '__pycache__', 'Pods', 'target', 'vendor', '.terraform'];
|
|
11
|
+
const NESTED_CACHE_MS = 15_000;
|
|
12
|
+
// Global options for every invocation:
|
|
13
|
+
// - --literal-pathspecs: file names are never interpreted as glob/magic pathspecs.
|
|
14
|
+
// - core.quotepath=off: keep non-ASCII names verbatim in human-readable diff headers.
|
|
15
|
+
// - --no-pager: never block on a pager.
|
|
16
|
+
const GIT_BASE = ['git', '--no-pager', '--literal-pathspecs', '-c', 'core.quotepath=off', '-c', 'color.ui=false'];
|
|
17
|
+
// `git stash` uses pathspec magic internally (with --literal-pathspecs, `stash -u` saves
|
|
18
|
+
// untracked files but leaves them in place). Stash commands never take user paths.
|
|
19
|
+
const STASH_BASE = GIT_BASE.filter((arg) => arg !== '--literal-pathspecs');
|
|
20
|
+
// Avoid taking optional index locks so status never contends with Git
|
|
21
|
+
// commands the user is running in a terminal at the same time.
|
|
22
|
+
const GIT_ENV = { GIT_OPTIONAL_LOCKS: '0', GIT_TERMINAL_PROMPT: '0' };
|
|
23
|
+
// --no-ext-diff/--no-textconv: never run repository-configured helper programs.
|
|
24
|
+
const DIFF_FLAGS = ['--no-color', '--no-ext-diff', '--no-textconv'];
|
|
25
|
+
// Commits can run hooks (lint, tests), so give them longer than inspection commands.
|
|
26
|
+
const COMMIT_TIMEOUT_MS = 120_000;
|
|
27
|
+
// Pull, push, fetch: remote round-trips plus hooks (pre-push).
|
|
28
|
+
const NETWORK_TIMEOUT_MS = 180_000;
|
|
29
|
+
// Never let a repository or remote opt into transports that run commands.
|
|
30
|
+
const NETWORK_FLAGS = ['-c', 'protocol.ext.allow=never', '-c', 'protocol.fd.allow=never'];
|
|
31
|
+
// Credentials embedded in remote URLs (https://user:token@host) must never reach the browser.
|
|
32
|
+
const stripCredentials = (text) => text.replace(/([a-z][a-z0-9+.-]*:\/\/)[^/@\s]+@/gi, '$1');
|
|
33
|
+
/** The Git subcommand in an argument list (skipping `-c name=value` pairs). */
|
|
34
|
+
const commandName = (args) => args.find((arg, index) => !arg.startsWith('-') && args[index - 1] !== '-c') ?? '';
|
|
35
|
+
/** The most useful line of Git's stderr: fatal/error lines beat progress and "To <url>" chatter. */
|
|
36
|
+
function errorSummary(stderr) {
|
|
37
|
+
const lines = stderr.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
38
|
+
const line = lines.find((entry) => /^(fatal|error):/i.test(entry)) ?? lines.find((entry) => entry.startsWith('! ')) ?? lines[0] ?? '';
|
|
39
|
+
return stripCredentials(line);
|
|
40
|
+
}
|
|
41
|
+
// occ's default: diffs beyond this are cut before they reach an AI backend.
|
|
42
|
+
const COMMIT_CONTEXT_MAX_DIFF = 10_000;
|
|
43
|
+
/**
|
|
44
|
+
* Git through the native Git CLI: inspection plus staging and committing. All
|
|
45
|
+
* commands are argv vectors handed to a CommandRunner; paths are validated and
|
|
46
|
+
* always passed after `--`, so no user input is ever interpreted as an option or a pattern.
|
|
47
|
+
*/
|
|
48
|
+
export class GitService {
|
|
49
|
+
#runner;
|
|
50
|
+
#options;
|
|
51
|
+
#nested = null;
|
|
52
|
+
constructor(runner, options) {
|
|
53
|
+
this.#runner = runner;
|
|
54
|
+
this.#options = options;
|
|
55
|
+
}
|
|
56
|
+
async #git(cwd, args, maxOutputBytes, okExitCodes = [0], timeoutMs, base = GIT_BASE, input) {
|
|
57
|
+
const result = await this.#runner.run([...base, ...args], { cwd, env: GIT_ENV, maxOutputBytes, timeoutMs, input });
|
|
58
|
+
if (result.exitCode === 127)
|
|
59
|
+
throw new AppError('GIT_ERROR', 'Git is not installed on the workspace host.');
|
|
60
|
+
// A truncated read stops the process early, so its exit status is meaningless.
|
|
61
|
+
const failed = !result.stdoutTruncated && (result.exitCode === null || !okExitCodes.includes(result.exitCode));
|
|
62
|
+
if (failed) {
|
|
63
|
+
if (/not a git repository/i.test(result.stderr))
|
|
64
|
+
throw new AppError('NOT_A_REPOSITORY', 'The workspace is not a Git repository.');
|
|
65
|
+
if (/please tell me who you are|empty ident name/i.test(result.stderr)) {
|
|
66
|
+
throw new AppError('GIT_ERROR', 'Git has no author identity on the workspace host: set user.name and user.email with git config.');
|
|
67
|
+
}
|
|
68
|
+
if (/dubious ownership/i.test(result.stderr)) {
|
|
69
|
+
throw new AppError('GIT_ERROR', 'Git refused the repository because of "dubious ownership" (see git config safe.directory).');
|
|
70
|
+
}
|
|
71
|
+
if (/^CONFLICT/m.test(result.stdout.toString('utf8'))) {
|
|
72
|
+
throw new AppError('GIT_ERROR', 'There are merge conflicts. Resolve them, stage the files, then commit (or abort).');
|
|
73
|
+
}
|
|
74
|
+
throw new AppError('GIT_ERROR', `git ${commandName(args)} failed: ${errorSummary(result.stderr)}`.trim());
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
/** The repository containing the workspace root, if any (it may start above the root). */
|
|
79
|
+
async #findRepository() {
|
|
80
|
+
try {
|
|
81
|
+
const result = await this.#git(this.#options.workspaceRoot, ['rev-parse', '--show-toplevel', '--show-prefix'], 64 * 1024);
|
|
82
|
+
const [topLevel = '', prefix = ''] = result.stdout.toString('utf8').split('\n');
|
|
83
|
+
return { path: '', topLevel, prefix };
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof AppError && error.code === 'NOT_A_REPOSITORY')
|
|
87
|
+
return null;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Workspace-relative directories below the root that contain a `.git` entry
|
|
93
|
+
* (nested clones, submodules, worktrees). `find` never follows symlinks, so
|
|
94
|
+
* results stay inside the workspace. Cached briefly: status refreshes are frequent.
|
|
95
|
+
*/
|
|
96
|
+
#discoverNested() {
|
|
97
|
+
if (this.#nested && Date.now() - this.#nested.at < NESTED_CACHE_MS)
|
|
98
|
+
return this.#nested.result;
|
|
99
|
+
const skip = NESTED_SKIP_DIRS.flatMap((name, index) => (index === 0 ? ['-name', name] : ['-o', '-name', name]));
|
|
100
|
+
const argv = ['find', '.', '-maxdepth', String(NESTED_MAX_DEPTH + 1), '(', ...skip, ')', '-prune', '-o', '-name', '.git', '-print0', '-prune'];
|
|
101
|
+
const result = this.#runner
|
|
102
|
+
.run(argv, { cwd: this.#options.workspaceRoot, maxOutputBytes: 1024 * 1024, timeoutMs: 15_000 })
|
|
103
|
+
.then((output) => {
|
|
104
|
+
// find exits 1 when some directories are unreadable but still prints what it found.
|
|
105
|
+
if (output.exitCode !== 0 && output.exitCode !== 1 && !output.stdoutTruncated)
|
|
106
|
+
return { paths: [], truncated: false };
|
|
107
|
+
const paths = output.stdout
|
|
108
|
+
.toString('utf8')
|
|
109
|
+
.split('\0')
|
|
110
|
+
.filter((entry) => entry.startsWith('./') && entry !== './.git')
|
|
111
|
+
.map((entry) => path.posix.dirname(entry.slice(2)))
|
|
112
|
+
.filter((entry) => entry !== '.' && !entry.split('/').includes('..'))
|
|
113
|
+
.sort((a, b) => a.localeCompare(b));
|
|
114
|
+
return { paths: paths.slice(0, NESTED_MAX_REPOSITORIES), truncated: output.stdoutTruncated || paths.length > NESTED_MAX_REPOSITORIES };
|
|
115
|
+
})
|
|
116
|
+
.catch(() => ({ paths: [], truncated: false }));
|
|
117
|
+
this.#nested = { at: Date.now(), result };
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A nested repository by workspace-relative path. Git silently walks up to a
|
|
122
|
+
* parent repository when a `.git` entry is invalid, so the top level must be
|
|
123
|
+
* exactly the requested directory (this also rejects paths through symlinks).
|
|
124
|
+
*/
|
|
125
|
+
async #nestedRepository(relativePath) {
|
|
126
|
+
const expected = path.posix.join(this.#options.workspaceRoot, relativePath);
|
|
127
|
+
try {
|
|
128
|
+
const result = await this.#git(expected, ['rev-parse', '--show-toplevel'], 64 * 1024);
|
|
129
|
+
const topLevel = result.stdout.toString('utf8').split('\n')[0] ?? '';
|
|
130
|
+
return topLevel === expected ? { path: relativePath, topLevel, prefix: '' } : null;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
#toWorkspacePath(repository, repoPath) {
|
|
137
|
+
if (repository.path !== '')
|
|
138
|
+
return `${repository.path}/${repoPath}`;
|
|
139
|
+
if (repository.prefix === '')
|
|
140
|
+
return repoPath;
|
|
141
|
+
return repoPath.startsWith(repository.prefix) ? repoPath.slice(repository.prefix.length) : null;
|
|
142
|
+
}
|
|
143
|
+
async #repositoryStatus(repository) {
|
|
144
|
+
const [statusResult, unstagedStats, stagedStats] = await Promise.all([
|
|
145
|
+
this.#git(repository.topLevel, ['status', '--porcelain=v2', '--branch', '-z', '--untracked-files=all'], STATUS_MAX_BYTES),
|
|
146
|
+
this.#git(repository.topLevel, ['diff', '--numstat', '-z', ...DIFF_FLAGS], STATUS_MAX_BYTES),
|
|
147
|
+
this.#git(repository.topLevel, ['diff', '--cached', '--numstat', '-z', ...DIFF_FLAGS], STATUS_MAX_BYTES),
|
|
148
|
+
]);
|
|
149
|
+
const parsed = parsePorcelainV2(statusResult.stdout.toString('utf8'));
|
|
150
|
+
const unstagedCounts = parseNumstat(unstagedStats.stdout.toString('utf8'));
|
|
151
|
+
const stagedCounts = parseNumstat(stagedStats.stdout.toString('utf8'));
|
|
152
|
+
const truncated = statusResult.stdoutTruncated || parsed.changes.length > this.#options.maxChanges;
|
|
153
|
+
const changes = parsed.changes.slice(0, this.#options.maxChanges).map((change) => {
|
|
154
|
+
const counts = change.area === 'staged' ? stagedCounts.get(change.path) : change.area === 'unstaged' ? unstagedCounts.get(change.path) : undefined;
|
|
155
|
+
return {
|
|
156
|
+
...change,
|
|
157
|
+
workspacePath: this.#toWorkspacePath(repository, change.path),
|
|
158
|
+
additions: counts?.additions ?? null,
|
|
159
|
+
deletions: counts?.deletions ?? null,
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
path: repository.path,
|
|
164
|
+
branch: parsed.branch,
|
|
165
|
+
detached: parsed.detached,
|
|
166
|
+
commit: parsed.commit ? parsed.commit.slice(0, 12) : null,
|
|
167
|
+
upstream: parsed.upstream,
|
|
168
|
+
ahead: parsed.ahead,
|
|
169
|
+
behind: parsed.behind,
|
|
170
|
+
changes,
|
|
171
|
+
truncated,
|
|
172
|
+
error: null,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Status of the project's repository and of every repository nested inside the project folder. */
|
|
176
|
+
async status() {
|
|
177
|
+
const [root, nested] = await Promise.all([this.#findRepository(), this.#discoverNested()]);
|
|
178
|
+
const nestedRepositories = (await Promise.all(nested.paths.map((relativePath) => this.#nestedRepository(relativePath)))).filter((repository) => repository !== null);
|
|
179
|
+
const repositories = [...(root ? [root] : []), ...nestedRepositories];
|
|
180
|
+
const statuses = await Promise.all(repositories.map((repository) => this.#repositoryStatus(repository).catch((error) => {
|
|
181
|
+
// One unreadable repository (e.g. "dubious ownership") must not hide the others.
|
|
182
|
+
if (repository === root)
|
|
183
|
+
throw error;
|
|
184
|
+
return {
|
|
185
|
+
path: repository.path,
|
|
186
|
+
branch: null,
|
|
187
|
+
detached: false,
|
|
188
|
+
commit: null,
|
|
189
|
+
upstream: null,
|
|
190
|
+
ahead: 0,
|
|
191
|
+
behind: 0,
|
|
192
|
+
changes: [],
|
|
193
|
+
truncated: false,
|
|
194
|
+
error: error instanceof AppError ? error.message : 'Could not read this repository.',
|
|
195
|
+
};
|
|
196
|
+
})));
|
|
197
|
+
// A nested clone appears in its parent as one untracked folder; its own section shows the details.
|
|
198
|
+
const nestedFolders = new Set(nestedRepositories.map((repository) => `${repository.path}/`));
|
|
199
|
+
for (const status of statuses) {
|
|
200
|
+
status.changes = status.changes.filter((change) => !(change.area === 'untracked' && change.workspacePath && nestedFolders.has(change.workspacePath)));
|
|
201
|
+
}
|
|
202
|
+
return { repositories: statuses, repositoriesTruncated: nested.truncated };
|
|
203
|
+
}
|
|
204
|
+
/** The project's repository ('') or a verified nested one. */
|
|
205
|
+
async #repository(repo) {
|
|
206
|
+
const repoPath = normalizeWorkspacePath(repo ?? '');
|
|
207
|
+
const repository = repoPath === '' ? await this.#findRepository() : await this.#nestedRepository(repoPath);
|
|
208
|
+
if (!repository)
|
|
209
|
+
throw new AppError('NOT_A_REPOSITORY', 'Not a Git repository.');
|
|
210
|
+
return { repoPath, repository };
|
|
211
|
+
}
|
|
212
|
+
/** Resolve a commit id to its full hash; never passes unverified input on to other commands. */
|
|
213
|
+
async #commit(repository, commit) {
|
|
214
|
+
if (!/^[0-9a-f]{7,64}$/.test(commit))
|
|
215
|
+
throw new AppError('BAD_REQUEST', 'Invalid commit.');
|
|
216
|
+
const result = await this.#runner.run([...GIT_BASE, 'rev-list', '--parents', '-n', '1', `${commit}^{commit}`, '--'], {
|
|
217
|
+
cwd: repository.topLevel,
|
|
218
|
+
env: GIT_ENV,
|
|
219
|
+
maxOutputBytes: 64 * 1024,
|
|
220
|
+
});
|
|
221
|
+
const [hash, ...parents] = result.stdout.toString('utf8').trim().split(' ');
|
|
222
|
+
if (result.exitCode !== 0 || !hash)
|
|
223
|
+
throw new AppError('NOT_FOUND', 'Commit not found.');
|
|
224
|
+
return { hash, parents };
|
|
225
|
+
}
|
|
226
|
+
async #optional(cwd, args) {
|
|
227
|
+
const result = await this.#runner.run([...GIT_BASE, ...args], { cwd, env: GIT_ENV, maxOutputBytes: 64 * 1024 });
|
|
228
|
+
const value = result.stdout.toString('utf8').trim();
|
|
229
|
+
return result.exitCode === 0 && value ? value : null;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Commit history for the graph, newest first in topological order (as VS Code's Git
|
|
233
|
+
* extension requests it). By default the current branch and its upstream; `all` adds
|
|
234
|
+
* every branch, remote branch, and tag.
|
|
235
|
+
*/
|
|
236
|
+
async log(query) {
|
|
237
|
+
const { repository } = await this.#repository(query.repo);
|
|
238
|
+
const limit = query.limit;
|
|
239
|
+
const [head, headRef] = await Promise.all([
|
|
240
|
+
this.#optional(repository.topLevel, ['rev-parse', '--verify', '--quiet', 'HEAD^{commit}']),
|
|
241
|
+
this.#optional(repository.topLevel, ['symbolic-ref', '-q', 'HEAD']),
|
|
242
|
+
]);
|
|
243
|
+
if (!head)
|
|
244
|
+
return { items: [], hasMore: false, head: null, headRef, upstreamRef: null };
|
|
245
|
+
const upstreamRef = headRef ? await this.#optional(repository.topLevel, ['for-each-ref', '--format=%(upstream)', headRef]) : null;
|
|
246
|
+
const revisions = query.all ? ['--branches', '--remotes', '--tags', 'HEAD'] : ['HEAD', ...(upstreamRef ? [upstreamRef] : [])];
|
|
247
|
+
const result = await this.#git(repository.topLevel, ['log', `--format=${LOG_FORMAT}`, '-z', '--topo-order', '--decorate=full', '-n', String(limit + 1), ...revisions, '--'], STATUS_MAX_BYTES);
|
|
248
|
+
const items = parseLog(result.stdout.toString('utf8'));
|
|
249
|
+
return { items: items.slice(0, limit), hasMore: items.length > limit || result.stdoutTruncated, head, headRef, upstreamRef };
|
|
250
|
+
}
|
|
251
|
+
/** One commit with the files it changed against its first parent. */
|
|
252
|
+
async commitDetails(query) {
|
|
253
|
+
const { repository } = await this.#repository(query.repo);
|
|
254
|
+
const { hash, parents } = await this.#commit(repository, query.commit);
|
|
255
|
+
const [first] = parents;
|
|
256
|
+
// Root commits are compared with the empty tree.
|
|
257
|
+
const range = first ? [first, hash] : ['--root', hash];
|
|
258
|
+
const [info, nameStatus, numstat] = await Promise.all([
|
|
259
|
+
this.#git(repository.topLevel, ['log', `--format=${LOG_FORMAT}`, '-z', '--decorate=full', '-n', '1', hash, '--'], 1024 * 1024),
|
|
260
|
+
this.#git(repository.topLevel, ['diff-tree', '-r', '-M', '--no-commit-id', '--name-status', '-z', ...range, '--'], STATUS_MAX_BYTES),
|
|
261
|
+
this.#git(repository.topLevel, ['diff-tree', '-r', '-M', '--no-commit-id', '--numstat', '-z', ...range, '--'], STATUS_MAX_BYTES),
|
|
262
|
+
]);
|
|
263
|
+
const item = parseLog(info.stdout.toString('utf8'))[0];
|
|
264
|
+
if (!item)
|
|
265
|
+
throw new AppError('NOT_FOUND', 'Commit not found.');
|
|
266
|
+
const counts = parseNumstat(numstat.stdout.toString('utf8'));
|
|
267
|
+
const entries = parseNameStatus(nameStatus.stdout.toString('utf8'));
|
|
268
|
+
const files = entries.slice(0, this.#options.maxChanges).map((entry) => ({
|
|
269
|
+
...entry,
|
|
270
|
+
additions: counts.get(entry.path)?.additions ?? null,
|
|
271
|
+
deletions: counts.get(entry.path)?.deletions ?? null,
|
|
272
|
+
}));
|
|
273
|
+
return { ...item, files, truncated: nameStatus.stdoutTruncated || entries.length > this.#options.maxChanges };
|
|
274
|
+
}
|
|
275
|
+
/** Diff of one file in a commit, against the commit's first parent. */
|
|
276
|
+
async commitDiff(query) {
|
|
277
|
+
const { repoPath, repository } = await this.#repository(query.repo);
|
|
278
|
+
const { hash, parents } = await this.#commit(repository, query.commit);
|
|
279
|
+
const filePath = normalizeWorkspacePath(query.path);
|
|
280
|
+
const origPath = query.origPath ? normalizeWorkspacePath(query.origPath) : null;
|
|
281
|
+
if (filePath === '')
|
|
282
|
+
throw new AppError('BAD_REQUEST', 'A file path is required.');
|
|
283
|
+
const paths = ['--', ...(origPath ? [origPath] : []), filePath];
|
|
284
|
+
const [first] = parents;
|
|
285
|
+
const args = first ? ['diff', '-M', ...DIFF_FLAGS, first, hash, ...paths] : ['show', '--format=', '-M', ...DIFF_FLAGS, hash, ...paths];
|
|
286
|
+
const result = await this.#git(repository.topLevel, args, this.#options.maxDiffBytes);
|
|
287
|
+
const diff = result.stdout.toString('utf8');
|
|
288
|
+
return { repo: repoPath, commit: hash, path: filePath, diff, binary: isBinaryDiff(diff), truncated: result.stdoutTruncated };
|
|
289
|
+
}
|
|
290
|
+
async diff(query) {
|
|
291
|
+
const { repoPath, repository } = await this.#repository(query.repo);
|
|
292
|
+
// Paths are repository-relative; the same normalization rules forbid escaping the repository.
|
|
293
|
+
const filePath = normalizeWorkspacePath(query.path);
|
|
294
|
+
const origPath = query.origPath ? normalizeWorkspacePath(query.origPath) : null;
|
|
295
|
+
if (filePath === '')
|
|
296
|
+
throw new AppError('BAD_REQUEST', 'A file path is required.');
|
|
297
|
+
let args;
|
|
298
|
+
let okExitCodes = [0];
|
|
299
|
+
switch (query.area) {
|
|
300
|
+
case 'staged':
|
|
301
|
+
args = ['diff', '--cached', '-M', ...DIFF_FLAGS, '--', ...(origPath ? [origPath] : []), filePath];
|
|
302
|
+
break;
|
|
303
|
+
case 'unstaged':
|
|
304
|
+
case 'conflicted':
|
|
305
|
+
args = ['diff', ...DIFF_FLAGS, '--', filePath];
|
|
306
|
+
break;
|
|
307
|
+
case 'untracked':
|
|
308
|
+
// --no-index exits 1 when the files differ, which is always the case here.
|
|
309
|
+
args = ['diff', '--no-index', ...DIFF_FLAGS, '--', '/dev/null', filePath];
|
|
310
|
+
okExitCodes = [0, 1];
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
const result = await this.#git(repository.topLevel, args, this.#options.maxDiffBytes, okExitCodes);
|
|
314
|
+
const diff = result.stdout.toString('utf8');
|
|
315
|
+
return { repo: repoPath, path: filePath, area: query.area, diff, binary: isBinaryDiff(diff), truncated: result.stdoutTruncated };
|
|
316
|
+
}
|
|
317
|
+
/** Repository-relative paths, validated like every other path. */
|
|
318
|
+
#paths(paths) {
|
|
319
|
+
const normalized = paths.map((entry) => normalizeWorkspacePath(entry));
|
|
320
|
+
if (normalized.some((entry) => entry === ''))
|
|
321
|
+
throw new AppError('BAD_REQUEST', 'A file path is required.');
|
|
322
|
+
return [...new Set(normalized)];
|
|
323
|
+
}
|
|
324
|
+
async #hasHead(repository) {
|
|
325
|
+
return (await this.#optional(repository.topLevel, ['rev-parse', '--verify', '--quiet', 'HEAD^{commit}'])) !== null;
|
|
326
|
+
}
|
|
327
|
+
async #hasStagedChanges(repository) {
|
|
328
|
+
// --quiet exits 1 when there are differences.
|
|
329
|
+
const result = await this.#git(repository.topLevel, ['diff', '--cached', '--quiet', ...DIFF_FLAGS], 64 * 1024, [0, 1]);
|
|
330
|
+
return result.exitCode === 1;
|
|
331
|
+
}
|
|
332
|
+
/** `git add` the paths, including deletions. */
|
|
333
|
+
async stage(repo, paths) {
|
|
334
|
+
const { repository } = await this.#repository(repo);
|
|
335
|
+
await this.#git(repository.topLevel, ['add', '-A', '--', ...this.#paths(paths)], 64 * 1024);
|
|
336
|
+
}
|
|
337
|
+
/** Remove the paths from the index, keeping the working tree. */
|
|
338
|
+
async unstage(repo, paths) {
|
|
339
|
+
const { repository } = await this.#repository(repo);
|
|
340
|
+
const files = this.#paths(paths);
|
|
341
|
+
// Before the first commit there is no HEAD to restore from: drop the entries from the index instead.
|
|
342
|
+
const args = (await this.#hasHead(repository)) ? ['restore', '--staged', '--', ...files] : ['rm', '--cached', '-r', '-q', '--ignore-unmatch', '--', ...files];
|
|
343
|
+
await this.#git(repository.topLevel, args, 64 * 1024);
|
|
344
|
+
}
|
|
345
|
+
/** "Discard Changes": tracked files go back to their staged (or committed) content, untracked files are deleted. */
|
|
346
|
+
async discard(repo, paths) {
|
|
347
|
+
const { repository } = await this.#repository(repo);
|
|
348
|
+
const files = this.#paths(paths);
|
|
349
|
+
const listed = await this.#git(repository.topLevel, ['ls-files', '-z', '--', ...files], STATUS_MAX_BYTES);
|
|
350
|
+
const tracked = new Set(listed.stdout.toString('utf8').split('\0'));
|
|
351
|
+
const restore = files.filter((file) => tracked.has(file));
|
|
352
|
+
const remove = files.filter((file) => !tracked.has(file));
|
|
353
|
+
if (restore.length > 0)
|
|
354
|
+
await this.#git(repository.topLevel, ['restore', '--worktree', '--', ...restore], 64 * 1024);
|
|
355
|
+
if (remove.length > 0)
|
|
356
|
+
await this.#git(repository.topLevel, ['clean', '-f', '-q', '--', ...remove], 64 * 1024);
|
|
357
|
+
}
|
|
358
|
+
/** "Discard Block": reverse-apply one hunk of a file's working-tree diff, but only if the diff still contains it. */
|
|
359
|
+
async discardHunk(repo, filePath, hunk) {
|
|
360
|
+
const { repository } = await this.#repository(repo);
|
|
361
|
+
const [file = ''] = this.#paths([filePath]);
|
|
362
|
+
const result = await this.#git(repository.topLevel, ['diff', ...DIFF_FLAGS, '--', file], this.#options.maxDiffBytes);
|
|
363
|
+
if (result.stdoutTruncated)
|
|
364
|
+
throw new AppError('BAD_REQUEST', 'This diff is too large to discard part of it. Discard the whole file instead.');
|
|
365
|
+
const { header, hunks } = splitDiffHunks(result.stdout.toString('utf8'));
|
|
366
|
+
const wanted = hunk.replace(/\n$/, '');
|
|
367
|
+
if (!hunks.includes(wanted))
|
|
368
|
+
throw new AppError('CONFLICT', 'The file changed since the diff was shown. Refresh and try again.');
|
|
369
|
+
await this.#git(repository.topLevel, ['apply', '-R', '--whitespace=nowarn', '-'], 64 * 1024, [0], undefined, GIT_BASE, `${header}${wanted}\n`);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Commit the index (or, with `stageAll` and an empty index, every change). `all` stages
|
|
373
|
+
* everything first; `amend` rewrites the last commit (keeping its message when `message`
|
|
374
|
+
* is empty). Hooks run as usual.
|
|
375
|
+
*/
|
|
376
|
+
async commit(repo, message, stageAll, { all = false, amend = false, signoff = false } = {}) {
|
|
377
|
+
const { repoPath, repository } = await this.#repository(repo);
|
|
378
|
+
if (amend && !(await this.#hasHead(repository)))
|
|
379
|
+
throw new AppError('BAD_REQUEST', 'There is no commit to amend yet.');
|
|
380
|
+
if (all)
|
|
381
|
+
await this.#git(repository.topLevel, ['add', '-A'], 64 * 1024);
|
|
382
|
+
if (!amend && !(await this.#hasStagedChanges(repository))) {
|
|
383
|
+
if (!stageAll && !all)
|
|
384
|
+
throw new AppError('BAD_REQUEST', 'There are no staged changes to commit.');
|
|
385
|
+
await this.#git(repository.topLevel, ['add', '-A'], 64 * 1024);
|
|
386
|
+
if (!(await this.#hasStagedChanges(repository)))
|
|
387
|
+
throw new AppError('BAD_REQUEST', 'There are no changes to commit.');
|
|
388
|
+
}
|
|
389
|
+
if (!amend && message === '')
|
|
390
|
+
throw new AppError('BAD_REQUEST', 'Enter a commit message.');
|
|
391
|
+
const args = ['commit', '--quiet', ...(amend ? ['--amend'] : []), ...(signoff ? ['--signoff'] : []), ...(message === '' ? ['--no-edit'] : ['-m', message])];
|
|
392
|
+
await this.#git(repository.topLevel, args, 1024 * 1024, [0], COMMIT_TIMEOUT_MS);
|
|
393
|
+
const commit = await this.#optional(repository.topLevel, ['rev-parse', 'HEAD']);
|
|
394
|
+
return { repo: repoPath, commit: commit ?? '' };
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* What an AI backend needs to describe the pending commit, gathered the way occ does:
|
|
398
|
+
* the staged diff (or, with nothing staged, the working tree plus untracked file names) and the branch.
|
|
399
|
+
*/
|
|
400
|
+
async commitMessageContext(repo) {
|
|
401
|
+
const { repository } = await this.#repository(repo);
|
|
402
|
+
const cwd = repository.topLevel;
|
|
403
|
+
const staged = await this.#hasStagedChanges(repository);
|
|
404
|
+
const [diffResult, untracked, branch] = await Promise.all([
|
|
405
|
+
this.#git(cwd, ['diff', ...(staged ? ['--cached'] : []), ...DIFF_FLAGS], COMMIT_CONTEXT_MAX_DIFF + 1),
|
|
406
|
+
staged ? null : this.#git(cwd, ['ls-files', '--others', '--exclude-standard', '-z'], 1024 * 1024),
|
|
407
|
+
this.#optional(cwd, ['branch', '--show-current']),
|
|
408
|
+
]);
|
|
409
|
+
let diff = diffResult.stdout.toString('utf8');
|
|
410
|
+
if (diff.length > COMMIT_CONTEXT_MAX_DIFF || diffResult.stdoutTruncated)
|
|
411
|
+
diff = `${diff.slice(0, COMMIT_CONTEXT_MAX_DIFF)}\n... (truncated)`;
|
|
412
|
+
const newFiles = untracked?.stdout.toString('utf8').split('\0').filter(Boolean) ?? [];
|
|
413
|
+
if (newFiles.length > 0)
|
|
414
|
+
diff += `${diff ? '\n\n' : ''}New untracked files:\n${newFiles.slice(0, 200).join('\n')}`;
|
|
415
|
+
if (diff.trim() === '')
|
|
416
|
+
throw new AppError('BAD_REQUEST', 'There are no changes to describe.');
|
|
417
|
+
return { branch: branch ?? 'HEAD', diff };
|
|
418
|
+
}
|
|
419
|
+
/** Branches, remotes, tags, and stashes, for the pickers of the "..." menu. */
|
|
420
|
+
async refs(repo) {
|
|
421
|
+
const { repository } = await this.#repository(repo);
|
|
422
|
+
const cwd = repository.topLevel;
|
|
423
|
+
const [refs, remotes, tags, stashes] = await Promise.all([
|
|
424
|
+
this.#git(cwd, ['for-each-ref', '--format=%(refname)%00%(HEAD)%00%(upstream:short)', 'refs/heads', 'refs/remotes'], STATUS_MAX_BYTES),
|
|
425
|
+
this.#git(cwd, ['remote', '-v'], 1024 * 1024),
|
|
426
|
+
this.#git(cwd, ['for-each-ref', '--sort=-creatordate', '--format=%(refname:strip=2)', 'refs/tags'], STATUS_MAX_BYTES),
|
|
427
|
+
this.#git(cwd, ['stash', 'list', '--format=%H%x00%gs'], 1024 * 1024),
|
|
428
|
+
]);
|
|
429
|
+
const branches = refs.stdout
|
|
430
|
+
.toString('utf8')
|
|
431
|
+
.split('\n')
|
|
432
|
+
.filter(Boolean)
|
|
433
|
+
.map((line) => {
|
|
434
|
+
const [ref = '', head = '', upstream = ''] = line.split('\0');
|
|
435
|
+
const remote = ref.startsWith('refs/remotes/');
|
|
436
|
+
return { name: ref.slice(remote ? 'refs/remotes/'.length : 'refs/heads/'.length), remote, current: head === '*', upstream: upstream || null };
|
|
437
|
+
})
|
|
438
|
+
// origin/HEAD is a pointer, not a branch.
|
|
439
|
+
.filter((branch) => !(branch.remote && branch.name.endsWith('/HEAD')));
|
|
440
|
+
const remoteUrls = new Map();
|
|
441
|
+
for (const line of remotes.stdout.toString('utf8').split('\n')) {
|
|
442
|
+
const match = /^(\S+)\t(.*) \(fetch\)$/.exec(line);
|
|
443
|
+
if (match?.[1])
|
|
444
|
+
remoteUrls.set(match[1], match[2] ? stripCredentials(match[2]) : null);
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
branches,
|
|
448
|
+
remotes: [...remoteUrls].map(([name, url]) => ({ name, url })),
|
|
449
|
+
tags: tags.stdout.toString('utf8').split('\n').filter(Boolean),
|
|
450
|
+
stashes: stashes.stdout
|
|
451
|
+
.toString('utf8')
|
|
452
|
+
.split('\n')
|
|
453
|
+
.filter(Boolean)
|
|
454
|
+
.map((line, index) => {
|
|
455
|
+
const [hash = '', message = ''] = line.split('\0');
|
|
456
|
+
return { index, hash, message };
|
|
457
|
+
}),
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
async #currentBranch(repository) {
|
|
461
|
+
const branch = await this.#optional(repository.topLevel, ['branch', '--show-current']);
|
|
462
|
+
if (!branch)
|
|
463
|
+
throw new AppError('BAD_REQUEST', 'Not on a branch (detached HEAD).');
|
|
464
|
+
return branch;
|
|
465
|
+
}
|
|
466
|
+
async #checkRefFormat(repository, name) {
|
|
467
|
+
const result = await this.#runner.run([...GIT_BASE, 'check-ref-format', '--branch', name], { cwd: repository.topLevel, env: GIT_ENV, maxOutputBytes: 64 * 1024 });
|
|
468
|
+
if (result.exitCode !== 0)
|
|
469
|
+
throw new AppError('BAD_REQUEST', `"${name}" is not a valid name.`);
|
|
470
|
+
}
|
|
471
|
+
/** The "..." menu and the sync button: one fixed argv per operation, names validated by the schema and Git. */
|
|
472
|
+
async operation(operation) {
|
|
473
|
+
const { repository } = await this.#repository(operation.repo);
|
|
474
|
+
const cwd = repository.topLevel;
|
|
475
|
+
const run = (args, okExitCodes = [0]) => this.#git(cwd, args, 1024 * 1024, okExitCodes, COMMIT_TIMEOUT_MS);
|
|
476
|
+
const stash = (args) => this.#git(cwd, ['stash', ...args], 1024 * 1024, [0], COMMIT_TIMEOUT_MS, STASH_BASE);
|
|
477
|
+
const network = (args) => this.#git(cwd, [...NETWORK_FLAGS, ...args], 1024 * 1024, [0], NETWORK_TIMEOUT_MS);
|
|
478
|
+
let commitMessage = null;
|
|
479
|
+
switch (operation.op) {
|
|
480
|
+
case 'fetch':
|
|
481
|
+
await network(['fetch', ...(operation.mode === 'prune' ? ['--prune'] : operation.mode === 'all' ? ['--all'] : [])]);
|
|
482
|
+
break;
|
|
483
|
+
case 'pull':
|
|
484
|
+
if (operation.branch && !operation.remote)
|
|
485
|
+
throw new AppError('BAD_REQUEST', 'Choose a remote to pull from.');
|
|
486
|
+
await network(['pull', '--no-edit', ...(operation.rebase ? ['--rebase'] : []), ...(operation.remote ? [operation.remote] : []), ...(operation.branch ? [operation.branch] : [])]);
|
|
487
|
+
break;
|
|
488
|
+
case 'push': {
|
|
489
|
+
if (operation.remote) {
|
|
490
|
+
await network(['push', operation.remote, await this.#currentBranch(repository)]);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
const branch = await this.#currentBranch(repository);
|
|
494
|
+
const upstream = await this.#optional(cwd, ['rev-parse', '--abbrev-ref', `${branch}@{upstream}`]);
|
|
495
|
+
if (!upstream)
|
|
496
|
+
throw new AppError('BAD_REQUEST', `The branch "${branch}" has no upstream. Publish it first.`);
|
|
497
|
+
await network(['push']);
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
case 'publish':
|
|
501
|
+
await network(['push', '--set-upstream', operation.remote, await this.#currentBranch(repository)]);
|
|
502
|
+
break;
|
|
503
|
+
case 'sync':
|
|
504
|
+
await network(['pull', '--no-edit']);
|
|
505
|
+
await network(['push']);
|
|
506
|
+
break;
|
|
507
|
+
case 'checkout':
|
|
508
|
+
if (!operation.remote) {
|
|
509
|
+
await run(['switch', operation.ref]);
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
{
|
|
513
|
+
const slash = operation.ref.indexOf('/');
|
|
514
|
+
const local = slash > 0 ? operation.ref.slice(slash + 1) : '';
|
|
515
|
+
if (!local)
|
|
516
|
+
throw new AppError('BAD_REQUEST', 'Choose a remote branch such as origin/main.');
|
|
517
|
+
const exists = await this.#optional(cwd, ['rev-parse', '--verify', '--quiet', `refs/heads/${local}`]);
|
|
518
|
+
await run(exists ? ['switch', local] : ['switch', '--create', local, '--track', `refs/remotes/${operation.ref}`]);
|
|
519
|
+
}
|
|
520
|
+
break;
|
|
521
|
+
case 'createBranch':
|
|
522
|
+
await this.#checkRefFormat(repository, operation.name);
|
|
523
|
+
await run(['switch', '--create', operation.name, ...(operation.from ? [operation.from] : [])]);
|
|
524
|
+
break;
|
|
525
|
+
case 'renameBranch':
|
|
526
|
+
await this.#checkRefFormat(repository, operation.name);
|
|
527
|
+
await run(['branch', '--move', await this.#currentBranch(repository), operation.name]);
|
|
528
|
+
break;
|
|
529
|
+
case 'deleteBranch':
|
|
530
|
+
await run(['branch', operation.force ? '-D' : '-d', operation.name]);
|
|
531
|
+
break;
|
|
532
|
+
case 'deleteRemoteBranch':
|
|
533
|
+
await network(['push', operation.remote, '--delete', `refs/heads/${operation.name}`]);
|
|
534
|
+
break;
|
|
535
|
+
case 'merge':
|
|
536
|
+
await run(['merge', '--no-edit', operation.ref]);
|
|
537
|
+
break;
|
|
538
|
+
case 'rebase':
|
|
539
|
+
await run(['rebase', operation.ref]);
|
|
540
|
+
break;
|
|
541
|
+
case 'abortRebase':
|
|
542
|
+
await run(['rebase', '--abort']);
|
|
543
|
+
break;
|
|
544
|
+
case 'undoCommit': {
|
|
545
|
+
if (!(await this.#hasHead(repository)))
|
|
546
|
+
throw new AppError('BAD_REQUEST', 'There is no commit to undo.');
|
|
547
|
+
commitMessage = (await this.#optional(cwd, ['log', '-1', '--format=%B', 'HEAD'])) ?? null;
|
|
548
|
+
// Like VS Code: keep the changes staged; the first commit has no parent to reset to.
|
|
549
|
+
const parent = await this.#optional(cwd, ['rev-parse', '--verify', '--quiet', 'HEAD~1^{commit}']);
|
|
550
|
+
await run(parent ? ['reset', '--soft', 'HEAD~1'] : ['update-ref', '-d', 'HEAD']);
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
case 'stageAll':
|
|
554
|
+
await run(['add', '-A']);
|
|
555
|
+
break;
|
|
556
|
+
case 'unstageAll':
|
|
557
|
+
await run((await this.#hasHead(repository)) ? ['reset', '-q'] : ['rm', '--cached', '-r', '-q', '--ignore-unmatch', '--', '.']);
|
|
558
|
+
break;
|
|
559
|
+
case 'discardAll':
|
|
560
|
+
// Staged changes stay; tracked files go back to the index, untracked files (not ignored ones) are deleted.
|
|
561
|
+
await run(['restore', '--worktree', '--', '.'], [0, 1]);
|
|
562
|
+
await run(['clean', '-f', '-d', '-q', '--', '.']);
|
|
563
|
+
break;
|
|
564
|
+
case 'addRemote':
|
|
565
|
+
await run(['remote', 'add', operation.name, operation.url]);
|
|
566
|
+
break;
|
|
567
|
+
case 'removeRemote':
|
|
568
|
+
await run(['remote', 'remove', operation.name]);
|
|
569
|
+
break;
|
|
570
|
+
case 'stash': {
|
|
571
|
+
const mode = operation.mode === 'untracked' ? ['--include-untracked'] : operation.mode === 'staged' ? ['--staged'] : [];
|
|
572
|
+
await stash(['push', ...mode, ...(operation.message ? ['--message', operation.message] : [])]);
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
case 'stashApply':
|
|
576
|
+
await stash([operation.pop ? 'pop' : 'apply', ...(operation.index === undefined ? [] : [`stash@{${operation.index}}`])]);
|
|
577
|
+
break;
|
|
578
|
+
case 'stashDrop':
|
|
579
|
+
await stash(['drop', `stash@{${operation.index}}`]);
|
|
580
|
+
break;
|
|
581
|
+
case 'stashClear':
|
|
582
|
+
await stash(['clear']);
|
|
583
|
+
break;
|
|
584
|
+
case 'createTag':
|
|
585
|
+
await this.#checkRefFormat(repository, operation.name);
|
|
586
|
+
await run(operation.message ? ['tag', '--annotate', operation.name, '--message', operation.message] : ['tag', operation.name]);
|
|
587
|
+
break;
|
|
588
|
+
case 'deleteTag':
|
|
589
|
+
await run(['tag', '--delete', operation.name]);
|
|
590
|
+
break;
|
|
591
|
+
case 'deleteRemoteTag':
|
|
592
|
+
await network(['push', operation.remote, '--delete', `refs/tags/${operation.name}`]);
|
|
593
|
+
break;
|
|
594
|
+
}
|
|
595
|
+
return { commitMessage };
|
|
596
|
+
}
|
|
597
|
+
}
|