From 37715d9fa8155149fd4e920a11646c395c3f715e Mon Sep 17 00:00:00 2001 From: Jess Frazelle Date: Tue, 4 Mar 2025 22:21:12 -0800 Subject: [PATCH] Move lsp server to this repo (#5619) --- .eslintignore | 4 +- .github/actions/github-release/Dockerfile | 8 + .github/actions/github-release/README.md | 21 + .github/actions/github-release/action.yml | 15 + .github/actions/github-release/main.js | 143 + .github/actions/github-release/package.json | 10 + .github/dependabot.yml | 1 + .github/workflows/kcl-language-server.yml | 401 +++ .github/workflows/static-analysis.yml | 4 +- .gitignore | 12 +- .prettierignore | 2 +- ...-load---solid-2d-1-Google-Chrome-linux.png | Bin 51550 -> 51559 bytes package.json | 8 +- rust/.cargo/config.toml | 2 + rust/Cargo.lock | 471 +++- rust/Cargo.toml | 11 + rust/README.md | 3 +- rust/kcl-bumper/Cargo.toml | 2 +- rust/kcl-language-server-release/Cargo.toml | 26 + rust/kcl-language-server-release/src/build.rs | 247 ++ rust/kcl-language-server-release/src/main.rs | 157 ++ rust/kcl-language-server/Cargo.toml | 53 + rust/kcl-language-server/README.md | 101 + .../client/src/bootstrap.ts | 162 ++ rust/kcl-language-server/client/src/client.ts | 74 + .../client/src/commands.ts | 32 + rust/kcl-language-server/client/src/config.ts | 293 ++ rust/kcl-language-server/client/src/ctx.ts | 387 +++ .../kcl-language-server/client/src/lsp_ext.ts | 24 + rust/kcl-language-server/client/src/main.ts | 79 + .../client/src/persistent_state.ts | 21 + .../client/src/test/runTest.ts | 25 + .../client/src/test/suite/extension.test.ts | 16 + .../client/src/test/suite/index.ts | 33 + .../client/src/undefinable.ts | 23 + rust/kcl-language-server/client/src/util.ts | 240 ++ rust/kcl-language-server/icon.png | Bin 0 -> 23106 bytes rust/kcl-language-server/package.json | 151 + rust/kcl-language-server/src/main.rs | 180 ++ rust/kcl-language-server/tsconfig.json | 20 + rust/kcl-language-server/yarn.lock | 2476 +++++++++++++++++ rust/kcl-lib/Cargo.toml | 6 +- rust/kcl-lib/README.md | 2 - rust/kcl-lib/src/engine/conn.rs | 4 +- rust/kcl-python-bindings/Cargo.toml | 3 + tsconfig.json | 2 +- vite.config.ts | 2 +- 47 files changed, 5929 insertions(+), 28 deletions(-) create mode 100644 .github/actions/github-release/Dockerfile create mode 100644 .github/actions/github-release/README.md create mode 100644 .github/actions/github-release/action.yml create mode 100644 .github/actions/github-release/main.js create mode 100644 .github/actions/github-release/package.json create mode 100644 .github/workflows/kcl-language-server.yml create mode 100644 rust/.cargo/config.toml create mode 100644 rust/kcl-language-server-release/Cargo.toml create mode 100644 rust/kcl-language-server-release/src/build.rs create mode 100644 rust/kcl-language-server-release/src/main.rs create mode 100644 rust/kcl-language-server/Cargo.toml create mode 100644 rust/kcl-language-server/README.md create mode 100644 rust/kcl-language-server/client/src/bootstrap.ts create mode 100644 rust/kcl-language-server/client/src/client.ts create mode 100644 rust/kcl-language-server/client/src/commands.ts create mode 100644 rust/kcl-language-server/client/src/config.ts create mode 100644 rust/kcl-language-server/client/src/ctx.ts create mode 100644 rust/kcl-language-server/client/src/lsp_ext.ts create mode 100644 rust/kcl-language-server/client/src/main.ts create mode 100644 rust/kcl-language-server/client/src/persistent_state.ts create mode 100644 rust/kcl-language-server/client/src/test/runTest.ts create mode 100644 rust/kcl-language-server/client/src/test/suite/extension.test.ts create mode 100644 rust/kcl-language-server/client/src/test/suite/index.ts create mode 100644 rust/kcl-language-server/client/src/undefinable.ts create mode 100644 rust/kcl-language-server/client/src/util.ts create mode 100644 rust/kcl-language-server/icon.png create mode 100644 rust/kcl-language-server/package.json create mode 100644 rust/kcl-language-server/src/main.rs create mode 100644 rust/kcl-language-server/tsconfig.json create mode 100644 rust/kcl-language-server/yarn.lock diff --git a/.eslintignore b/.eslintignore index 9cf59f6c3..dab3af326 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,6 @@ -rust/* +rust/**/*.ts +!rust/kcl-language-server/client/src/**/*.ts *.typegen.ts packages/codemirror-lsp-client/dist/* e2e/playwright/snapshots/prompt-to-edit/* +.vscode-test diff --git a/.github/actions/github-release/Dockerfile b/.github/actions/github-release/Dockerfile new file mode 100644 index 000000000..5849eac7d --- /dev/null +++ b/.github/actions/github-release/Dockerfile @@ -0,0 +1,8 @@ +FROM node:slim + +COPY . /action +WORKDIR /action + +RUN npm install --production + +ENTRYPOINT ["node", "/action/main.js"] diff --git a/.github/actions/github-release/README.md b/.github/actions/github-release/README.md new file mode 100644 index 000000000..c8ff3ec6e --- /dev/null +++ b/.github/actions/github-release/README.md @@ -0,0 +1,21 @@ +# github-release + +Copy-pasted from +https://github.com/bytecodealliance/wasmtime/tree/8acfdbdd8aa550d1b84e0ce1e6222a6605d14e38/.github/actions/github-release + +An action used to publish GitHub releases for `wasmtime`. + +As of the time of this writing there's a few actions floating around which +perform github releases but they all tend to have their set of drawbacks. +Additionally nothing handles deleting releases which we need for our rolling +`dev` release. + +To handle all this, this action rolls its own implementation using the +actions/toolkit repository and packages published there. These run in a Docker +container and take various inputs to orchestrate the release from the build. + +More comments can be found in `main.js`. + +Testing this is really hard. If you want to try though run `npm install` and +then `node main.js`. You'll have to configure a bunch of env vars though to get +anything reasonably working. diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml new file mode 100644 index 000000000..4b7eeff5b --- /dev/null +++ b/.github/actions/github-release/action.yml @@ -0,0 +1,15 @@ +name: "wasmtime github releases" +description: "wasmtime github releases" +inputs: + token: + description: "" + required: true + name: + description: "" + required: true + files: + description: "" + required: true +runs: + using: "docker" + image: "Dockerfile" diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js new file mode 100644 index 000000000..30066dd06 --- /dev/null +++ b/.github/actions/github-release/main.js @@ -0,0 +1,143 @@ +const core = require("@actions/core"); +const path = require("path"); +const fs = require("fs"); +const github = require("@actions/github"); +const glob = require("glob"); + +function sleep(milliseconds) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)); +} + +async function runOnce() { + // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` + const files = core.getInput("files"); + const name = core.getInput("name"); + const token = core.getInput("token"); + const slug = process.env.GITHUB_REPOSITORY; + const owner = slug.split("/")[0]; + const repo = slug.split("/")[1]; + const sha = process.env.HEAD_SHA; + + core.info(`files: ${files}`); + core.info(`name: ${name}`); + + const options = { + request: { + timeout: 30000, + }, + }; + const octokit = github.getOctokit(token, options); + + // Delete the previous release since we can't overwrite one. This may happen + // due to retrying an upload or it may happen because we're doing the dev + // release. + const releases = await octokit.paginate("GET /repos/:owner/:repo/releases", { owner, repo }); + for (const release of releases) { + if (release.tag_name !== name) { + continue; + } + const release_id = release.id; + core.info(`deleting release ${release_id}`); + await octokit.rest.repos.deleteRelease({ owner, repo, release_id }); + } + + // We also need to update the `dev` tag while we're at it on the `dev` branch. + if (name == "nightly") { + try { + core.info(`updating nightly tag`); + await octokit.rest.git.updateRef({ + owner, + repo, + ref: "tags/nightly", + sha, + force: true, + }); + } catch (e) { + core.error(e); + core.info(`creating nightly tag`); + await octokit.rest.git.createTag({ + owner, + repo, + tag: "nightly", + message: "nightly release", + object: sha, + type: "commit", + }); + } + } + + // Creates an official GitHub release for this `tag`, and if this is `dev` + // then we know that from the previous block this should be a fresh release. + core.info(`creating a release`); + const release = await octokit.rest.repos.createRelease({ + owner, + repo, + name, + tag_name: name, + target_commitish: sha, + prerelease: name === "nightly", + }); + const release_id = release.data.id; + + // Upload all the relevant assets for this release as just general blobs. + for (const file of glob.sync(files)) { + const size = fs.statSync(file).size; + const name = path.basename(file); + + await runWithRetry(async function () { + // We can't overwrite assets, so remove existing ones from a previous try. + let assets = await octokit.rest.repos.listReleaseAssets({ + owner, + repo, + release_id, + }); + for (const asset of assets.data) { + if (asset.name === name) { + core.info(`delete asset ${name}`); + const asset_id = asset.id; + await octokit.rest.repos.deleteReleaseAsset({ owner, repo, asset_id }); + } + } + + core.info(`upload ${file}`); + const headers = { "content-length": size, "content-type": "application/octet-stream" }; + const data = fs.createReadStream(file); + await octokit.rest.repos.uploadReleaseAsset({ + data, + headers, + name, + url: release.data.upload_url, + }); + }); + } +} + +async function runWithRetry(f) { + const retries = 10; + const maxDelay = 4000; + let delay = 1000; + + for (let i = 0; i < retries; i++) { + try { + await f(); + break; + } catch (e) { + if (i === retries - 1) throw e; + + core.error(e); + const currentDelay = Math.round(Math.random() * delay); + core.info(`sleeping ${currentDelay} ms`); + await sleep(currentDelay); + delay = Math.min(delay * 2, maxDelay); + } + } +} + +async function run() { + await runWithRetry(runOnce); +} + +run().catch((err) => { + core.error(err); + core.setFailed(err.message); +}); diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json new file mode 100644 index 000000000..af4bf074d --- /dev/null +++ b/.github/actions/github-release/package.json @@ -0,0 +1,10 @@ +{ + "name": "wasmtime-github-release", + "version": "0.0.0", + "main": "main.js", + "dependencies": { + "@actions/core": "^1.6", + "@actions/github": "^5.0", + "glob": "^7.1.5" + } +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 299d2a1d5..46ddd527e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,7 @@ updates: - '/' - '/packages/codemirror-lang-kcl/' - '/packages/codemirror-lsp-client/' + - '/rust/kcl-language-server/' schedule: interval: weekly day: monday diff --git a/.github/workflows/kcl-language-server.yml b/.github/workflows/kcl-language-server.yml new file mode 100644 index 000000000..f77b73947 --- /dev/null +++ b/.github/workflows/kcl-language-server.yml @@ -0,0 +1,401 @@ +name: kcl-language-server +on: + push: + branches: + - main + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + - '**/rust-toolchain.toml' + - 'rust/kcl-language-server/**' + - '**.rs' + - .github/workflows/kcl-language-server.yml + tags: + - 'kcl-*' + pull_request: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + - '**/rust-toolchain.toml' + - 'rust/kcl-language-server/**' + - '**.rs' + - .github/workflows/kcl-language-server.yml + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: 0 + CARGO_NET_RETRY: 10 + RUSTFLAGS: "" + RUSTUP_MAX_RETRIES: 10 + FETCH_DEPTH: 0 # pull in the tags for the version string + MACOSX_DEPLOYMENT_TARGET: 10.15 + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc + +jobs: + test: + name: vscode tests + strategy: + fail-fast: false + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + - name: Install dependencies + run: | + yarn install + cd rust/kcl-language-server + yarn install + - name: Run tests + run: | + cd rust/kcl-language-server + yarn build + yarn test-compile + ls -la dist + xvfb-run -a yarn test + if: runner.os == 'Linux' + - name: Run tests + run: | + cd rust/kcl-language-server + yarn test + if: runner.os != 'Linux' + build-release: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + target: x86_64-pc-windows-msvc + code-target: + win32-x64 + #- os: windows-latest + #target: i686-pc-windows-msvc + #code-target: + #win32-ia32 + #- os: windows-latest + #target: aarch64-pc-windows-msvc + #code-target: win32-arm64 + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + code-target: + linux-x64 + #- os: ubuntu-latest + #target: aarch64-unknown-linux-musl + #code-target: linux-arm64 + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + code-target: linux-arm64 + - os: ubuntu-latest + target: arm-unknown-linux-gnueabihf + code-target: linux-armhf + - os: macos-latest + target: x86_64-apple-darwin + code-target: darwin-x64 + - os: macos-latest + target: aarch64-apple-darwin + code-target: darwin-arm64 + + name: build-release (${{ matrix.target }}) + runs-on: ${{ matrix.os }} + container: ${{ matrix.container }} + + env: + RA_TARGET: ${{ matrix.target }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: ${{ env.FETCH_DEPTH }} + + - name: Use correct Rust toolchain + shell: bash + run: | + rm rust/rust-toolchain.toml + + - name: Install rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + cache: rust + components: rust-src + target: ${{ matrix.target }} + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + + - name: Update apt repositories + if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest' + run: sudo apt-get update + + - if: ${{ matrix.os == 'ubuntu-latest' }} + name: Install deps + shell: bash + run: | + sudo apt install -y \ + ca-certificates \ + clang \ + cmake \ + curl \ + g++ \ + gcc \ + gcc-mingw-w64-i686 \ + gcc-mingw-w64 \ + jq \ + libmpc-dev \ + libmpfr-dev \ + libgmp-dev \ + libssl-dev \ + libxml2-dev \ + mingw-w64 \ + wget \ + zlib1g-dev + + cargo install cross + + - name: Install AArch64 target toolchain + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: sudo apt-get install gcc-aarch64-linux-gnu + + - name: Install ARM target toolchain + if: matrix.target == 'arm-unknown-linux-gnueabihf' + run: sudo apt-get install gcc-arm-linux-gnueabihf + + - name: build + run: | + cd rust + cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }} + + - name: Install dependencies + run: | + cd rust/kcl-language-server + yarn install + + - name: Package Extension (release) + if: startsWith(github.event.ref, 'refs/tags/') + run: | + cd rust/kcl-language-server + npx vsce package -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} + + - name: Package Extension (nightly) + if: startsWith(github.event.ref, 'refs/tags/') == false + run: | + cd rust/kcl-language-server + npx vsce package -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release + + - name: remove server + if: matrix.target == 'x86_64-unknown-linux-gnu' + run: | + cd rust/kcl-language-server + rm -rf server + + - name: Package Extension (no server, release) + if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') + run: | + cd rust/kcl-language-server + npx vsce package -o ../build/kcl-language-server-no-server.vsix + + - name: Package Extension (no server, nightly) + if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false + run: | + cd rust/kcl-language-server + npx vsce package -o ../build/kcl-language-server-no-server.vsix --pre-release + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: release-${{ matrix.target }} + path: ./rust/build + + build-release-x86_64-unknown-linux-musl: + name: build-release (x86_64-unknown-linux-musl) + runs-on: ubuntu-latest + env: + RA_TARGET: x86_64-unknown-linux-musl + # For some reason `-crt-static` is not working for clang without lld + RUSTFLAGS: "-C link-arg=-fuse-ld=lld -C target-feature=-crt-static" + container: + image: alpine:latest + volumes: + - /usr/local/cargo/registry:/usr/local/cargo/registry + + steps: + - name: Install dependencies + run: | + apk add --no-cache \ + bash \ + curl \ + git \ + clang \ + lld \ + musl-dev \ + nodejs \ + yarn \ + npm + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: ${{ env.FETCH_DEPTH }} + + - name: Use correct Rust toolchain + shell: bash + run: | + rm rust/rust-toolchain.toml + + - name: Install rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + cache: rust + components: rust-src + target: ${{ matrix.target }} + + - name: build + run: | + cd rust + cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }} + + - name: Install dependencies + run: | + cd rust/kcl-language-server + yarn install + + - name: Package Extension (release) + if: startsWith(github.event.ref, 'refs/tags/') + run: | + cd rust/kcl-language-server + npx vsce package -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 + + - name: Package Extension (release) + if: startsWith(github.event.ref, 'refs/tags/') == false + run: | + cd rust/kcl-language-server + npx vsce package -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: release-x86_64-unknown-linux-musl + path: ./rust/build + + publish: + name: publish + runs-on: ubuntu-latest + needs: ["build-release", "build-release-x86_64-unknown-linux-musl"] + if: startsWith(github.event.ref, 'refs/tags') + permissions: + contents: write + steps: + - run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - run: 'echo "TAG: $TAG"' + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: ${{ env.FETCH_DEPTH }} + + - name: Install Nodejs + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + + - run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV + - run: 'echo "HEAD_SHA: $HEAD_SHA"' + + - uses: actions/download-artifact@v4 + with: + name: release-aarch64-apple-darwin + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-x86_64-apple-darwin + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-x86_64-unknown-linux-gnu + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-x86_64-unknown-linux-musl + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-aarch64-unknown-linux-gnu + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-arm-unknown-linux-gnueabihf + path: rust/build + - uses: actions/download-artifact@v4 + with: + name: release-x86_64-pc-windows-msvc + path: + rust/build + #- uses: actions/download-artifact@v4 + #with: + #name: release-i686-pc-windows-msvc + #path: + #build + #- uses: actions/download-artifact@v4 + #with: + #name: release-aarch64-pc-windows-msvc + #path: rust/build + - run: ls -al ./rust/build + + - name: Publish Release + uses: ./.github/actions/github-release + with: + files: "rust/build/*" + name: ${{ env.TAG }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: move files to dir for upload + shell: bash + run: | + cd rust + mkdir -p releases/language-server/${{ env.TAG }} + cp -r build/* releases/language-server/${{ env.TAG }} + + - name: "Authenticate to Google Cloud" + uses: "google-github-actions/auth@v2.1.7" + with: + credentials_json: "${{ secrets.GOOGLE_CLOUD_DL_SA }}" + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v2.1.2 + with: + project_id: kittycadapi + - name: "upload files to gcp" + id: upload-files + uses: google-github-actions/upload-cloud-storage@v2.2.1 + with: + path: rust/releases + destination: dl.kittycad.io + + - run: rm rust/build/kcl-language-server-no-server.vsix + + - name: Publish Extension (Code Marketplace, release) + # token from https://dev.azure.com/kcl-language-server/ + run: | + cd rust/kcl-language-server + npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix + + - name: Publish Extension (OpenVSX, release) + run: | + cd rust/kcl-language-server + npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../build/kcl-language-server-*.vsix + timeout-minutes: 2 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index c1dc2d8b7..5342e009d 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -52,6 +52,7 @@ jobs: node-version-file: '.nvmrc' cache: 'yarn' - run: yarn install + - run: yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install - uses: Swatinem/rust-cache@v2 with: workspaces: './rust' @@ -72,6 +73,7 @@ jobs: node-version-file: '.nvmrc' cache: 'yarn' - run: yarn install + - run: yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install - run: yarn lint python-codespell: @@ -141,7 +143,7 @@ jobs: - name: run unit tests if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} - run: yarn test:unit + run: xvfb-run -a yarn test:unit env: VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} diff --git a/.gitignore b/.gitignore index 14ef0ac3d..dc11eb211 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies -/node_modules +node_modules /.pnp .pnp.js @@ -9,7 +9,7 @@ /coverage # production -/build +build # misc .DS_Store @@ -35,6 +35,10 @@ rust/lcov.info rust/kcl-wasm-lib/pkg *.snap.new rust/kcl-lib/fuzz/Cargo.lock +rust/kcl-language-server-release/Cargo.lock + +# kcl language server package +rust/kcl-language-server/dist/ e2e/playwright/playwright-secrets.env e2e/playwright/temp1.png @@ -71,5 +75,7 @@ out/ # python __pycache__/ uv.lock -rust/kcl-python-bindings/dist +dist venv + +.vscode-test diff --git a/.prettierignore b/.prettierignore index dbe88b0d2..4dea6fe02 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,10 +7,10 @@ coverage *.rs *.hbs target -rust/ e2e/playwright/export-snapshots e2e/playwright/snapshots/prompt-to-edit # XState generated files src/machines/**.typegen.ts +.vscode-test diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png index bff08b9bad8c6480d89379f11ce1075d803fb4bf..f834075e0ae273db023794681634ec311811077b 100644 GIT binary patch literal 51559 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 b_mk6edIm>*IFqHnI|Io`K~pLT!x#S#%0bUD literal 51550 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 diff --git a/package.json b/package.json index 86829c6b2..f34d6bc4a 100644 --- a/package.json +++ b/package.json @@ -87,8 +87,8 @@ "simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &", "simpleserver:bg": "yarn pretest && http-server ./public --cors -p 3000 &", "simpleserver:stop": "kill-port 3000", - "fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages", - "fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages", + "fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server", + "fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server", "fetch:wasm": "./scripts/get-latest-wasm-bundle.sh", "fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1", "fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/next/manifest.json", @@ -98,8 +98,8 @@ "build:wasm:windows": "yarn install:wasm-pack:cargo && yarn build:wasm:nocopy && ./scripts/copy-wasm.ps1 && yarn fmt", "remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"", "wasm-prep": "rimraf rust/kcl-wasm-lib/pkg && mkdirp rust/kcl-wasm-lib/pkg && rimraf rust/kcl-lib/bindings", - "lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src", - "lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src", + "lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src", + "lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src", "files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json", "files:set-notes": "./scripts/set-files-notes.sh", "files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh", diff --git a/rust/.cargo/config.toml b/rust/.cargo/config.toml new file mode 100644 index 000000000..875074992 --- /dev/null +++ b/rust/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +kcl-language-server-release = "run --manifest-path ./kcl-language-server-release/Cargo.toml --" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 175d73418..953d0b0ec 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -27,6 +27,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -361,6 +372,26 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "cast" version = "0.3.0" @@ -373,6 +404,8 @@ version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -442,6 +475,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.31" @@ -523,6 +566,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "convert_case" version = "0.8.0" @@ -557,6 +606,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -604,6 +668,15 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -713,6 +786,12 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +[[package]] +name = "deflate64" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" + [[package]] name = "deranged" version = "0.3.11" @@ -794,6 +873,28 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] @@ -899,9 +1000,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", @@ -1182,6 +1283,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.11" @@ -1564,6 +1674,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "insta" version = "1.42.1" @@ -1643,6 +1762,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -1683,6 +1811,47 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "kcl-language-server" +version = "0.2.45" +dependencies = [ + "anyhow", + "clap", + "dashmap 6.1.0", + "kcl-lib", + "kittycad", + "lazy_static", + "log", + "signal-hook", + "slog", + "slog-async", + "slog-json", + "slog-term", + "tokio", + "tower-lsp", + "tracing-subscriber", +] + +[[package]] +name = "kcl-language-server-release" +version = "0.1.45" +dependencies = [ + "anyhow", + "clap", + "flate2", + "lazy_static", + "log", + "slog", + "slog-async", + "slog-json", + "slog-term", + "time", + "tokio", + "tracing-subscriber", + "xshell", + "zip", +] + [[package]] name = "kcl-lib" version = "0.2.45" @@ -1930,6 +2099,16 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.8.0", + "libc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1959,10 +2138,16 @@ dependencies = [ ] [[package]] -name = "log" -version = "0.4.25" +name = "lockfree-object-pool" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + +[[package]] +name = "log" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" dependencies = [ "serde", ] @@ -1989,6 +2174,16 @@ dependencies = [ "url", ] +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + [[package]] name = "measurements" version = "0.11.0" @@ -2068,9 +2263,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", "simd-adler32", @@ -2118,6 +2313,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -2209,6 +2414,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "4.1.0" @@ -2299,6 +2510,16 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2408,6 +2629,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + [[package]] name = "plotters" version = "0.3.7" @@ -2747,6 +2974,17 @@ dependencies = [ "bitflags 2.8.0", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regex" version = "1.11.1" @@ -3197,12 +3435,31 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3233,6 +3490,49 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slog" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" + +[[package]] +name = "slog-async" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c8038f898a2c79507940990f05386455b3a317d8f18d4caea7cbc3d5096b84" +dependencies = [ + "crossbeam-channel", + "slog", + "take_mut", + "thread_local", +] + +[[package]] +name = "slog-json" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1e53f61af1e3c8b852eef0a9dee29008f55d6dd63794f3f12cef786cf0f219" +dependencies = [ + "serde", + "serde_json", + "slog", + "time", +] + +[[package]] +name = "slog-term" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e022d0b998abfe5c3782c1f03551a596269450ccd677ea51c56f8b214610e8" +dependencies = [ + "is-terminal", + "slog", + "term", + "thread_local", + "time", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -3410,6 +3710,12 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" @@ -3436,6 +3742,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -3511,6 +3828,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.37" @@ -3798,6 +4125,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] @@ -4004,6 +4370,12 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" @@ -4349,6 +4721,21 @@ dependencies = [ "tap", ] +[[package]] +name = "xshell" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d" +dependencies = [ + "xshell-macros", +] + +[[package]] +name = "xshell-macros" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -4435,6 +4822,20 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] [[package]] name = "zerovec" @@ -4464,11 +4865,67 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae9c1ea7b3a5e1f4b922ff856a129881167511563dc219869afe3787fc0c1a45" dependencies = [ + "aes", "arbitrary", + "bzip2", + "constant_time_eq", "crc32fast", "crossbeam-utils", + "deflate64", "displaydoc", + "flate2", + "hmac", "indexmap 2.7.1", + "lzma-rs", "memchr", + "pbkdf2", + "rand 0.8.5", + "sha1", "thiserror 2.0.11", + "time", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.14+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index bd6e696da..301e2e1fd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -3,6 +3,8 @@ resolver = "2" members = [ "kcl-bumper", "kcl-derive-docs", + "kcl-language-server", + "kcl-language-server-release", "kcl-lib", "kcl-python-bindings", "kcl-test-server", @@ -27,17 +29,26 @@ debug = "line-tables-only" [workspace.dependencies] async-trait = "0.1.85" anyhow = { version = "1" } +clap = { version = "4.5.31", features = ["derive"] } +dashmap = { version = "6.1.0" } http = "1" indexmap = "2.7.0" kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] } kittycad-modeling-cmds = { version = "0.2.100", features = ["ts-rs", "websocket"] } +lazy_static = "1.5.0" miette = "7.5.0" pyo3 = { version = "0.22.6" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1" } +slog = "2.7.0" +slog-async = "2.8.0" +slog-json = "2.6.1" +slog-term = "2.9.1" tokio = { version = "1" } tower-lsp = { version = "0.20.0", default-features = false } +tracing-subscriber = { version = "0.3.19", features = ["registry", "std", "fmt", "smallvec", "ansi", "tracing-log", "json"] } uuid = { version = "1", features = ["v4", "serde"] } +zip = { version = "2.2.2", default-features = false } [workspace.lints.clippy] assertions_on_result_states = "warn" diff --git a/rust/README.md b/rust/README.md index c5b361038..bb2744d7c 100644 --- a/rust/README.md +++ b/rust/README.md @@ -20,4 +20,5 @@ - This will publish the relevant crates and push a new tag with the prefix `kcl-`. DO NOT SET THE PREFIX TO `kcl-` when you run the command. The `just` command will do that for you. - - The tag will then trigger the release of kcl-python-bindings. + - The tag will then trigger the release of `kcl-python-bindings` and + `kcl-language-server`. diff --git a/rust/kcl-bumper/Cargo.toml b/rust/kcl-bumper/Cargo.toml index b1482fc8f..2a6760245 100644 --- a/rust/kcl-bumper/Cargo.toml +++ b/rust/kcl-bumper/Cargo.toml @@ -11,7 +11,7 @@ publish = false [dependencies] anyhow = { workspace = true } -clap = { version = "4.5.31", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } semver = "1.0.25" serde = { workspace = true } toml_edit = "0.22.16" diff --git a/rust/kcl-language-server-release/Cargo.toml b/rust/kcl-language-server-release/Cargo.toml new file mode 100644 index 000000000..2ef02f728 --- /dev/null +++ b/rust/kcl-language-server-release/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "kcl-language-server-release" +version = "0.1.45" +edition = "2021" +authors = ["KittyCAD Inc "] +publish = false +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = { workspace = true } +clap = { workspace = true, features = ["cargo", "derive", "env", "unicode"] } +flate2 = "1.1.0" +lazy_static = { workspace = true } +log = { version = "0.4.26", features = ["serde"] } +slog = { workspace = true } +slog-async = { workspace = true } +slog-json = { workspace = true } +slog-term = { workspace = true } +time = "0.3.37" +tokio = { workspace = true, features = ["full"] } +tracing-subscriber = { workspace = true } +xshell = "0.2.6" +zip = { workspace = true, features = ["default"] } + +[lints] +workspace = true diff --git a/rust/kcl-language-server-release/src/build.rs b/rust/kcl-language-server-release/src/build.rs new file mode 100644 index 000000000..32a0fba39 --- /dev/null +++ b/rust/kcl-language-server-release/src/build.rs @@ -0,0 +1,247 @@ +use std::{ + env, + fs::File, + io::{self, BufWriter}, + path::{Path, PathBuf}, +}; + +use anyhow::Result; +use clap::Parser; +use flate2::{write::GzEncoder, Compression}; +use time::OffsetDateTime; +use xshell::{cmd, Shell}; +use zip::ZipWriter; + +/// A subcommand for building and packaging a release. +#[derive(Parser, Clone, Debug)] +pub struct Build { + /// An optional client patch version to use. + #[clap(long = "client-patch-version", default_value = "None")] + pub client_patch_version: Option, +} + +impl Build { + pub(crate) fn run(&self, sh: &Shell) -> Result<()> { + let stable = sh + .var("GITHUB_REF") + .unwrap_or_default() + .as_str() + .contains("refs/tags/v"); + + let project_root = crate::project_root(); + let target = Target::get(&project_root); + let build = project_root.join("build"); + sh.remove_path(&build)?; + sh.create_dir(&build)?; + + // Read the version from our root Cargo.toml. + let version = sh.read_file("kcl-language-server/Cargo.toml")?; + let mut version = version + .lines() + .find(|line| line.starts_with("version = ")) + .unwrap_or_default() + .replace("version = ", "") + .replace(['\"', '\''], "") + .trim() + .to_string(); + + if !stable { + version = format!("{}-nightly", version); + } + + let release_tag = if stable { + // We already checked above if the env var contains "refs/tags/v". + // So this is safe to unwrap. + sh.var("GITHUB_REF") + .unwrap_or_default() + .replace("refs/tags/", "") + .to_string() + } else { + "nightly".to_string() + }; + + if stable && !release_tag.contains(&version) { + // bail early if the tag doesn't match the version + anyhow::bail!( + "Tag {} doesn't match version {}. Did you forget to update Cargo.toml?", + release_tag, + version + ); + } + + build_server(sh, &version, &target)?; + build_client(sh, &version, &release_tag, &target)?; + Ok(()) + } +} + +fn build_client(sh: &Shell, version: &str, release_tag: &str, target: &Target) -> anyhow::Result<()> { + let bundle_path = Path::new("server"); + sh.create_dir(bundle_path)?; + sh.copy_file(&target.server_path, bundle_path)?; + if let Some(symbols_path) = &target.symbols_path { + sh.copy_file(symbols_path, bundle_path)?; + } + + let mut patch = Patch::new(sh, "./kcl-language-server/package.json")?; + patch + .replace(r#""version": "0.0.0""#, &format!(r#""version": "{version}""#)) + .replace(r#""releaseTag": null"#, &format!(r#""releaseTag": "{release_tag}""#)) + .replace(r#""enabledApiProposals": [],"#, r#""#); + patch.commit(sh)?; + + Ok(()) +} + +fn build_server(sh: &Shell, release: &str, target: &Target) -> anyhow::Result<()> { + let _e = sh.push_env("CFG_RELEASE", release); + let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin"); + + // Uncomment to enable debug info for releases. Note that: + // * debug info is split on windows and macs, so it does nothing for those platforms, + // * on Linux, this blows up the binary size from 8MB to 43MB, which is unreasonable. + // let _e = sh.push_env("CARGO_PROFILE_RELEASE_DEBUG", "1"); + + if target.name.contains("-linux-") { + env::set_var("CC", "clang"); + } + + let target_name = &target.name; + cmd!( + sh, + "cargo build -p kcl-language-server --target {target_name} --release" + ) + .run()?; + + let dst = Path::new("build").join(&target.artifact_name); + gzip(&target.server_path, &dst.with_extension("gz"))?; + if target_name.contains("-windows-") { + zip( + &target.server_path, + target.symbols_path.as_ref(), + &dst.with_extension("zip"), + )?; + } + + Ok(()) +} + +fn gzip(src_path: &Path, dest_path: &Path) -> anyhow::Result<()> { + let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best()); + let mut input = io::BufReader::new(File::open(src_path)?); + io::copy(&mut input, &mut encoder)?; + encoder.finish()?; + Ok(()) +} + +fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> anyhow::Result<()> { + let file = File::create(dest_path)?; + let mut writer = ZipWriter::new(BufWriter::new(file)); + let file_options = zip::write::SimpleFileOptions::default() + .last_modified_time(convert_date_time(OffsetDateTime::from( + std::fs::metadata(src_path)?.modified()?, + ))?) + .unix_permissions(0o755) + .compression_method(zip::CompressionMethod::Deflated) + .compression_level(Some(9)); + writer.start_file(src_path.file_name().unwrap().to_str().unwrap(), file_options)?; + let mut input = io::BufReader::new(File::open(src_path)?); + io::copy(&mut input, &mut writer)?; + if let Some(symbols_path) = symbols_path { + writer.start_file(symbols_path.file_name().unwrap().to_str().unwrap(), file_options)?; + let mut input = io::BufReader::new(File::open(symbols_path)?); + io::copy(&mut input, &mut writer)?; + } + writer.finish()?; + Ok(()) +} + +struct Target { + name: String, + server_path: PathBuf, + symbols_path: Option, + artifact_name: String, +} + +impl Target { + fn get(project_root: &Path) -> Self { + let name = match env::var("RA_TARGET") { + Ok(target) => target, + _ => { + if cfg!(target_os = "linux") { + "x86_64-unknown-linux-gnu".to_string() + } else if cfg!(target_os = "windows") { + "x86_64-pc-windows-msvc".to_string() + } else if cfg!(target_os = "macos") { + "aarch64-apple-darwin".to_string() + } else { + panic!("Unsupported OS, maybe try setting RA_TARGET") + } + } + }; + let out_path = project_root.join("target").join(&name).join("release"); + let (exe_suffix, symbols_path) = if name.contains("-windows-") { + (".exe".into(), Some(out_path.join("kcl_language_server.pdb"))) + } else { + (String::new(), None) + }; + let server_path = out_path.join(format!("kcl-language-server{exe_suffix}")); + let artifact_name = format!("kcl-language-server-{name}{exe_suffix}"); + Self { + name, + server_path, + symbols_path, + artifact_name, + } + } +} + +struct Patch { + path: PathBuf, + original_contents: String, + contents: String, +} + +impl Patch { + fn new(sh: &Shell, path: impl Into) -> anyhow::Result { + let path = path.into(); + let contents = sh.read_file(&path)?; + Ok(Patch { + path, + original_contents: contents.clone(), + contents, + }) + } + + fn replace(&mut self, from: &str, to: &str) -> &mut Patch { + assert!(self.contents.contains(from)); + self.contents = self.contents.replace(from, to); + self + } + + fn commit(&self, sh: &Shell) -> anyhow::Result<()> { + sh.write_file(&self.path, &self.contents)?; + Ok(()) + } +} + +impl Drop for Patch { + fn drop(&mut self) { + // FIXME: find a way to bring this back + let _ = &self.original_contents; + // write_file(&self.path, &self.original_contents).unwrap(); + } +} + +fn convert_date_time(offset_dt: OffsetDateTime) -> anyhow::Result { + // Convert to MS-DOS date time format that the zip crate expects + zip::DateTime::from_date_and_time( + offset_dt.year() as u16, + offset_dt.month() as u8, + offset_dt.day(), + offset_dt.hour(), + offset_dt.minute(), + offset_dt.second(), + ) + .map_err(|err| anyhow::anyhow!("Failed to convert date time to MS-DOS format: {}", err)) +} diff --git a/rust/kcl-language-server-release/src/main.rs b/rust/kcl-language-server-release/src/main.rs new file mode 100644 index 000000000..ae2e2dce9 --- /dev/null +++ b/rust/kcl-language-server-release/src/main.rs @@ -0,0 +1,157 @@ +//! A release building tool and packager. + +#![deny(missing_docs)] + +/// A subcommand for building and packaging a release. +pub mod build; + +use std::{ + env, + path::{Path, PathBuf}, +}; + +use anyhow::{bail, Result}; +use clap::Parser; +use slog::Drain; +use tracing_subscriber::{prelude::*, Layer}; +use xshell::Shell; + +lazy_static::lazy_static! { +/// Initialize the logger. + // We need a slog::Logger for steno and when we export out the logs from re-exec-ed processes. + pub static ref LOGGER: slog::Logger = { + let decorator = slog_term::TermDecorator::new().build(); + let drain = slog_term::FullFormat::new(decorator).build().fuse(); + let drain = slog_async::Async::new(drain).build().fuse(); + slog::Logger::root(drain, slog::slog_o!()) + }; +} + +/// This doc string acts as a help message when the user runs '--help' +/// as do all doc strings on fields. +#[derive(Parser, Debug, Clone)] +#[clap(version = clap::crate_version!(), author = clap::crate_authors!("\n"))] +pub struct Opts { + /// Print debug info + #[clap(short, long)] + pub debug: bool, + + /// Print logs as json + #[clap(short, long)] + pub json: bool, + + /// The subcommand to run. + #[clap(subcommand)] + pub subcmd: SubCommand, +} + +impl Opts { + /// Setup our logger. + pub fn create_logger(&self) -> slog::Logger { + if self.json { + let drain = slog_json::Json::default(std::io::stderr()).fuse(); + self.async_root_logger(drain) + } else { + let decorator = slog_term::TermDecorator::new().build(); + let drain = slog_term::FullFormat::new(decorator).build().fuse(); + self.async_root_logger(drain) + } + } + + fn async_root_logger(&self, drain: T) -> slog::Logger + where + T: slog::Drain + Send + 'static, + ::Err: std::fmt::Debug, + { + let level = if self.debug { + slog::Level::Debug + } else { + slog::Level::Info + }; + + let level_drain = slog::LevelFilter(drain, level).fuse(); + let async_drain = slog_async::Async::new(level_drain).build().fuse(); + slog::Logger::root(async_drain, slog::o!()) + } +} + +/// A subcommand for our cli. +#[derive(Parser, Debug, Clone)] +pub enum SubCommand { + /// Build release packages. + Build(crate::build::Build), +} + +#[tokio::main] +async fn main() -> Result<()> { + let opts: Opts = Opts::parse(); + + let level_filter = if opts.debug { + tracing_subscriber::filter::LevelFilter::DEBUG + } else { + tracing_subscriber::filter::LevelFilter::INFO + }; + + // Format fields using the provided closure. + // We want to make this very consise otherwise the logs are not able to be read by humans. + let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| { + if format!("{}", field) == "message" { + write!(writer, "{}: {:?}", field, value) + } else { + write!(writer, "{}", field) + } + }) + // Separate each field with a comma. + // This method is provided by an extension trait in the + // `tracing-subscriber` prelude. + .delimited(", "); + + let (json, plain) = if opts.json { + // Cloud run likes json formatted logs if possible. + // See: https://cloud.google.com/run/docs/logging + // We could probably format these specifically for cloud run if we wanted, + // will save that as a TODO: https://cloud.google.com/run/docs/logging#special-fields + ( + Some(tracing_subscriber::fmt::layer().json().with_filter(level_filter)), + None, + ) + } else { + ( + None, + Some( + tracing_subscriber::fmt::layer() + .pretty() + .fmt_fields(format) + .with_filter(level_filter), + ), + ) + }; + + // Initialize the tracing. + tracing_subscriber::registry().with(json).with(plain).init(); + + if let Err(err) = run_cmd(&opts).await { + bail!("running cmd `{:?}` failed: {:?}", &opts.subcmd, err); + } + + Ok(()) +} + +async fn run_cmd(opts: &Opts) -> Result<()> { + let sh = &Shell::new()?; + sh.change_dir(project_root()); + + match &opts.subcmd { + SubCommand::Build(b) => b.run(sh)?, + } + + Ok(()) +} + +fn project_root() -> PathBuf { + Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned())) + .ancestors() + .nth(1) + .unwrap() + .to_path_buf() +} diff --git a/rust/kcl-language-server/Cargo.toml b/rust/kcl-language-server/Cargo.toml new file mode 100644 index 000000000..3db57a209 --- /dev/null +++ b/rust/kcl-language-server/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "kcl-language-server" +description = "A language server for KCL." +authors = ["KittyCAD Inc "] +version = "0.2.45" +edition = "2021" +license = "MIT" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "kcl-language-server" +path = "src/main.rs" + +[dependencies] +anyhow = { workspace = true } +clap = { workspace = true, features = ["cargo", "derive", "env", "unicode"] } +dashmap = { workspace = true } +kcl-lib = { path = "../kcl-lib", default-features = false, features = [ + "cli", + "engine", + "disable-println", +] } +kittycad = { workspace = true } +lazy_static = { workspace = true } +log = { version = "0.4.26", features = ["serde"] } +slog = { workspace = true } +slog-async = { workspace = true } +slog-json = { workspace = true } +slog-term = { workspace = true } +tracing-subscriber = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +signal-hook = "0.3.17" +tokio = { version = "1.43.0", features = ["full"] } +tower-lsp = { version = "0.20.0", features = ["proposed"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +tower-lsp = { version = "0.20.0", default-features = false, features = [ + "runtime-agnostic", +] } + +[lints] +workspace = true + +[profile.dev] +# Disabling debug info speeds up builds a bunch, +# and we don't rely on it for debugging that much. +debug = 0 + +[profile.release] +incremental = true +# Set this to 1 or 2 to get more useful backtraces in debugger. +debug = 0 diff --git a/rust/kcl-language-server/README.md b/rust/kcl-language-server/README.md new file mode 100644 index 000000000..c5a92ff78 --- /dev/null +++ b/rust/kcl-language-server/README.md @@ -0,0 +1,101 @@ +# kcl-lsp + +The `kcl` [Language Server Protocol](https://microsoft.github.io/language-server-protocol) +implementation and VSCode extension. + +This language server is a thin wrapper around the KCL language tooling library. +That is found in the [modeling-app](https://github.com/kittycad/modeling-app) repo, and published as +on crates.io as [kcl-lib](https://crates.io/crates/kcl-lib). + +## VSCode + +Install our extension: [KittyCAD Language Server](https://marketplace.visualstudio.com/items?itemName=KittyCAD.kcl-language-server) + +## Neovim + +You can add the following to your `vim` configuration if you are using `lspconfig`. + +This is [@jessfraz's +setup](https://github.com/jessfraz/.vim/blob/master/vimrc#L935). + +```vim +if executable('kcl-language-server') +lua << EOF +local lspconfig = require 'lspconfig' +local configs = require 'lspconfig.configs' + +if not configs.kcl_lsp then + configs.kcl_lsp = { + default_config = { + cmd = {'kcl-language-server', 'server', '--stdio'}, + filetypes = {'kcl'}, + root_dir = lspconfig.util.root_pattern('.git'), + single_file_support = true, + }, + docs = { + description = [=[ +https://github.com/KittyCAD/kcl-lsp +https://kittycad.io + +The KittyCAD Language Server Protocol implementation for the KCL language. + +To better detect kcl files, the following can be added: + + + vim.cmd [[ autocmd BufRead,BufNewFile *.kcl set filetype=kcl ]] + +]=], + default_config = { + root_dir = [[root_pattern(".git")]], + }, + } + } +end + +lspconfig.kcl_lsp.setup{} +EOF +else + echo "You might want to install kcl-language-server: https://github.com/KittyCAD/kcl-lsp/releases" +end +``` + +## Helix + +Add this to your `languages.toml` file. Remember to change `/Users/adamchalmers` to your path. + +Note that we don't currently have Treesitter parsers, so there won't be syntax highlighting. + +```toml +[[language]] +name = "kcl" +scope = "source.kcl" +injection-regex = "kcl" +file-types = ["kcl"] +comment-tokens = "//" +indent = { tab-width = 2, unit = " " } +language-servers = [ "kcl-lsp" ] +block-comment-tokens = { start = "/*", end = "*/"} + + +[language-server.kcl-lsp] +command = "/Users/adamchalmers/kc-repos/kcl-lsp/target/release/kcl-language-server" +args = ["server", "--stdio"] +``` + +## Development + +```bash +$ yarn install +$ cargo build +$ code . +``` + +Once VSCode opens, go to the "Run and Debug" panel (cmd-shift-D on MacOS), and choose Run Extension (Debug Build). +This opens a new VSCode window with our KCL extension installed. Open a KCL file and check that the LSP is working. + +- press F5 or change to the Debug panel and click Launch Client + +> **Note** +> +> If encountered errors like `Cannot find module '/xxx/xxx/dist/extension.js'` +> please try run command `tsc -b` manually diff --git a/rust/kcl-language-server/client/src/bootstrap.ts b/rust/kcl-language-server/client/src/bootstrap.ts new file mode 100644 index 000000000..02472bbf6 --- /dev/null +++ b/rust/kcl-language-server/client/src/bootstrap.ts @@ -0,0 +1,162 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as vscode from 'vscode' +import * as os from 'os' +import type { Config } from './config' +import { log, isValidExecutable } from './util' +import type { PersistentState } from './persistent_state' +import { exec } from 'child_process' + +export async function bootstrap( + context: vscode.ExtensionContext, + config: Config, + state: PersistentState +): Promise { + const path = await getServer(context, config, state) + if (!path) { + throw new Error( + 'KittyCAD Language Server is not available. ' + + 'Please, ensure its [proper installation](https://github.com/kittycad/kcl-lsp).' + ) + } + + log.info('Using server binary at', path) + + if (!isValidExecutable(path)) { + if (config.serverPath) { + throw new Error(`Failed to execute ${path} --version. \`config.server.path\` or \`config.serverPath\` has been set explicitly.\ + Consider removing this config or making a valid server binary available at that path.`) + } else { + throw new Error(`Failed to execute ${path} --version`) + } + } + + return path +} +async function getServer( + context: vscode.ExtensionContext, + config: Config, + state: PersistentState +): Promise { + const explicitPath = + process.env['__KCL_LSP_SERVER_DEBUG'] ?? config.serverPath + if (explicitPath) { + if (explicitPath.startsWith('~/')) { + return os.homedir() + explicitPath.slice('~'.length) + } + return explicitPath + } + if (config.package.releaseTag === null) return 'kcl-language-server' + + const ext = process.platform === 'win32' ? '.exe' : '' + const bundled = vscode.Uri.joinPath( + context.extensionUri, + 'server', + `kcl-language-server${ext}` + ) + log.info('Checking if bundled server exists at', bundled) + const bundledExists = await vscode.workspace.fs.stat(bundled).then( + () => true, + () => false + ) + log.info('Bundled server exists:', bundledExists) + if (bundledExists) { + let server = bundled + if (await isNixOs()) { + await vscode.workspace.fs.createDirectory(config.globalStorageUri).then() + const dest = vscode.Uri.joinPath( + config.globalStorageUri, + `kcl-language-server${ext}` + ) + let exists = await vscode.workspace.fs.stat(dest).then( + () => true, + () => false + ) + if (exists && config.package.version !== state.serverVersion) { + log.info( + 'Server version changed, removing old server binary', + config.package.version, + state.serverVersion + ) + await vscode.workspace.fs.delete(dest) + exists = false + } + if (!exists) { + await vscode.workspace.fs.copy(bundled, dest) + await patchelf(dest) + } + server = dest + } + + await state.updateServerVersion(config.package.version) + return server.fsPath + } + + await state.updateServerVersion(undefined) + await vscode.window.showErrorMessage( + "Unfortunately we don't ship binaries for your platform yet. " + + 'You need to manually clone the kcl-lsp repository and ' + + 'run `cargo install` to build the language server from sources. ' + + 'If you feel that your platform should be supported, please create an issue ' + + 'about that [here](https://github.com/kittycad/kcl-lsp/issues) and we ' + + 'will consider it.' + ) + return undefined +} + +async function isNixOs(): Promise { + try { + const contents = ( + await vscode.workspace.fs.readFile(vscode.Uri.file('/etc/os-release')) + ).toString() + const idString = + contents.split('\n').find((a) => a.startsWith('ID=')) || 'ID=linux' + return idString.indexOf('nixos') !== -1 + } catch { + return false + } +} + +async function patchelf(dest: vscode.Uri): Promise { + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: 'Patching kcl-language-server for NixOS', + }, + async (progress, _) => { + const expression = ` + {srcStr, pkgs ? import {}}: + pkgs.stdenv.mkDerivation { + name = "kcl-language-server"; + src = /. + srcStr; + phases = [ "installPhase" "fixupPhase" ]; + installPhase = "cp $src $out"; + fixupPhase = '' + chmod 755 $out + patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out + ''; + } + ` + const origFile = vscode.Uri.file(dest.fsPath + '-orig') + await vscode.workspace.fs.rename(dest, origFile, { overwrite: true }) + try { + progress.report({ message: 'Patching executable', increment: 20 }) + await new Promise((resolve, reject) => { + const handle = exec( + `nix-build -E - --argstr srcStr '${origFile.fsPath}' -o '${dest.fsPath}'`, + (err, stdout, stderr) => { + if (err != null) { + reject(Error(stderr)) + } else { + resolve(stdout) + } + } + ) + handle.stdin?.write(expression) + handle.stdin?.end() + }) + } finally { + await vscode.workspace.fs.delete(origFile) + } + } + ) +} diff --git a/rust/kcl-language-server/client/src/client.ts b/rust/kcl-language-server/client/src/client.ts new file mode 100644 index 000000000..968fe7d65 --- /dev/null +++ b/rust/kcl-language-server/client/src/client.ts @@ -0,0 +1,74 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as lc from 'vscode-languageclient/node' +import type * as vscode from 'vscode' + +export async function createClient( + traceOutputChannel: vscode.OutputChannel, + outputChannel: vscode.OutputChannel, + initializationOptions: vscode.WorkspaceConfiguration, + serverOptions: lc.ServerOptions +): Promise { + const clientOptions: lc.LanguageClientOptions = { + documentSelector: [{ scheme: 'file', language: 'kcl' }], + initializationOptions, + traceOutputChannel, + outputChannel, + middleware: { + workspace: { + // HACK: This is a workaround, when the client has been disposed, VSCode + // continues to emit events to the client and the default one for this event + // attempt to restart the client for no reason + async didChangeWatchedFile(event: any, next: any) { + if (client.isRunning()) { + await next(event) + } + }, + async configuration( + params: lc.ConfigurationParams, + token: vscode.CancellationToken, + next: lc.ConfigurationRequest.HandlerSignature + ) { + const resp = await next(params, token) + return resp + }, + }, + }, + } + + const client = new lc.LanguageClient( + 'kcl-language-server', + 'KittyCAD Language Server', + serverOptions, + clientOptions + ) + + client.registerFeature(new ExperimentalFeatures()) + + return client +} + +class ExperimentalFeatures implements lc.StaticFeature { + getState(): lc.FeatureState { + return { kind: 'static' } + } + fillClientCapabilities(capabilities: lc.ClientCapabilities): void { + capabilities.experimental = { + snippetTextEdit: true, + codeActionGroup: true, + hoverActions: true, + serverStatusNotification: true, + colorDiagnosticOutput: true, + openServerLogs: true, + commands: { + commands: ['editor.action.triggerParameterHints'], + }, + ...capabilities.experimental, + } + } + initialize( + _capabilities: lc.ServerCapabilities, + _documentSelector: lc.DocumentSelector | undefined + ): void {} + dispose(): void {} + clear(): void {} +} diff --git a/rust/kcl-language-server/client/src/commands.ts b/rust/kcl-language-server/client/src/commands.ts new file mode 100644 index 000000000..b51c8ec53 --- /dev/null +++ b/rust/kcl-language-server/client/src/commands.ts @@ -0,0 +1,32 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as vscode from 'vscode' + +import type { Cmd, CtxInit } from './ctx' +import { spawnSync } from 'child_process' + +export function serverVersion(ctx: CtxInit): Cmd { + return async () => { + if (!ctx.serverPath) { + void vscode.window.showWarningMessage( + `kcl-language-server server is not running` + ) + return + } + const { stdout } = spawnSync(ctx.serverPath, ['--version'], { + encoding: 'utf8', + }) + const versionString = stdout.slice(`kcl-language-server `.length).trim() + + void vscode.window.showInformationMessage( + `kcl-language-server version: ${versionString}` + ) + } +} + +export function openLogs(ctx: CtxInit): Cmd { + return async () => { + if (ctx.client.outputChannel) { + ctx.client.outputChannel.show() + } + } +} diff --git a/rust/kcl-language-server/client/src/config.ts b/rust/kcl-language-server/client/src/config.ts new file mode 100644 index 000000000..49ad5addd --- /dev/null +++ b/rust/kcl-language-server/client/src/config.ts @@ -0,0 +1,293 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as Is from 'vscode-languageclient/lib/common/utils/is' +import * as os from 'os' +import * as path from 'path' +import * as vscode from 'vscode' +import { log, type Env } from './util' +import { expectNotUndefined, unwrapUndefinable } from './undefinable' + +export type RunnableEnvCfgItem = { + mask?: string + env: Record + platform?: string | string[] +} +export type RunnableEnvCfg = + | undefined + | Record + | RunnableEnvCfgItem[] + +export class Config { + readonly extensionId = 'kittycad.kcl-language-server' + configureLang: vscode.Disposable | undefined + + readonly rootSection = 'kcl-language-server' + private readonly requiresReloadOpts = ['serverPath', 'server', 'files'].map( + (opt) => `${this.rootSection}.${opt}` + ) + + readonly package: { + version: string + releaseTag: string | null + enableProposedApi: boolean | undefined + } = vscode.extensions.getExtension(this.extensionId)!.packageJSON + + readonly globalStorageUri: vscode.Uri + + constructor(ctx: vscode.ExtensionContext) { + this.globalStorageUri = ctx.globalStorageUri + vscode.workspace.onDidChangeConfiguration( + this.onDidChangeConfiguration, + this, + ctx.subscriptions + ) + this.refreshLogging() + } + + dispose() { + this.configureLang?.dispose() + } + + private refreshLogging() { + log.setEnabled(this.traceExtension ?? false) + log.info('Extension version:', this.package.version) + + const cfg = Object.entries(this.cfg).filter( + ([_, val]) => !(val instanceof Function) + ) + log.info('Using configuration', Object.fromEntries(cfg)) + } + + private async onDidChangeConfiguration( + event: vscode.ConfigurationChangeEvent + ) { + this.refreshLogging() + + const requiresReloadOpt = this.requiresReloadOpts.find((opt) => + event.affectsConfiguration(opt) + ) + + if (!requiresReloadOpt) return + + const message = `Changing "${requiresReloadOpt}" requires a server restart` + const userResponse = await vscode.window.showInformationMessage( + message, + 'Restart now' + ) + + if (userResponse) { + const command = 'kcl-language-server.restartServer' + await vscode.commands.executeCommand(command) + } + } + + // We don't do runtime config validation here for simplicity. More on stackoverflow: + // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension + + private get cfg(): vscode.WorkspaceConfiguration { + return vscode.workspace.getConfiguration(this.rootSection) + } + + /** + * Beware that postfix `!` operator erases both `null` and `undefined`. + * This is why the following doesn't work as expected: + * + * ```ts + * const nullableNum = vscode + * .workspace + * .getConfiguration + * .getConfiguration("kcl-language-server") + * .get(path)!; + * + * // What happens is that type of `nullableNum` is `number` but not `null | number`: + * const fullFledgedNum: number = nullableNum; + * ``` + * So this getter handles this quirk by not requiring the caller to use postfix `!` + */ + private get(path: string): T | undefined { + return prepareVSCodeConfig(this.cfg.get(path)) + } + + get serverPath() { + return ( + this.get('server.path') ?? + this.get('serverPath') + ) + } + + get traceExtension() { + return this.get('trace.extension') + } +} + +// the optional `cb?` parameter is meant to be used to add additional +// key/value pairs to the VS Code configuration. This needed for, e.g., +// including a `rust-project.json` into the `linkedProjects` key as part +// of the configuration/InitializationParams _without_ causing VS Code +// configuration to be written out to workspace-level settings. This is +// undesirable behavior because rust-project.json files can be tens of +// thousands of lines of JSON, most of which is not meant for humans +// to interact with. +export function prepareVSCodeConfig( + resp: T, + cb?: (key: Extract, res: { [key: string]: any }) => void +): T { + if (Is.string(resp)) { + return substituteVSCodeVariableInString(resp) as T + } else if (resp && Is.array(resp)) { + return resp.map((val) => { + return prepareVSCodeConfig(val) + }) as T + } else if (resp && typeof resp === 'object') { + const res: { [key: string]: any } = {} + for (const key in resp) { + const val = resp[key] + res[key] = prepareVSCodeConfig(val) + if (cb) { + cb(key, res) + } + } + return res as T + } + return resp +} + +// FIXME: Merge this with `substituteVSCodeVariables` above +export function substituteVariablesInEnv(env: Env): Env { + const missingDeps = new Set() + // vscode uses `env:ENV_NAME` for env vars resolution, and it's easier + // to follow the same convention for our dependency tracking + const definedEnvKeys = new Set(Object.keys(env).map((key) => `env:${key}`)) + const envWithDeps = Object.fromEntries( + Object.entries(env).map(([key, value]) => { + const deps = new Set() + const depRe = new RegExp(/\${(?.+?)}/g) + let match = undefined + while ((match = depRe.exec(value))) { + const depName = unwrapUndefinable(match.groups?.['depName']) + deps.add(depName) + // `depName` at this point can have a form of `expression` or + // `prefix:expression` + if (!definedEnvKeys.has(depName)) { + missingDeps.add(depName) + } + } + return [`env:${key}`, { deps: [...deps], value }] + }) + ) + + const resolved = new Set() + for (const dep of missingDeps) { + const match = /(?.*?):(?.+)/.exec(dep) + if (match) { + const { prefix, body } = match.groups! + if (prefix === 'env') { + const envName = unwrapUndefinable(body) + envWithDeps[dep] = { + value: process.env[envName] ?? '', + deps: [], + } + resolved.add(dep) + } else { + // we can't handle other prefixes at the moment + // leave values as is, but still mark them as resolved + envWithDeps[dep] = { + value: '${' + dep + '}', + deps: [], + } + resolved.add(dep) + } + } else { + envWithDeps[dep] = { + value: computeVscodeVar(dep) || '${' + dep + '}', + deps: [], + } + } + } + const toResolve = new Set(Object.keys(envWithDeps)) + + let leftToResolveSize + do { + leftToResolveSize = toResolve.size + for (const key of toResolve) { + const item = unwrapUndefinable(envWithDeps[key]) + if (item.deps.every((dep) => resolved.has(dep))) { + item.value = item.value.replace( + /\${(?.+?)}/g, + (_wholeMatch, depName) => { + const item = unwrapUndefinable(envWithDeps[depName]) + return item.value + } + ) + resolved.add(key) + toResolve.delete(key) + } + } + } while (toResolve.size > 0 && toResolve.size < leftToResolveSize) + + const resolvedEnv: Env = {} + for (const key of Object.keys(env)) { + const item = unwrapUndefinable(envWithDeps[`env:${key}`]) + resolvedEnv[key] = item.value + } + return resolvedEnv +} + +const VarRegex = new RegExp(/\$\{(.+?)\}/g) +function substituteVSCodeVariableInString(val: string): string { + return val.replace(VarRegex, (substring: string, varName) => { + if (Is.string(varName)) { + return computeVscodeVar(varName) || substring + } else { + return substring + } + }) +} + +function computeVscodeVar(varName: string): string | null { + const workspaceFolder = () => { + const folders = vscode.workspace.workspaceFolders ?? [] + const folder = folders[0] + // TODO: support for remote workspaces? + const fsPath: string = + folder === undefined + ? // no workspace opened + '' + : // could use currently opened document to detect the correct + // workspace. However, that would be determined by the document + // user has opened on Editor startup. Could lead to + // unpredictable workspace selection in practice. + // It's better to pick the first one + folder.uri.fsPath + return fsPath + } + // https://code.visualstudio.com/docs/editor/variables-reference + const supportedVariables: { [k: string]: () => string } = { + workspaceFolder, + + workspaceFolderBasename: () => { + return path.basename(workspaceFolder()) + }, + + cwd: () => process.cwd(), + userHome: () => os.homedir(), + + // see + // https://github.com/microsoft/vscode/blob/08ac1bb67ca2459496b272d8f4a908757f24f56f/src/vs/workbench/api/common/extHostVariableResolverService.ts#L81 + // or + // https://github.com/microsoft/vscode/blob/29eb316bb9f154b7870eb5204ec7f2e7cf649bec/src/vs/server/node/remoteTerminalChannel.ts#L56 + execPath: () => process.env['VSCODE_EXEC_PATH'] ?? process.execPath, + + pathSeparator: () => path.sep, + } + + if (varName in supportedVariables) { + const fn = expectNotUndefined( + supportedVariables[varName], + `${varName} should not be undefined here` + ) + return fn() + } else { + // return "${" + varName + "}"; + return null + } +} diff --git a/rust/kcl-language-server/client/src/ctx.ts b/rust/kcl-language-server/client/src/ctx.ts new file mode 100644 index 000000000..e350ebb6c --- /dev/null +++ b/rust/kcl-language-server/client/src/ctx.ts @@ -0,0 +1,387 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as vscode from 'vscode' +import type * as lc from 'vscode-languageclient/node' + +import { Config, prepareVSCodeConfig } from './config' +import { createClient } from './client' +import { + isKclDocument, + isKclEditor, + LazyOutputChannel, + log, + type KclEditor, +} from './util' +import type { ServerStatusParams } from './lsp_ext' +import { PersistentState } from './persistent_state' +import { bootstrap } from './bootstrap' +import { TransportKind } from 'vscode-languageclient/node' + +// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if +// only those are in use. We use "Empty" to represent these scenarios +// (r-a still somewhat works with Live Share, because commands are tunneled to the host) + +export type Workspace = + | { kind: 'Empty' } + | { + kind: 'Workspace Folder' + } + | { + kind: 'Detached Files' + files: vscode.TextDocument[] + } + +export function fetchWorkspace(): Workspace { + const folders = (vscode.workspace.workspaceFolders || []).filter( + (folder) => folder.uri.scheme === 'file' + ) + const kclDocuments = vscode.workspace.textDocuments.filter((document) => + isKclDocument(document) + ) + + return folders.length === 0 + ? kclDocuments.length === 0 + ? { kind: 'Empty' } + : { + kind: 'Detached Files', + files: kclDocuments, + } + : { kind: 'Workspace Folder' } +} + +export type CommandFactory = { + enabled: (ctx: CtxInit) => Cmd + disabled?: (ctx: Ctx) => Cmd +} + +export type CtxInit = Ctx & { + readonly client: lc.LanguageClient +} + +export class Ctx { + readonly statusBar: vscode.StatusBarItem + config: Config + readonly workspace: Workspace + + private _client: lc.LanguageClient | undefined + private _serverPath: string | undefined + private traceOutputChannel: vscode.OutputChannel | undefined + private outputChannel: vscode.OutputChannel | undefined + private clientSubscriptions: Disposable[] + private state: PersistentState + private commandFactories: Record + private commandDisposables: Disposable[] + private lastStatus: ServerStatusParams | { health: 'stopped' } = { + health: 'stopped', + } + + get client() { + return this._client + } + + constructor( + readonly extCtx: vscode.ExtensionContext, + commandFactories: Record, + workspace: Workspace + ) { + extCtx.subscriptions.push(this) + this.statusBar = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Left + ) + this.workspace = workspace + this.clientSubscriptions = [] + this.commandDisposables = [] + this.commandFactories = commandFactories + this.state = new PersistentState(extCtx.globalState) + this.config = new Config(extCtx) + + this.updateCommands('disable') + this.setServerStatus({ + health: 'stopped', + }) + } + + dispose() { + this.config.dispose() + this.statusBar.dispose() + void this.disposeClient() + this.commandDisposables.forEach((disposable) => disposable.dispose()) + } + + async onWorkspaceFolderChanges() { + const workspace = fetchWorkspace() + if ( + workspace.kind === 'Detached Files' && + this.workspace.kind === 'Detached Files' + ) { + if (workspace.files !== this.workspace.files) { + if (this.client?.isRunning()) { + // Ideally we wouldn't need to tear down the server here, but currently detached files + // are only specified at server start + await this.stopAndDispose() + await this.start() + } + return + } + } + if ( + workspace.kind === 'Workspace Folder' && + this.workspace.kind === 'Workspace Folder' + ) { + return + } + if (workspace.kind === 'Empty') { + await this.stopAndDispose() + return + } + if (this.client?.isRunning()) { + await this.restart() + } + } + + private async getOrCreateClient() { + if (this.workspace.kind === 'Empty') { + return + } + + if (!this.traceOutputChannel) { + this.traceOutputChannel = new LazyOutputChannel( + 'KittyCAD Language Server Trace' + ) + this.pushExtCleanup(this.traceOutputChannel) + } + if (!this.outputChannel) { + this.outputChannel = vscode.window.createOutputChannel( + 'KittyCAD Language Server' + ) + this.pushExtCleanup(this.outputChannel) + } + + if (!this._client) { + this._serverPath = await bootstrap( + this.extCtx, + this.config, + this.state + ).catch((err) => { + let message = 'bootstrap error. ' + + message += + 'See the logs in "OUTPUT > KittyCAD Language Client" (should open automatically). ' + message += + 'To enable verbose logs use { "kcl-language-server.trace.extension": true }' + + log.error('Bootstrap error', err) + throw new Error(message) + }) + const run: lc.Executable = { + command: this._serverPath, + args: ['--json', 'server'], + transport: TransportKind.stdio, + options: { env: { ...process.env } }, + } + const serverOptions = { + run, + debug: run, + } + + let rawInitializationOptions = vscode.workspace.getConfiguration( + 'kcl-language-server' + ) + + if (this.workspace.kind === 'Detached Files') { + rawInitializationOptions = { + detachedFiles: this.workspace.files.map((file) => file.uri.fsPath), + ...rawInitializationOptions, + } + } + + const initializationOptions = prepareVSCodeConfig( + rawInitializationOptions + ) + + this._client = await createClient( + this.traceOutputChannel, + this.outputChannel, + initializationOptions, + serverOptions + ) + } + return this._client + } + + async start() { + log.info('Starting language client') + const client = await this.getOrCreateClient() + if (!client) { + return + } + await client.start() + this.setServerStatus({ health: 'ok', quiescent: true }) + this.updateCommands() + } + + async restart() { + // FIXME: We should reuse the client, that is ctx.deactivate() if none of the configs have changed + await this.stopAndDispose() + await this.start() + } + + async stop() { + if (!this._client) { + return + } + log.info('Stopping language client') + this.updateCommands('disable') + await this._client.stop() + } + + async stopAndDispose() { + if (!this._client) { + return + } + log.info('Disposing language client') + this.updateCommands('disable') + await this.disposeClient() + } + + private async disposeClient() { + this.clientSubscriptions?.forEach((disposable) => disposable.dispose()) + this.clientSubscriptions = [] + try { + await this._client?.dispose(2000) + } catch (e) { + // DO nothing. + } + this._serverPath = undefined + this._client = undefined + } + + get activeKclEditor(): KclEditor | undefined { + const editor = vscode.window.activeTextEditor + return editor && isKclEditor(editor) ? editor : undefined + } + + get extensionPath(): string { + return this.extCtx.extensionPath + } + + get subscriptions(): Disposable[] { + return this.extCtx.subscriptions + } + + get serverPath(): string | undefined { + return this._serverPath + } + + private updateCommands(forceDisable?: 'disable') { + this.commandDisposables.forEach((disposable) => disposable.dispose()) + this.commandDisposables = [] + + const clientRunning = (!forceDisable && this._client?.isRunning()) ?? false + const isClientRunning = function (_ctx: Ctx): _ctx is CtxInit { + return clientRunning + } + + for (const [name, factory] of Object.entries(this.commandFactories)) { + const fullName = `kcl-language-server.${name}` + let callback + if (isClientRunning(this)) { + // we asserted that `client` is defined + callback = factory.enabled(this) + } else if (factory.disabled) { + callback = factory.disabled(this) + } else { + callback = () => + vscode.window.showErrorMessage( + `command ${fullName} failed: kcl-language-server server is not running` + ) + } + + this.commandDisposables.push( + vscode.commands.registerCommand(fullName, callback) + ) + } + } + + setServerStatus(status: ServerStatusParams | { health: 'stopped' }) { + this.lastStatus = status + this.updateStatusBarItem() + } + refreshServerStatus() { + this.updateStatusBarItem() + } + private updateStatusBarItem() { + let icon = '' + const status = this.lastStatus + const statusBar = this.statusBar + statusBar.show() + statusBar.tooltip = new vscode.MarkdownString('', true) + statusBar.tooltip.isTrusted = true + switch (status.health) { + case 'ok': + statusBar.tooltip.appendText(status.message ?? 'Ready') + statusBar.color = undefined + statusBar.backgroundColor = undefined + statusBar.command = 'kcl-language-server.openLogs' + break + case 'warning': + if (status.message) { + statusBar.tooltip.appendText(status.message) + } + statusBar.color = new vscode.ThemeColor( + 'statusBarItem.warningForeground' + ) + statusBar.backgroundColor = new vscode.ThemeColor( + 'statusBarItem.warningBackground' + ) + statusBar.command = 'kcl-language-server.openLogs' + icon = '$(warning) ' + break + case 'error': + if (status.message) { + statusBar.tooltip.appendText(status.message) + } + statusBar.color = new vscode.ThemeColor('statusBarItem.errorForeground') + statusBar.backgroundColor = new vscode.ThemeColor( + 'statusBarItem.errorBackground' + ) + statusBar.command = 'kcl-language-server.openLogs' + icon = '$(error) ' + break + case 'stopped': + statusBar.tooltip.appendText('Server is stopped') + statusBar.tooltip.appendMarkdown( + '\n\n[Start server](command:kcl-language-server.startServer)' + ) + statusBar.color = new vscode.ThemeColor( + 'statusBarItem.warningForeground' + ) + statusBar.backgroundColor = new vscode.ThemeColor( + 'statusBarItem.warningBackground' + ) + statusBar.command = 'kcl-language-server.startServer' + statusBar.text = '$(stop-circle) kcl-language-server' + return + } + if (statusBar.tooltip.value) { + statusBar.tooltip.appendMarkdown('\n\n---\n\n') + } + statusBar.tooltip.appendMarkdown( + '\n\n[Restart server](command:kcl-language-server.restartServer)' + ) + statusBar.tooltip.appendMarkdown( + '\n\n[Stop server](command:kcl-language-server.stopServer)' + ) + if (!status.quiescent) icon = '$(sync~spin) ' + statusBar.text = `${icon}kcl-language-server` + } + + pushExtCleanup(d: Disposable) { + this.extCtx.subscriptions.push(d) + } +} + +export interface Disposable { + dispose(): void +} + +export type Cmd = (...args: any[]) => unknown diff --git a/rust/kcl-language-server/client/src/lsp_ext.ts b/rust/kcl-language-server/client/src/lsp_ext.ts new file mode 100644 index 000000000..6610570d0 --- /dev/null +++ b/rust/kcl-language-server/client/src/lsp_ext.ts @@ -0,0 +1,24 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as lc from 'vscode-languageclient' + +export type CommandLink = { + /** + * A tooltip for the command, when represented in the UI. + */ + tooltip?: string +} & lc.Command +export type CommandLinkGroup = { + title?: string + commands: CommandLink[] +} + +// experimental extensions + +export const serverStatus = new lc.NotificationType( + 'experimental/serverStatus' +) +export type ServerStatusParams = { + health: 'ok' | 'warning' | 'error' + quiescent: boolean + message?: string +} diff --git a/rust/kcl-language-server/client/src/main.ts b/rust/kcl-language-server/client/src/main.ts new file mode 100644 index 000000000..19ce6e372 --- /dev/null +++ b/rust/kcl-language-server/client/src/main.ts @@ -0,0 +1,79 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as vscode from 'vscode' +import type * as lc from 'vscode-languageclient/node' + +import * as commands from './commands' +import { type CommandFactory, Ctx, fetchWorkspace } from './ctx' +import { setContextValue } from './util' + +const KCL_PROJECT_CONTEXT_NAME = 'inKclProject' + +export interface KclAnalyzerExtensionApi { + readonly client?: lc.LanguageClient +} + +export async function deactivate() { + await setContextValue(KCL_PROJECT_CONTEXT_NAME, undefined) +} + +export async function activate( + context: vscode.ExtensionContext +): Promise { + const ctx = new Ctx(context, createCommands(), fetchWorkspace()) + // VS Code doesn't show a notification when an extension fails to activate + // so we do it ourselves. + const api = await activateServer(ctx).catch((err) => { + void vscode.window.showErrorMessage( + `Cannot activate kcl-language-server extension: ${err.message}` + ) + throw err + }) + await setContextValue(KCL_PROJECT_CONTEXT_NAME, true) + return api +} + +async function activateServer(ctx: Ctx): Promise { + await ctx.start() + return ctx +} + +function createCommands(): Record { + return { + restartServer: { + enabled: (ctx) => async () => { + await ctx.restart() + }, + disabled: (ctx) => async () => { + await ctx.start() + }, + }, + startServer: { + enabled: (ctx) => async () => { + await ctx.start() + ctx.setServerStatus({ + health: 'ok', + quiescent: true, + }) + }, + disabled: (ctx) => async () => { + await ctx.start() + ctx.setServerStatus({ + health: 'ok', + quiescent: true, + }) + }, + }, + stopServer: { + enabled: (ctx) => async () => { + // FIXME: We should reuse the client, that is ctx.deactivate() if none of the configs have changed + await ctx.stopAndDispose() + ctx.setServerStatus({ + health: 'stopped', + }) + }, + disabled: (_) => async () => {}, + }, + serverVersion: { enabled: commands.serverVersion }, + openLogs: { enabled: commands.openLogs }, + } +} diff --git a/rust/kcl-language-server/client/src/persistent_state.ts b/rust/kcl-language-server/client/src/persistent_state.ts new file mode 100644 index 000000000..ae9e60204 --- /dev/null +++ b/rust/kcl-language-server/client/src/persistent_state.ts @@ -0,0 +1,21 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import type * as vscode from 'vscode' +import { log } from './util' + +export class PersistentState { + constructor(private readonly globalState: vscode.Memento) { + const { serverVersion } = this + log.info('PersistentState:', { serverVersion }) + } + + /** + * Version of the extension that installed the server. + * Used to check if we need to run patchelf again on NixOS. + */ + get serverVersion(): string | undefined { + return this.globalState.get('serverVersion') + } + async updateServerVersion(value: string | undefined) { + await this.globalState.update('serverVersion', value) + } +} diff --git a/rust/kcl-language-server/client/src/test/runTest.ts b/rust/kcl-language-server/client/src/test/runTest.ts new file mode 100644 index 000000000..542d5903e --- /dev/null +++ b/rust/kcl-language-server/client/src/test/runTest.ts @@ -0,0 +1,25 @@ +import * as path from 'path' + +import { runTests } from '@vscode/test-electron' + +async function main() { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, '../../') + + // The path to the extension test runner script + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, './suite/index') + + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }) + } catch (err) { + console.error(err) + console.error('Failed to run tests') + process.exit(1) + } +} + +/* eslint-disable */ +main() diff --git a/rust/kcl-language-server/client/src/test/suite/extension.test.ts b/rust/kcl-language-server/client/src/test/suite/extension.test.ts new file mode 100644 index 000000000..d28ece25b --- /dev/null +++ b/rust/kcl-language-server/client/src/test/suite/extension.test.ts @@ -0,0 +1,16 @@ +import * as assert from 'assert' + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode' +// import * as myExtension from '../../extension'; + +suite('Extension Test Suite', () => { + /* eslint-disable */ + vscode.window.showInformationMessage('Start all tests.') + + test('Sample test', () => { + assert.strictEqual([1, 2, 3].indexOf(5), -1) + assert.strictEqual([1, 2, 3].indexOf(0), -1) + }) +}) diff --git a/rust/kcl-language-server/client/src/test/suite/index.ts b/rust/kcl-language-server/client/src/test/suite/index.ts new file mode 100644 index 000000000..d6681067c --- /dev/null +++ b/rust/kcl-language-server/client/src/test/suite/index.ts @@ -0,0 +1,33 @@ +import * as path from 'path' +const Mocha = require('mocha') +const { glob } = require('glob') + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd', + }) + + const testsRoot = path.resolve(__dirname, '..') + + return new Promise((c, e) => { + glob('**/**.test.js', { cwd: testsRoot }).then((files: string[]) => { + // Add files to the test suite + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))) + + try { + // Run the mocha test + mocha.run((failures: any) => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)) + } else { + c() + } + }) + } catch (err) { + console.error(err) + e(err) + } + }) + }) +} diff --git a/rust/kcl-language-server/client/src/undefinable.ts b/rust/kcl-language-server/client/src/undefinable.ts new file mode 100644 index 000000000..ba9c36062 --- /dev/null +++ b/rust/kcl-language-server/client/src/undefinable.ts @@ -0,0 +1,23 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +export type NotUndefined = T extends undefined ? never : T + +export type Undefinable = T | undefined + +function isNotUndefined(input: Undefinable): input is NotUndefined { + return input !== undefined +} + +export function expectNotUndefined( + input: Undefinable, + msg: string +): NotUndefined { + if (isNotUndefined(input)) { + return input + } + + throw new TypeError(msg) +} + +export function unwrapUndefinable(input: Undefinable): NotUndefined { + return expectNotUndefined(input, `unwrapping \`undefined\``) +} diff --git a/rust/kcl-language-server/client/src/util.ts b/rust/kcl-language-server/client/src/util.ts new file mode 100644 index 000000000..04ad5a1fd --- /dev/null +++ b/rust/kcl-language-server/client/src/util.ts @@ -0,0 +1,240 @@ +/* eslint suggest-no-throw/suggest-no-throw: 0 */ +import * as vscode from 'vscode' +import { strict as nativeAssert } from 'assert' +import { exec, type ExecOptions, spawnSync } from 'child_process' +import { inspect } from 'util' + +export interface Env { + [name: string]: string +} + +export function assert( + condition: boolean, + explanation: string +): asserts condition { + try { + nativeAssert(condition, explanation) + } catch (err) { + log.error(`Assertion failed:`, explanation) + throw err + } +} + +class Logger { + private enabled = true + private readonly output = vscode.window.createOutputChannel( + 'KittyCAD Language Client' + ) + + setEnabled(yes: boolean): void { + log.enabled = yes + } + + // Hint: the type [T, ...T[]] means a non-empty array + debug(...msg: [unknown, ...unknown[]]): void { + if (!log.enabled) return + log.write('DEBUG', ...msg) + } + + info(...msg: [unknown, ...unknown[]]): void { + log.write('INFO', ...msg) + } + + warn(...msg: [unknown, ...unknown[]]): void { + debugger + log.write('WARN', ...msg) + } + + error(...msg: [unknown, ...unknown[]]): void { + debugger + log.write('ERROR', ...msg) + log.output.show(true) + } + + private write(label: string, ...messageParts: unknown[]): void { + const message = messageParts.map(log.stringify).join(' ') + const dateTime = new Date().toLocaleString() + log.output.appendLine(`${label} [${dateTime}]: ${message}`) + } + + private stringify(val: unknown): string { + if (typeof val === 'string') return val + return inspect(val, { + colors: false, + depth: 6, // heuristic + }) + } +} + +export const log = new Logger() + +export function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +export type KclDocument = vscode.TextDocument & { languageId: 'kcl' } +export type KclEditor = vscode.TextEditor & { document: KclDocument } + +export function isKclDocument( + document: vscode.TextDocument +): document is KclDocument { + // Prevent corrupted text (particularly via inlay hints) in diff views + // by allowing only `file` schemes + // unfortunately extensions that use diff views not always set this + // to something different than 'file' (see ongoing bug: #4608) + return document.languageId === 'kcl' && document.uri.scheme === 'file' +} + +export function isCargoTomlDocument( + document: vscode.TextDocument +): document is KclDocument { + // ideally `document.languageId` should be 'toml' but user maybe not have toml extension installed + return ( + document.uri.scheme === 'file' && document.fileName.endsWith('Cargo.toml') + ) +} + +export function isKclEditor(editor: vscode.TextEditor): editor is KclEditor { + return isKclDocument(editor.document) +} + +export function isDocumentInWorkspace(document: KclDocument): boolean { + const workspaceFolders = vscode.workspace.workspaceFolders + if (!workspaceFolders) { + return false + } + for (const folder of workspaceFolders) { + if (document.uri.fsPath.startsWith(folder.uri.fsPath)) { + return true + } + } + return false +} + +export function isValidExecutable(path: string): boolean { + log.debug('Checking availability of a binary at', path) + + const res = spawnSync(path, ['--version'], { + encoding: 'utf8', + env: { ...process.env }, + }) + + const printOutput = res.error ? log.warn : log.info + printOutput(path, '--version:', res) + + return res.status === 0 +} + +/** Sets ['when'](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts) clause contexts */ +export function setContextValue(key: string, value: any): Thenable { + return vscode.commands.executeCommand('setContext', key, value) +} + +/** + * Returns a higher-order function that caches the results of invoking the + * underlying async function. + */ +export function memoizeAsync( + func: (this: TThis, arg: Param) => Promise +) { + const cache = new Map() + + return async function (this: TThis, arg: Param) { + const cached = cache.get(arg) + if (cached) return cached + + const result = await func.call(this, arg) + cache.set(arg, result) + + return result + } +} + +/** Awaitable wrapper around `child_process.exec` */ +export function execute( + command: string, + options: ExecOptions +): Promise { + log.info(`running command: ${command}`) + return new Promise((resolve, reject) => { + exec(command, options, (err, stdout, stderr) => { + if (err) { + log.error(err) + reject(err) + return + } + + if (stderr) { + reject(new Error(stderr)) + return + } + + resolve(stdout.trimEnd()) + }) + }) +} + +export function executeDiscoverProject( + command: string, + options: ExecOptions +): Promise { + options = Object.assign({ maxBuffer: 10 * 1024 * 1024 }, options) + log.info(`running command: ${command}`) + return new Promise((resolve, reject) => { + exec(command, options, (err, stdout, _) => { + if (err) { + log.error(err) + reject(err) + return + } + + resolve(stdout.trimEnd()) + }) + }) +} + +export class LazyOutputChannel implements vscode.OutputChannel { + constructor(name: string) { + this.name = name + } + + name: string + _channel: vscode.OutputChannel | undefined + + get channel(): vscode.OutputChannel { + if (!this._channel) { + this._channel = vscode.window.createOutputChannel(this.name) + } + return this._channel + } + + append(value: string): void { + this.channel.append(value) + } + appendLine(value: string): void { + this.channel.appendLine(value) + } + replace(value: string): void { + this.channel.replace(value) + } + clear(): void { + if (this._channel) { + this._channel.clear() + } + } + show(preserveFocus?: boolean): void + show(column?: vscode.ViewColumn, preserveFocus?: boolean): void + show(column?: any, preserveFocus?: any): void { + this.channel.show(column, preserveFocus) + } + hide(): void { + if (this._channel) { + this._channel.hide() + } + } + dispose(): void { + if (this._channel) { + this._channel.dispose() + } + } +} diff --git a/rust/kcl-language-server/icon.png b/rust/kcl-language-server/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..46f2e2c4533083633b5f4c6bf8e8220c560fe953 GIT binary patch literal 23106 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 NK#(H8vLxDxO8JsS^TpIjR`w_yt z(vBM&0_lcrl4%exa||9V8{Z{6${e; zEX=Th%+q&Z7{``MBU*khe9 zN$c3{UbD0)Fu6fyXWO)z`?DPv4c_w$=#9V0t5!~VOX#s~mO z#QfG;mNbh)m-FqL{^hiVRtA+3zR$~(;or_H!X=?NO^pj)&HD&eRu)bfZUG?#E*Mjn z75T6(%MzL9;xtb8QdPUZ5zgZU_ZyqlPH^t zAeQ{-lpyZkRka%zUNwQpEPzsmYSiDEras$a2)Jgop#(O}QT+osQNLH@Z-F5vFE^N-! zkJO;j<3>4%1dgFo^42ul}N!R}b-z8>*mMuKNt( zXZeURK`lil=4v$gTb*T#xXsGoFgh*Yr{-IbnbGE*^WSP*aO7%1c{1EnSnbA|%gA$n zN=L8WMPbX2=U^aPFYEv@W87Z7c=)IO68BFQF)eWDPjp_!`V?EN1@vY|V`hn6@Q&*< zJ@?zx{=}Wx%G<3tR$w7zuWk;o4L!L2`HO^*?Hk)wWSbU9h)#7*)+{_$_E;2@nkf%v z=1Wby@OcUob%S%{=0AZ)7dmBjb1<uZ&2ScU!%EIPJu literal 0 HcmV?d00001 diff --git a/rust/kcl-language-server/package.json b/rust/kcl-language-server/package.json new file mode 100644 index 000000000..6241377a4 --- /dev/null +++ b/rust/kcl-language-server/package.json @@ -0,0 +1,151 @@ +{ + "name": "kcl-language-server", + "displayName": "KittyCAD Language Server", + "description": "KittyCAD language support for Visual Studio Code", + "private": true, + "icon": "icon.png", + "publisher": "kittycad", + "homepage": "https://kittycad.io", + "license": "MIT", + "version": "0.0.0", + "releaseTag": null, + "keywords": [ + "language-server", + "kittycad", + "kcl", + "hardware", + "cad", + "manufacturing" + ], + "categories": [ + "Programming Languages" + ], + "repository": { + "url": "https://github.com/kittycad/modeling-app.git", + "type": "git" + }, + "engines": { + "vscode": "^1.97.0" + }, + "enabledApiProposals": [], + "activationEvents": [ + "onLanguage:kcl" + ], + "main": "./dist/main.js", + "contributes": { + "languages": [ + { + "id": "kcl", + "extensions": [ + ".kcl" + ] + } + ], + "configuration": { + "type": "object", + "title": "kcl-language-server", + "properties": { + "kcl-language-server.server.path": { + "type": [ + "null", + "string" + ], + "scope": "machine-overridable", + "default": null, + "markdownDescription": "Path to kcl-language-server executable (points to bundled binary by default)." + }, + "kcl-language-server.trace.server": { + "type": "string", + "scope": "window", + "enum": [ + "off", + "messages", + "verbose" + ], + "enumDescriptions": [ + "No traces", + "Error only", + "Full log" + ], + "default": "off", + "description": "Trace requests to the kcl-language-server (this is usually overly verbose and not recommended for regular users)." + }, + "kcl-language-server.trace.extension": { + "description": "Enable logging of VS Code extensions itself.", + "type": "boolean", + "default": false + } + } + }, + "configurationDefaults": { + "[kcl]": { + "editor.semanticHighlighting.enabled": true + } + }, + "commands": [ + { + "command": "kcl-language-server.restartServer", + "title": "Restart server", + "category": "kcl-language-server" + }, + { + "command": "kcl-language-server.startServer", + "title": "Start server", + "category": "kcl-language-server" + }, + { + "command": "kcl-language-server.stopServer", + "title": "Stop server", + "category": "kcl-language-server" + }, + { + "command": "kcl-language-server.serverVersion", + "title": "Show server version", + "category": "kcl-language-server" + } + ], + "menus": { + "commandPalette": [ + { + "command": "kcl-language-server.restartServer", + "when": "inKclProject" + }, + { + "command": "kcl-language-server.serverVersion", + "when": "inKclProject" + } + ] + } + }, + "scripts": { + "vscode:prepublish": "yarn run build-base -- --minify", + "deploy": "vsce publish --yarn", + "build-base": "esbuild ./client/src/main.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --target=node16", + "test-compile": "tsc -p ./", + "compile": "cross-env NODE_ENV=production tsc -b", + "build": "yarn run build-base -- --sourcemap", + "watch": "yarn run build-base -- --sourcemap --watch", + "pretest": "yarn run build && yarn test-compile", + "test": "node ./dist/client/src/test/runTest.js", + "package": "vsce package -o kcl-language-server.vsix" + }, + "devDependencies": { + "@tsconfig/strictest": "^2.0.5", + "@types/glob": "^8.1.0", + "@types/mocha": "^10.0.10", + "@types/node": "^22.13.9", + "@types/vscode": "^1.97.0", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", + "@vscode/test-electron": "^2.4.1", + "@vscode/vsce": "^2.30.0", + "cross-env": "^7.0.3", + "esbuild": "^0.25.0", + "glob": "^10.4.3", + "mocha": "^11.1.0", + "typescript": "^5.8.2" + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + } +} diff --git a/rust/kcl-language-server/src/main.rs b/rust/kcl-language-server/src/main.rs new file mode 100644 index 000000000..e76a02459 --- /dev/null +++ b/rust/kcl-language-server/src/main.rs @@ -0,0 +1,180 @@ +//! The `kcl` lsp server. + +#![deny(missing_docs)] + +use anyhow::{bail, Result}; +use clap::Parser; +use slog::Drain; +use tower_lsp::{LspService, Server as LspServer}; +use tracing_subscriber::{prelude::*, Layer}; + +lazy_static::lazy_static! { +/// Initialize the logger. + // We need a slog::Logger for steno and when we export out the logs from re-exec-ed processes. + pub static ref LOGGER: slog::Logger = { + let decorator = slog_term::TermDecorator::new().build(); + let drain = slog_term::FullFormat::new(decorator).build().fuse(); + let drain = slog_async::Async::new(drain).build().fuse(); + slog::Logger::root(drain, slog::slog_o!()) + }; +} + +/// This doc string acts as a help message when the user runs '--help' +/// as do all doc strings on fields. +#[derive(Parser, Debug, Clone)] +#[clap(version = clap::crate_version!(), author = clap::crate_authors!("\n"))] +pub struct Opts { + /// Print debug info + #[clap(short, long)] + pub debug: bool, + + /// Print logs as json + #[clap(short, long)] + pub json: bool, + + /// The subcommand to run. + #[clap(subcommand)] + pub subcmd: SubCommand, +} + +impl Opts { + /// Setup our logger. + pub fn create_logger(&self) -> slog::Logger { + if self.json { + let drain = slog_json::Json::default(std::io::stderr()).fuse(); + self.async_root_logger(drain) + } else { + let decorator = slog_term::TermDecorator::new().build(); + let drain = slog_term::FullFormat::new(decorator).build().fuse(); + self.async_root_logger(drain) + } + } + + fn async_root_logger(&self, drain: T) -> slog::Logger + where + T: slog::Drain + Send + 'static, + ::Err: std::fmt::Debug, + { + let level = if self.debug { + slog::Level::Debug + } else { + slog::Level::Info + }; + + let level_drain = slog::LevelFilter(drain, level).fuse(); + let async_drain = slog_async::Async::new(level_drain).build().fuse(); + slog::Logger::root(async_drain, slog::o!()) + } +} + +/// A subcommand for our cli. +#[derive(Parser, Debug, Clone)] +pub enum SubCommand { + /// Run the server. + Server(kcl_lib::KclLspServerSubCommand), +} + +#[tokio::main] +async fn main() -> Result<()> { + let opts: Opts = Opts::parse(); + + let level_filter = if opts.debug { + tracing_subscriber::filter::LevelFilter::DEBUG + } else { + tracing_subscriber::filter::LevelFilter::INFO + }; + + // Format fields using the provided closure. + // We want to make this very consise otherwise the logs are not able to be read by humans. + let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| { + if format!("{}", field) == "message" { + write!(writer, "{}: {:?}", field, value) + } else { + write!(writer, "{}", field) + } + }) + // Separate each field with a comma. + // This method is provided by an extension trait in the + // `tracing-subscriber` prelude. + .delimited(", "); + + let (json, plain) = if opts.json { + // Cloud run likes json formatted logs if possible. + // See: https://cloud.google.com/run/docs/logging + // We could probably format these specifically for cloud run if we wanted, + // will save that as a TODO: https://cloud.google.com/run/docs/logging#special-fields + ( + Some(tracing_subscriber::fmt::layer().json().with_filter(level_filter)), + None, + ) + } else { + ( + None, + Some( + tracing_subscriber::fmt::layer() + .pretty() + .fmt_fields(format) + .with_filter(level_filter), + ), + ) + }; + + // Initialize the tracing. + tracing_subscriber::registry().with(json).with(plain).init(); + + if let Err(err) = run_cmd(&opts).await { + bail!("running cmd `{:?}` failed: {:?}", &opts.subcmd, err); + } + + Ok(()) +} + +async fn run_cmd(opts: &Opts) -> Result<()> { + match &opts.subcmd { + SubCommand::Server(s) => { + let (service, socket) = LspService::new(|client| { + kcl_lib::KclLspBackend::new(client, Default::default(), kittycad::Client::new(""), false).unwrap() + }); + + // TODO find a way to ctrl+c on windows. + #[cfg(not(target_os = "windows"))] + { + // For Cloud run & ctrl+c, shutdown gracefully. + // "The main process inside the container will receive SIGTERM, and after a grace period, + // SIGKILL." + // Registering SIGKILL here will panic at runtime, so let's avoid that. + use signal_hook::{ + consts::{SIGINT, SIGTERM}, + iterator::Signals, + }; + let mut signals = Signals::new([SIGINT, SIGTERM])?; + + tokio::spawn(async move { + if let Some(sig) = signals.forever().next() { + log::info!("received signal: {:?}", sig); + log::info!("triggering cleanup..."); + + // Exit the process. + log::info!("all clean, exiting!"); + std::process::exit(0); + } + }); + } + + if s.stdio { + // Listen on stdin and stdout. + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + LspServer::new(stdin, stdout, socket).serve(service).await; + } else { + // Listen on a tcp stream. + let listener = tokio::net::TcpListener::bind(&format!("0.0.0.0:{}", s.socket)).await?; + let (stream, _) = listener.accept().await?; + let (read, write) = tokio::io::split(stream); + LspServer::new(read, write, socket).serve(service).await; + } + } + } + + Ok(()) +} diff --git a/rust/kcl-language-server/tsconfig.json b/rust/kcl-language-server/tsconfig.json new file mode 100644 index 000000000..3d4c1aa07 --- /dev/null +++ b/rust/kcl-language-server/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json", + "compilerOptions": { + "esModuleInterop": false, + "module": "node16", + "moduleResolution": "node16", + "target": "es2021", + "outDir": "dist", + "lib": ["es2021"], + "sourceMap": true, + "rootDir": ".", + "newLine": "LF", + "allowSyntheticDefaultImports": true, + + // FIXME: https://github.com/rust-lang/rust-analyzer/issues/15253 + "exactOptionalPropertyTypes": false + }, + "exclude": ["node_modules", ".vscode-test"], + "include": ["client"] +} diff --git a/rust/kcl-language-server/yarn.lock b/rust/kcl-language-server/yarn.lock new file mode 100644 index 000000000..beb294ed8 --- /dev/null +++ b/rust/kcl-language-server/yarn.lock @@ -0,0 +1,2476 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@azure/abort-controller@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" + integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== + dependencies: + tslib "^2.2.0" + +"@azure/abort-controller@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz#42fe0ccab23841d9905812c58f1082d27784566d" + integrity sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA== + dependencies: + tslib "^2.6.2" + +"@azure/core-auth@^1.4.0", "@azure/core-auth@^1.5.0": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.7.2.tgz#558b7cb7dd12b00beec07ae5df5907d74df1ebd9" + integrity sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.6.2" + +"@azure/core-client@^1.4.0": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@azure/core-client/-/core-client-1.9.2.tgz#6fc69cee2816883ab6c5cdd653ee4f2ff9774f74" + integrity sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-auth" "^1.4.0" + "@azure/core-rest-pipeline" "^1.9.1" + "@azure/core-tracing" "^1.0.0" + "@azure/core-util" "^1.6.1" + "@azure/logger" "^1.0.0" + tslib "^2.6.2" + +"@azure/core-rest-pipeline@^1.1.0", "@azure/core-rest-pipeline@^1.9.1": + version "1.16.0" + resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz#631172e2fe0346cf4410d1c8e01ad98d849738e2" + integrity sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-auth" "^1.4.0" + "@azure/core-tracing" "^1.0.1" + "@azure/core-util" "^1.9.0" + "@azure/logger" "^1.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + tslib "^2.6.2" + +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.1.2.tgz#065dab4e093fb61899988a1cdbc827d9ad90b4ee" + integrity sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA== + dependencies: + tslib "^2.6.2" + +"@azure/core-util@^1.1.0", "@azure/core-util@^1.3.0", "@azure/core-util@^1.6.1", "@azure/core-util@^1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.9.0.tgz#469afd7e6452d5388b189f90d33f7756b0b210d1" + integrity sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw== + dependencies: + "@azure/abort-controller" "^2.0.0" + tslib "^2.6.2" + +"@azure/identity@^4.1.0": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" + integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-client" "^1.4.0" + "@azure/core-rest-pipeline" "^1.1.0" + "@azure/core-tracing" "^1.0.0" + "@azure/core-util" "^1.3.0" + "@azure/logger" "^1.0.0" + "@azure/msal-browser" "^3.11.1" + "@azure/msal-node" "^2.9.2" + events "^3.0.0" + jws "^4.0.0" + open "^8.0.0" + stoppable "^1.1.0" + tslib "^2.2.0" + +"@azure/logger@^1.0.0": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.1.2.tgz#3f4b876cefad328dc14aff8b850d63b611e249dc" + integrity sha512-l170uE7bsKpIU6B/giRc9i4NI0Mj+tANMMMxf7Zi/5cKzEqPayP7+X1WPrG7e+91JgY8N+7K7nF2WOi7iVhXvg== + dependencies: + tslib "^2.6.2" + +"@azure/msal-browser@^3.11.1": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.14.0.tgz#1cb5cab438a9943212aa50c403d11f775c787b21" + integrity sha512-Un85LhOoecJ3HDTS3Uv3UWnXC9/43ZSO+Kc+anSqpZvcEt58SiO/3DuVCAe1A3I5UIBYJNMgTmZPGXQ0MVYrwA== + dependencies: + "@azure/msal-common" "14.10.0" + +"@azure/msal-common@14.10.0": + version "14.10.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.10.0.tgz#215449726717b53d549953db77562cad6cb8421c" + integrity sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA== + +"@azure/msal-common@14.12.0": + version "14.12.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.12.0.tgz#844abe269b071f8fa8949dadc2a7b65bbb147588" + integrity sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw== + +"@azure/msal-node@^2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.9.2.tgz#e6d3c1661012c1bd0ef68e328f73a2fdede52931" + integrity sha512-8tvi6Cos3m+0KmRbPjgkySXi+UQU/QiuVRFnrxIwt5xZlEEFa69O04RTaNESGgImyBBlYbo2mfE8/U8Bbdk1WQ== + dependencies: + "@azure/msal-common" "14.12.0" + jsonwebtoken "^9.0.0" + uuid "^8.3.0" + +"@esbuild/aix-ppc64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" + integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== + +"@esbuild/android-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" + integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== + +"@esbuild/android-arm@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" + integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== + +"@esbuild/android-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" + integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== + +"@esbuild/darwin-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" + integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== + +"@esbuild/darwin-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" + integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== + +"@esbuild/freebsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" + integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== + +"@esbuild/freebsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" + integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== + +"@esbuild/linux-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" + integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== + +"@esbuild/linux-arm@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" + integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== + +"@esbuild/linux-ia32@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" + integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== + +"@esbuild/linux-loong64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" + integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== + +"@esbuild/linux-mips64el@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" + integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== + +"@esbuild/linux-ppc64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" + integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== + +"@esbuild/linux-riscv64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" + integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== + +"@esbuild/linux-s390x@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" + integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== + +"@esbuild/linux-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" + integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw== + +"@esbuild/netbsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" + integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== + +"@esbuild/netbsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" + integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== + +"@esbuild/openbsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" + integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== + +"@esbuild/openbsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" + integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== + +"@esbuild/sunos-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" + integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== + +"@esbuild/win32-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" + integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== + +"@esbuild/win32-ia32@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" + integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== + +"@esbuild/win32-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" + integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ== + +"@eslint-community/eslint-utils@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.5.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@tsconfig/strictest@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@tsconfig/strictest/-/strictest-2.0.5.tgz#2cbc67f207ba87fdec2a84ad79b1708cf4edd93b" + integrity sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg== + +"@types/glob@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== + dependencies: + "@types/minimatch" "^5.1.2" + "@types/node" "*" + +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/minimatch@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@*", "@types/node@^22.13.9": + version "22.13.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.9.tgz#5d9a8f7a975a5bd3ef267352deb96fb13ec02eca" + integrity sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw== + dependencies: + undici-types "~6.20.0" + +"@types/semver@^7.5.0": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@types/vscode@^1.97.0": + version "1.97.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.97.0.tgz#62ce3a32243019aaa4fc20cee2a3de06bc71af4f" + integrity sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w== + +"@typescript-eslint/eslint-plugin@^6.6.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^6.6.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== + dependencies: + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== + dependencies: + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== + +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== + dependencies: + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" + +"@vscode/test-electron@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-2.4.1.tgz#5c2760640bf692efbdaa18bafcd35fb519688941" + integrity sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ== + dependencies: + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.5" + jszip "^3.10.1" + ora "^7.0.1" + semver "^7.6.2" + +"@vscode/vsce-sign-alpine-arm64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz#4accc485e55aa6ff04b195b47f722ead57daa58e" + integrity sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ== + +"@vscode/vsce-sign-alpine-x64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz#4a4b7b505b4cc0f58596394897c49a0bce0e540c" + integrity sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw== + +"@vscode/vsce-sign-darwin-arm64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz#10aa69feb7f81a3dc68c242038ca03eaff19c12e" + integrity sha512-rz8F4pMcxPj8fjKAJIfkUT8ycG9CjIp888VY/6pq6cuI2qEzQ0+b5p3xb74CJnBbSC0p2eRVoe+WgNCAxCLtzQ== + +"@vscode/vsce-sign-darwin-x64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz#3315528f3ea1007a648b3320bff36a33a9e07aa5" + integrity sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw== + +"@vscode/vsce-sign-linux-arm64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz#ce5c5cfc99e3454b4fb770405812b46bd6dca870" + integrity sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA== + +"@vscode/vsce-sign-linux-arm@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz#4142fda83e7130b31aedd8aa81e4daa6334323c2" + integrity sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ== + +"@vscode/vsce-sign-linux-x64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz#59ab93f322efb3cf49166d4e2e812789c3117428" + integrity sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg== + +"@vscode/vsce-sign-win32-arm64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz#d095704a14b0404c0b6f696e9889e9a51b31a86c" + integrity sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ== + +"@vscode/vsce-sign-win32-x64@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz#294ea72b44fedd694d49f5cef4c55bf3876dc257" + integrity sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg== + +"@vscode/vsce-sign@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz#b4bf155d16f2a4badc069df850dc86f756124842" + integrity sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA== + optionalDependencies: + "@vscode/vsce-sign-alpine-arm64" "2.0.2" + "@vscode/vsce-sign-alpine-x64" "2.0.2" + "@vscode/vsce-sign-darwin-arm64" "2.0.2" + "@vscode/vsce-sign-darwin-x64" "2.0.2" + "@vscode/vsce-sign-linux-arm" "2.0.2" + "@vscode/vsce-sign-linux-arm64" "2.0.2" + "@vscode/vsce-sign-linux-x64" "2.0.2" + "@vscode/vsce-sign-win32-arm64" "2.0.2" + "@vscode/vsce-sign-win32-x64" "2.0.2" + +"@vscode/vsce@^2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-2.30.0.tgz#7a0c16b20ef529fa291fe9d3c7fe51a2a613f773" + integrity sha512-MBYpXdCY1SCdc2u/y11kmJuSODKFyZRpeRTQq5p4rSg05QSjSy5pz6h/BGLNdSahgXfKRBATEkjAcJFdJuDz8Q== + dependencies: + "@azure/identity" "^4.1.0" + "@vscode/vsce-sign" "^2.0.0" + azure-devops-node-api "^12.5.0" + chalk "^2.4.2" + cheerio "^1.0.0-rc.9" + cockatiel "^3.1.2" + commander "^6.2.1" + form-data "^4.0.0" + glob "^7.0.6" + hosted-git-info "^4.0.2" + jsonc-parser "^3.2.0" + leven "^3.1.0" + markdown-it "^12.3.2" + mime "^1.3.4" + minimatch "^3.0.3" + parse-semver "^1.1.1" + read "^1.0.7" + semver "^7.5.2" + tmp "^0.2.1" + typed-rest-client "^1.8.4" + url-join "^4.0.1" + xml2js "^0.5.0" + yauzl "^2.3.1" + yazl "^2.2.2" + optionalDependencies: + keytar "^7.7.0" + +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +azure-devops-node-api@^12.5.0: + version "12.5.0" + resolved "https://registry.yarnpkg.com/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz#38b9efd7c5ac74354fe4e8dbe42697db0b8e85a5" + integrity sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og== + dependencies: + tunnel "0.0.6" + typed-rest-client "^1.8.4" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.0.0, chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.9: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== + dependencies: + restore-cursor "^4.0.0" + +cli-spinners@^2.9.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +cockatiel@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/cockatiel/-/cockatiel-3.1.3.tgz#bb1774a498a17e739dd994d56610dc6538b02858" + integrity sha512-xC759TpZ69d7HhfDp8m2WkRwEUiCkxY8Ee2OQH/3H6zmy2D/5Sm+zSTbPRa+V2QyjDtpMvjOIAOVjA2gp6N1kQ== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +debug@4, debug@^4.3.4, debug@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-libc@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +emoji-regex@^10.2.1: + version "10.3.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" + integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +esbuild@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" + integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.0" + "@esbuild/android-arm" "0.25.0" + "@esbuild/android-arm64" "0.25.0" + "@esbuild/android-x64" "0.25.0" + "@esbuild/darwin-arm64" "0.25.0" + "@esbuild/darwin-x64" "0.25.0" + "@esbuild/freebsd-arm64" "0.25.0" + "@esbuild/freebsd-x64" "0.25.0" + "@esbuild/linux-arm" "0.25.0" + "@esbuild/linux-arm64" "0.25.0" + "@esbuild/linux-ia32" "0.25.0" + "@esbuild/linux-loong64" "0.25.0" + "@esbuild/linux-mips64el" "0.25.0" + "@esbuild/linux-ppc64" "0.25.0" + "@esbuild/linux-riscv64" "0.25.0" + "@esbuild/linux-s390x" "0.25.0" + "@esbuild/linux-x64" "0.25.0" + "@esbuild/netbsd-arm64" "0.25.0" + "@esbuild/netbsd-x64" "0.25.0" + "@esbuild/openbsd-arm64" "0.25.0" + "@esbuild/openbsd-x64" "0.25.0" + "@esbuild/sunos-x64" "0.25.0" + "@esbuild/win32-arm64" "0.25.0" + "@esbuild/win32-ia32" "0.25.0" + "@esbuild/win32-x64" "0.25.0" + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +fast-glob@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +foreground-child@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^10.4.3, glob@^10.4.5: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.0.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hosted-git-info@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + +http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.0, https-proxy-agent@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" + integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-unicode-supported@^1.1.0, is-unicode-supported@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" + integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jackspeak@^3.1.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.0.tgz#a75763ff36ad778ede6a156d8ee8b124de445b4a" + integrity sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + +keytar@^7.7.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" + integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== + dependencies: + node-addon-api "^4.3.0" + prebuild-install "^7.0.1" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-symbols@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" + integrity sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA== + dependencies: + chalk "^5.0.0" + is-unicode-supported "^1.1.0" + +lru-cache@^10.2.0: + version "10.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.3, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.1.0, minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.3: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mocha@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.1.0.tgz#20d7c6ac4d6d6bcb60a8aa47971fca74c65c3c66" + integrity sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mute-stream@~0.0.4: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-abi@^3.3.0: + version "3.62.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.62.0.tgz#017958ed120f89a3a14a7253da810f5d724e3f36" + integrity sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g== + dependencies: + semver "^7.3.5" + +node-addon-api@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +ora@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-7.0.1.tgz#cdd530ecd865fe39e451a0e7697865669cb11930" + integrity sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw== + dependencies: + chalk "^5.3.0" + cli-cursor "^4.0.0" + cli-spinners "^2.9.0" + is-interactive "^2.0.0" + is-unicode-supported "^1.3.0" + log-symbols "^5.1.0" + stdin-discarder "^0.1.0" + string-width "^6.1.0" + strip-ansi "^7.1.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parse-semver@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/parse-semver/-/parse-semver-1.1.1.tgz#9a4afd6df063dc4826f93fba4a99cf223f666cb8" + integrity sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ== + dependencies: + semver "^5.1.0" + +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prebuild-install@^7.0.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.2.tgz#a5fd9986f5a6251fbc47e1e5c65de71e68c0a056" + integrity sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +qs@^6.9.1: + version "6.12.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" + integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== + dependencies: + side-channel "^1.0.6" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ== + dependencies: + mute-stream "~0.0.4" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +sax@>=0.6.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" + integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + +semver@^5.1.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +stdin-discarder@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21" + integrity sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ== + dependencies: + bl "^5.0.0" + +stoppable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" + integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string-width@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-6.1.0.tgz#96488d6ed23f9ad5d82d13522af9e4c4c3fd7518" + integrity sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^10.2.1" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1, strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^1.0.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" + integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== + +tslib@^2.2.0, tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tunnel@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +typed-rest-client@^1.8.4: + version "1.8.11" + resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz#6906f02e3c91e8d851579f255abf0fd60800a04d" + integrity sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA== + dependencies: + qs "^6.9.1" + tunnel "0.0.6" + underscore "^1.12.1" + +typescript@^5.8.2: + version "5.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +underscore@^1.12.1: + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.3.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== + +vscode-languageclient@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz#cdfe20267726c8d4db839dc1e9d1816e1296e854" + integrity sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA== + dependencies: + minimatch "^5.1.0" + semver "^7.3.7" + vscode-languageserver-protocol "3.17.5" + +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== + dependencies: + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" + +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yauzl@^2.3.1: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yazl@^2.2.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" + integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== + dependencies: + buffer-crc32 "~0.2.3" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/rust/kcl-lib/Cargo.toml b/rust/kcl-lib/Cargo.toml index 5a367c659..5eff26814 100644 --- a/rust/kcl-lib/Cargo.toml +++ b/rust/kcl-lib/Cargo.toml @@ -21,7 +21,7 @@ clap = { version = "4.5.27", default-features = false, optional = true, features "derive", ] } convert_case = "0.8.0" -dashmap = "6.1.0" +dashmap = {workspace = true} dhat = { version = "0.3", optional = true } fnv = "1.0.7" form_urlencoded = "1.2.1" @@ -35,7 +35,7 @@ itertools = "0.13.0" kcl-derive-docs = { version = "0.1.44", path = "../kcl-derive-docs" } kittycad = { workspace = true } kittycad-modeling-cmds = { workspace = true } -lazy_static = "1.5.0" +lazy_static = { workspace = true } measurements = "0.11.0" miette = { workspace = true } mime_guess = "2.0.5" @@ -74,7 +74,7 @@ uuid = { workspace = true, features = ["v4", "js", "serde"] } validator = { version = "0.20.0", features = ["derive"] } web-time = "1.1" winnow = "=0.6.24" -zip = { version = "2.2.2", default-features = false } +zip = { workspace = true } [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = { version = "0.3.72" } diff --git a/rust/kcl-lib/README.md b/rust/kcl-lib/README.md index b5e8cb6eb..4de47a3c9 100644 --- a/rust/kcl-lib/README.md +++ b/rust/kcl-lib/README.md @@ -23,6 +23,4 @@ We've built a lot of tooling to make contributing to KCL easier. If you are inte If you bump the version of kcl-lib and push it to crates, be sure to update the repos we own that use it as well. These are: -- [kcl.py](https://github.com/kittycad/kcl.py) -- [kcl-lsp](https://github.com/kittycad/kcl-lsp) - [cli](https://github.com/kittycad/cli) diff --git a/rust/kcl-lib/src/engine/conn.rs b/rust/kcl-lib/src/engine/conn.rs index ea7f06785..6419de1e3 100644 --- a/rust/kcl-lib/src/engine/conn.rs +++ b/rust/kcl-lib/src/engine/conn.rs @@ -205,8 +205,8 @@ impl EngineConnection { pub async fn new(ws: reqwest::Upgraded) -> Result { let wsconfig = tokio_tungstenite::tungstenite::protocol::WebSocketConfig { // 4294967296 bytes, which is around 4.2 GB. - max_message_size: Some(0x100000000), - max_frame_size: Some(0x100000000), + max_message_size: Some(usize::MAX), + max_frame_size: Some(usize::MAX), ..Default::default() }; diff --git a/rust/kcl-python-bindings/Cargo.toml b/rust/kcl-python-bindings/Cargo.toml index 6c2762b9d..41a6f1a96 100644 --- a/rust/kcl-python-bindings/Cargo.toml +++ b/rust/kcl-python-bindings/Cargo.toml @@ -24,3 +24,6 @@ serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } uuid = { workspace = true, features = ["v4"] } + +[lints] +workspace = true diff --git a/tsconfig.json b/tsconfig.json index 5ad3581bf..4dd68fb00 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,6 +37,6 @@ "jsx": "react-jsx" }, "include": ["src", "e2e", "packages", "*.ts", "rust"], - "exclude": ["node_modules", "./*.grammar", "vite.config.ts"], + "exclude": ["node_modules", "./*.grammar", "vite.config.ts", ".vscode-test"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/vite.config.ts b/vite.config.ts index e6ba34043..3fb1b5d38 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -34,7 +34,7 @@ const config = defineConfig({ coverage: { provider: 'istanbul', // or 'v8' }, - exclude: [...configDefaults.exclude, '**/e2e/**/*'], + exclude: [...configDefaults.exclude, '**/e2e/**/*', 'rust'], deps: { optimizer: { web: {