@smbcloud / cli / commits / 41cb0e2

Add npm, NuGet, and PyPI distribution for the xcrs binary

Extend the xcrs binary to ship through the same package managers as the smb CLI (npm, NuGet, PyPI), wired into the tag-driven release orchestration. crates.io already covers xcrs via cargo-workspaces publish. xcrs builds fully standalone (reqwest+rustls, no smbcloud-* or openssl deps), so its workflows drop CLI_CLIENT_SECRET, GH_OAUTH_*, OpenSSL vendoring, and the manylinux perl-core step. The binary name equals the crate name, so the PyPI package is simply 'xcrs' with no stub. - Scaffold npm/xcrs (@smbcloud/xcrs + platform packages), pypi-xcrs (xcrs), and nuget/xcrs (SmbCloud.Xcrs). - Generalize the npm package generators to take a product identity, keeping smb output byte-identical. - Add release-xcrs-{npm,nuget,pypi}.yml and fan them out from release-crate.yml's dispatch-distributions job. - Extend sync/check-release-versions scripts for the new manifests. Release Notes: - The xcrs MCP CLI can now be installed via npm (@smbcloud/xcrs), pip (xcrs), and dotnet tool (SmbCloud.Xcrs), in addition to cargo install xcrs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Seto Elkahfi committed Aug 3, 2026 at 11:48 UTC 41cb0e29fdb5685a52e3c2d927c624828a2b3db8
20 files changed +3333 -46
.github/workflows/release-crate.yml
+42
@@ -217,6 +217,48 @@ jobs:
217 }
218 })
219
220 + - name: Trigger npm XCRS release
221 + uses: actions/github-script@v7
222 + with:
223 + script: |
224 + await github.rest.actions.createWorkflowDispatch({
225 + owner: context.repo.owner,
226 + repo: context.repo.repo,
227 + workflow_id: 'release-xcrs-npm.yml',
228 + ref: '${{ needs.publish.outputs.tag }}',
229 + inputs: {
230 + tag: '${{ needs.publish.outputs.tag }}'
231 + }
232 + })
233 +
234 + - name: Trigger NuGet XCRS release
235 + uses: actions/github-script@v7
236 + with:
237 + script: |
238 + await github.rest.actions.createWorkflowDispatch({
239 + owner: context.repo.owner,
240 + repo: context.repo.repo,
241 + workflow_id: 'release-xcrs-nuget.yml',
242 + ref: '${{ needs.publish.outputs.tag }}',
243 + inputs: {
244 + tag: '${{ needs.publish.outputs.tag }}'
245 + }
246 + })
247 +
248 + - name: Trigger PyPI XCRS release
249 + uses: actions/github-script@v7
250 + with:
251 + script: |
252 + await github.rest.actions.createWorkflowDispatch({
253 + owner: context.repo.owner,
254 + repo: context.repo.repo,
255 + workflow_id: 'release-xcrs-pypi.yml',
256 + ref: '${{ needs.publish.outputs.tag }}',
257 + inputs: {
258 + tag: '${{ needs.publish.outputs.tag }}'
259 + }
260 + })
261 +
262 dispatch-sdk-pypi:
263 name: Trigger SDK PyPI release
264 needs: publish
.github/workflows/release-xcrs-npm.yml new
+197
@@ -0,0 +1,197 @@
1 +name: NPM XCRS Release
2 +
3 +on:
4 + workflow_dispatch:
5 + inputs:
6 + tag:
7 + description: "Release tag (e.g. v0.3.39)"
8 + required: true
9 +
10 +permissions:
11 + id-token: write
12 + contents: read
13 +
14 +jobs:
15 + publish-npm-binaries:
16 + name: Publish NPM packages
17 + runs-on: ${{ matrix.build.OS }}
18 + strategy:
19 + fail-fast: false
20 + matrix:
21 + build:
22 + - {
23 + NAME: linux-x64-glibc,
24 + OS: ubuntu-latest,
25 + TARGET: x86_64-unknown-linux-gnu,
26 + }
27 + - {
28 + NAME: linux-arm64-glibc,
29 + OS: ubuntu-24.04-arm,
30 + TARGET: aarch64-unknown-linux-gnu,
31 + }
32 + - {
33 + NAME: win32-x64-msvc,
34 + OS: windows-2022,
35 + TARGET: x86_64-pc-windows-msvc,
36 + }
37 + - {
38 + NAME: win32-arm64-msvc,
39 + OS: windows-2022,
40 + TARGET: aarch64-pc-windows-msvc,
41 + }
42 + - {
43 + NAME: darwin-x64,
44 + OS: macos-15-intel,
45 + TARGET: x86_64-apple-darwin,
46 + }
47 + - {
48 + NAME: darwin-arm64,
49 + OS: macos-latest,
50 + TARGET: aarch64-apple-darwin,
51 + }
52 + steps:
53 + - name: Checkout
54 + uses: actions/checkout@v6
55 + with:
56 + ref: ${{ github.event.inputs.tag || github.ref }}
57 +
58 + - name: Set the release version
59 + shell: bash
60 + run: |
61 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
62 + release_version="${GITHUB_REF_NAME#v}"
63 + else
64 + release_version="${{ github.event.inputs.tag }}"
65 + release_version="${release_version#v}"
66 + fi
67 +
68 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
69 +
70 + - name: Read Rust toolchain
71 + shell: bash
72 + run: |
73 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
74 + if [ -z "$rust_toolchain" ]; then
75 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
76 + exit 1
77 + fi
78 +
79 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
80 +
81 + - name: Install toolkit
82 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
83 + with:
84 + toolchain: ${{ env.RUST_TOOLCHAIN }}
85 +
86 + - name: Install Rust target
87 + shell: bash
88 + run: |
89 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
90 + rustup target list --installed
91 +
92 + - name: Build
93 + shell: bash
94 + run: |
95 + cargo build --release --locked --target ${{ matrix.build.TARGET }} --package xcrs
96 +
97 + - name: Install node
98 + uses: actions/setup-node@v6
99 + with:
100 + node-version-file: .nvmrc
101 + registry-url: "https://registry.npmjs.org"
102 +
103 + - name: Publish to NPM
104 + env:
105 + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
106 + shell: bash
107 + run: |
108 + # We want to name our npm package @smbcloud/xcrs, and the command is xcrs.
109 + # All optional platform dependencies follow the @smbcloud/xcrs-${os}-${arch}
110 + # naming convention.
111 +
112 + # Move to the npm directory
113 + cd npm
114 + # set the binary name, this is from the rust Cargo.toml file
115 + cargo_bin="xcrs"
116 + node_pkg_prefix="xcrs"
117 + # derive the OS and architecture from the build matrix name
118 + # note: when split by a hyphen, first part is the OS and the second is the architecture
119 + node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
120 + export node_os
121 + node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
122 + export node_arch
123 + # set the version
124 + export node_version="${{ env.RELEASE_VERSION }}"
125 + # set the package name
126 + # note: use 'windows' as OS name instead of 'win32'
127 + if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
128 + export node_pkg="${node_pkg_prefix}-windows-${node_arch}"
129 + else
130 + export node_pkg="${node_pkg_prefix}-${node_os}-${node_arch}"
131 + fi
132 + # create the package directory
133 + mkdir -p "${node_pkg}/bin"
134 + # generate package metadata
135 + node ./scripts/render-platform-package.cjs "${node_pkg}" "${node_version}" "${node_os}" "${node_arch}" "Platform binary for the xcrs CLI."
136 + # copy the binary into the package
137 + # note: windows binaries has '.exe' extension
138 + if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
139 + cargo_bin="${cargo_bin}.exe"
140 + fi
141 + cp "../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
142 + # publish the package
143 + cd "${node_pkg}"
144 + npm_package_name="@smbcloud/${node_pkg}"
145 + if npm view "${npm_package_name}@${node_version}" version >/dev/null 2>&1; then
146 + echo "${npm_package_name}@${node_version} already exists on npm, skipping publish"
147 + exit 0
148 + fi
149 + npm publish --access public
150 +
151 + publish-npm-base:
152 + name: Publish the base NPM package
153 + needs: publish-npm-binaries
154 + runs-on: ubuntu-latest
155 + steps:
156 + - name: Checkout
157 + uses: actions/checkout@v6
158 + with:
159 + ref: ${{ github.event.inputs.tag || github.ref }}
160 +
161 + - name: Set the release version
162 + shell: bash
163 + run: |
164 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
165 + release_version="${GITHUB_REF_NAME#v}"
166 + else
167 + release_version="${{ github.event.inputs.tag }}"
168 + release_version="${release_version#v}"
169 + fi
170 +
171 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
172 +
173 + - name: Install node
174 + uses: actions/setup-node@v6
175 + with:
176 + node-version-file: .nvmrc
177 + registry-url: "https://registry.npmjs.org"
178 +
179 + - name: Publish the package
180 + env:
181 + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
182 + shell: bash
183 + run: |
184 + cd npm/xcrs
185 +
186 + node ../scripts/render-main-package.cjs "./package.json" "${{ env.RELEASE_VERSION }}" xcrs
187 +
188 + npm_package_name="@smbcloud/xcrs"
189 + npm_package_version="${{ env.RELEASE_VERSION }}"
190 + if npm view "${npm_package_name}@${npm_package_version}" version >/dev/null 2>&1; then
191 + echo "${npm_package_name}@${npm_package_version} already exists on npm, skipping publish"
192 + exit 0
193 + fi
194 +
195 + npm install
196 + npm run build
197 + npm publish --access public
.github/workflows/release-xcrs-nuget.yml new
+285
@@ -0,0 +1,285 @@
1 +name: NuGet XCRS Release
2 +
3 +on:
4 + workflow_dispatch:
5 + inputs:
6 + tag:
7 + description: "Release tag (e.g. v0.3.39)"
8 + required: true
9 +
10 +permissions:
11 + contents: read
12 +
13 +env:
14 + CARGO_TERM_COLOR: always
15 + DOTNET_VERSION: 8.0.x
16 + NUGET_PACKAGE_ID: SmbCloud.Xcrs
17 +
18 +jobs:
19 + build-native-binaries:
20 + name: Build native binary (${{ matrix.build.NAME }})
21 + runs-on: ${{ matrix.build.OS }}
22 + strategy:
23 + fail-fast: false
24 + matrix:
25 + build:
26 + - {
27 + NAME: linux-x64,
28 + OS: ubuntu-latest,
29 + TARGET: x86_64-unknown-linux-gnu,
30 + }
31 + - {
32 + NAME: linux-arm64,
33 + OS: ubuntu-24.04-arm,
34 + TARGET: aarch64-unknown-linux-gnu,
35 + }
36 + - {
37 + NAME: windows-x64,
38 + OS: windows-2022,
39 + TARGET: x86_64-pc-windows-msvc,
40 + }
41 + - {
42 + NAME: windows-arm64,
43 + OS: windows-2022,
44 + TARGET: aarch64-pc-windows-msvc,
45 + }
46 + - {
47 + NAME: darwin-x64,
48 + OS: macos-15-intel,
49 + TARGET: x86_64-apple-darwin,
50 + }
51 + - {
52 + NAME: darwin-arm64,
53 + OS: macos-latest,
54 + TARGET: aarch64-apple-darwin,
55 + }
56 + steps:
57 + - name: Checkout
58 + uses: actions/checkout@v6
59 + with:
60 + ref: ${{ github.event.inputs.tag || github.ref }}
61 +
62 + - name: Set the release version
63 + shell: bash
64 + run: |
65 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
66 + release_version="${GITHUB_REF_NAME#v}"
67 + else
68 + release_version="${{ github.event.inputs.tag }}"
69 + release_version="${release_version#v}"
70 + fi
71 +
72 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
73 +
74 + - name: Read Rust toolchain
75 + shell: bash
76 + run: |
77 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
78 + if [ -z "$rust_toolchain" ]; then
79 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
80 + exit 1
81 + fi
82 +
83 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
84 +
85 + - name: Install toolkit
86 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
87 + with:
88 + toolchain: ${{ env.RUST_TOOLCHAIN }}
89 + targets: ${{ matrix.build.TARGET }}
90 +
91 + - name: Setup Rust cache
92 + uses: Swatinem/rust-cache@v2
93 + with:
94 + key: nuget-xcrs-${{ matrix.build.TARGET }}
95 +
96 + - name: Build
97 + shell: bash
98 + run: cargo build --release --locked --target ${{ matrix.build.TARGET }} --package xcrs
99 +
100 + - name: Prepare artifact
101 + shell: bash
102 + run: |
103 + executable_name="xcrs"
104 + if [[ "${{ matrix.build.OS }}" == "windows-2022" ]]; then
105 + executable_name="xcrs.exe"
106 + fi
107 +
108 + mkdir -p "nuget-artifacts/native/${{ matrix.build.NAME }}"
109 + cp "target/${{ matrix.build.TARGET }}/release/${executable_name}" "nuget-artifacts/native/${{ matrix.build.NAME }}/${executable_name}"
110 +
111 + - name: Upload native artifact
112 + uses: actions/upload-artifact@v7
113 + with:
114 + name: nuget-xcrs-native-${{ matrix.build.NAME }}
115 + path: nuget-artifacts/native
116 +
117 + pack-nuget:
118 + name: Pack NuGet .NET tool
119 + runs-on: ubuntu-latest
120 + needs: build-native-binaries
121 + steps:
122 + - name: Checkout
123 + uses: actions/checkout@v6
124 + with:
125 + ref: ${{ github.event.inputs.tag || github.ref }}
126 +
127 + - name: Set the release version
128 + shell: bash
129 + run: |
130 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
131 + release_version="${GITHUB_REF_NAME#v}"
132 + else
133 + release_version="${{ github.event.inputs.tag }}"
134 + release_version="${release_version#v}"
135 + fi
136 +
137 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
138 +
139 + - name: Download native artifacts
140 + uses: actions/download-artifact@v7
141 + with:
142 + pattern: nuget-xcrs-native-*
143 + path: nuget/xcrs/native
144 + merge-multiple: true
145 +
146 + - name: Setup .NET SDK
147 + uses: actions/setup-dotnet@v4
148 + with:
149 + dotnet-version: ${{ env.DOTNET_VERSION }}
150 +
151 + - name: Pack .NET tool
152 + shell: bash
153 + run: |
154 + dotnet pack nuget/xcrs/Xcrs.csproj \
155 + --configuration Release \
156 + --output nuget/dist \
157 + -p:PackageVersion=${RELEASE_VERSION}
158 +
159 + - name: Upload package artifact
160 + uses: actions/upload-artifact@v7
161 + with:
162 + name: nuget-xcrs-package
163 + path: nuget/dist/*.nupkg
164 +
165 + smoke-test:
166 + name: Smoke test (${{ matrix.os }})
167 + runs-on: ${{ matrix.os }}
168 + needs: pack-nuget
169 + strategy:
170 + fail-fast: false
171 + matrix:
172 + os:
173 + - ubuntu-latest
174 + - windows-2022
175 + - macos-latest
176 + steps:
177 + - name: Checkout
178 + uses: actions/checkout@v6
179 + with:
180 + ref: ${{ github.event.inputs.tag || github.ref }}
181 +
182 + - name: Set the release version
183 + shell: bash
184 + run: |
185 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
186 + release_version="${GITHUB_REF_NAME#v}"
187 + else
188 + release_version="${{ github.event.inputs.tag }}"
189 + release_version="${release_version#v}"
190 + fi
191 +
192 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
193 +
194 + - name: Download package artifact
195 + uses: actions/download-artifact@v7
196 + with:
197 + name: nuget-xcrs-package
198 + path: nuget/dist
199 +
200 + - name: Setup .NET SDK
201 + uses: actions/setup-dotnet@v4
202 + with:
203 + dotnet-version: ${{ env.DOTNET_VERSION }}
204 +
205 + - name: Install tool from local package
206 + shell: pwsh
207 + run: |
208 + $packageSource = (Resolve-Path "nuget/dist").Path
209 + @"
210 + <?xml version="1.0" encoding="utf-8"?>
211 + <configuration>
212 + <packageSources>
213 + <clear />
214 + <add key="local" value="$packageSource" />
215 + </packageSources>
216 + </configuration>
217 + "@ | Set-Content -Path "nuget/NuGet.Config"
218 +
219 + dotnet tool install `
220 + --tool-path ".tool" `
221 + --configfile "nuget/NuGet.Config" `
222 + --version "$env:RELEASE_VERSION" `
223 + "$env:NUGET_PACKAGE_ID"
224 +
225 + - name: Run xcrs --version
226 + shell: pwsh
227 + run: |
228 + $toolPath = if ($IsWindows) { ".\.tool\xcrs.exe" } else { "./.tool/xcrs" }
229 + & $toolPath --version
230 +
231 + publish-nuget:
232 + name: Publish to NuGet
233 + runs-on: ubuntu-latest
234 + needs: smoke-test
235 + steps:
236 + - name: Checkout
237 + uses: actions/checkout@v6
238 + with:
239 + ref: ${{ github.event.inputs.tag || github.ref }}
240 +
241 + - name: Set the release version
242 + shell: bash
243 + run: |
244 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
245 + release_version="${GITHUB_REF_NAME#v}"
246 + else
247 + release_version="${{ github.event.inputs.tag }}"
248 + release_version="${release_version#v}"
249 + fi
250 +
251 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
252 +
253 + - name: Download package artifact
254 + uses: actions/download-artifact@v7
255 + with:
256 + name: nuget-xcrs-package
257 + path: nuget/dist
258 +
259 + - name: Setup .NET SDK
260 + uses: actions/setup-dotnet@v4
261 + with:
262 + dotnet-version: ${{ env.DOTNET_VERSION }}
263 +
264 + - name: Check whether release already exists on NuGet
265 + id: nuget-check
266 + shell: bash
267 + run: |
268 + package_index_url="https://api.nuget.org/v3-flatcontainer/smbcloud.xcrs/index.json"
269 + if curl -fsS "${package_index_url}" | grep -F "\"${RELEASE_VERSION}\"" >/dev/null; then
270 + echo "${NUGET_PACKAGE_ID} ${RELEASE_VERSION} already exists on NuGet, skipping publish"
271 + echo "exists=true" >> "$GITHUB_OUTPUT"
272 + else
273 + echo "exists=false" >> "$GITHUB_OUTPUT"
274 + fi
275 +
276 + - name: Publish package
277 + if: steps.nuget-check.outputs.exists != 'true'
278 + env:
279 + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
280 + shell: bash
281 + run: |
282 + dotnet nuget push nuget/dist/*.nupkg \
283 + --api-key "${NUGET_API_KEY}" \
284 + --source https://api.nuget.org/v3/index.json \
285 + --skip-duplicate
.github/workflows/release-xcrs-pypi.yml new
+204
@@ -0,0 +1,204 @@
1 +name: PyPI XCRS Release
2 +
3 +# Windows arm64 wheels are intentionally not built here. GitHub's hosted
4 +# Windows runners provide x64 Python, and maturin refuses to build an arm64
5 +# wheel when the interpreter reports win-amd64.
6 +
7 +on:
8 + workflow_dispatch:
9 + inputs:
10 + tag:
11 + description: "Release tag (e.g. v0.3.39)"
12 + required: true
13 +
14 +permissions:
15 + id-token: write
16 + contents: read
17 +
18 +env:
19 + CARGO_TERM_COLOR: always
20 +
21 +jobs:
22 + build-wheels:
23 + name: Build PyPI wheels
24 + runs-on: ${{ matrix.build.OS }}
25 + strategy:
26 + fail-fast: false
27 + matrix:
28 + build:
29 + - {
30 + NAME: linux-x64-glibc,
31 + OS: ubuntu-latest,
32 + TARGET: x86_64-unknown-linux-gnu,
33 + MANYLINUX: "2014",
34 + }
35 + - {
36 + NAME: linux-arm64-glibc,
37 + OS: ubuntu-24.04-arm,
38 + TARGET: aarch64-unknown-linux-gnu,
39 + MANYLINUX: "2014",
40 + }
41 + - {
42 + NAME: win32-x64-msvc,
43 + OS: windows-2022,
44 + TARGET: x86_64-pc-windows-msvc,
45 + }
46 +
47 + - { NAME: darwin-x64, OS: macos-latest, TARGET: x86_64-apple-darwin }
48 + - {
49 + NAME: darwin-arm64,
50 + OS: macos-latest,
51 + TARGET: aarch64-apple-darwin,
52 + }
53 + steps:
54 + - name: Checkout
55 + uses: actions/checkout@v6
56 + with:
57 + ref: ${{ github.event.inputs.tag || github.ref }}
58 +
59 + - name: Set the release version
60 + shell: bash
61 + run: |
62 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
63 + release_version="${GITHUB_REF_NAME#v}"
64 + else
65 + release_version="${{ github.event.inputs.tag }}"
66 + release_version="${release_version#v}"
67 + fi
68 +
69 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
70 +
71 + - name: Read Rust toolchain
72 + shell: bash
73 + run: |
74 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
75 + if [ -z "$rust_toolchain" ]; then
76 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
77 + exit 1
78 + fi
79 +
80 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
81 +
82 + - name: Install toolkit
83 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
84 + with:
85 + toolchain: ${{ env.RUST_TOOLCHAIN }}
86 +
87 + - name: Install Rust target
88 + shell: bash
89 + run: |
90 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
91 + rustup target list --installed
92 +
93 + - name: Build wheel
94 + uses: PyO3/maturin-action@v1
95 + with:
96 + target: ${{ matrix.build.TARGET }}
97 + manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
98 + working-directory: pypi-xcrs
99 + args: --release --locked --compatibility pypi --out dist
100 +
101 + - name: Upload wheel artifact
102 + uses: actions/upload-artifact@v7
103 + with:
104 + name: wheels-${{ matrix.build.NAME }}
105 + path: pypi-xcrs/dist/*
106 +
107 + build-sdist:
108 + name: Build source distribution
109 + runs-on: ubuntu-latest
110 + steps:
111 + - name: Checkout
112 + uses: actions/checkout@v6
113 + with:
114 + ref: ${{ github.event.inputs.tag || github.ref }}
115 +
116 + - name: Set the release version
117 + shell: bash
118 + run: |
119 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
120 + release_version="${GITHUB_REF_NAME#v}"
121 + else
122 + release_version="${{ github.event.inputs.tag }}"
123 + release_version="${release_version#v}"
124 + fi
125 +
126 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
127 +
128 + - name: Read Rust toolchain
129 + shell: bash
130 + run: |
131 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
132 + if [ -z "$rust_toolchain" ]; then
133 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
134 + exit 1
135 + fi
136 +
137 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
138 +
139 + - name: Install toolkit
140 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
141 + with:
142 + toolchain: ${{ env.RUST_TOOLCHAIN }}
143 +
144 + - name: Build sdist
145 + uses: PyO3/maturin-action@v1
146 + with:
147 + command: sdist
148 + working-directory: pypi-xcrs
149 + args: --out dist
150 +
151 + - name: Upload sdist artifact
152 + uses: actions/upload-artifact@v7
153 + with:
154 + name: sdist
155 + path: pypi-xcrs/dist/*
156 +
157 + publish-pypi:
158 + name: Publish to PyPI
159 + runs-on: ubuntu-latest
160 + needs:
161 + - build-wheels
162 + - build-sdist
163 +
164 + steps:
165 + - name: Checkout
166 + uses: actions/checkout@v6
167 + with:
168 + ref: ${{ github.event.inputs.tag || github.ref }}
169 +
170 + - name: Set the release version
171 + shell: bash
172 + run: |
173 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
174 + release_version="${GITHUB_REF_NAME#v}"
175 + else
176 + release_version="${{ github.event.inputs.tag }}"
177 + release_version="${release_version#v}"
178 + fi
179 +
180 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
181 +
182 + - name: Download distribution artifacts
183 + uses: actions/download-artifact@v7
184 + with:
185 + pattern: "*"
186 + path: dist
187 + merge-multiple: true
188 +
189 + - name: Check whether release already exists on PyPI
190 + id: pypi-check
191 + shell: bash
192 + run: |
193 + if curl -fsS "https://pypi.org/pypi/xcrs/${RELEASE_VERSION}/json" >/dev/null 2>&1; then
194 + echo "xcrs ${RELEASE_VERSION} already exists on PyPI, skipping publish"
195 + echo "exists=true" >> "$GITHUB_OUTPUT"
196 + else
197 + echo "exists=false" >> "$GITHUB_OUTPUT"
198 + fi
199 +
200 + - name: Publish distribution
201 + if: steps.pypi-check.outputs.exists != 'true'
202 + uses: pypa/gh-action-pypi-publish@release/v1
203 + with:
204 + skip-existing: true
npm/scripts/render-main-package.cjs
+96 -43
@@ -3,51 +3,110 @@
3 const fs = require("fs");
4 const path = require("path");
5
6 -const [outputPath, version] = process.argv.slice(2);
6 +const [outputPath, version, product = "smb"] = process.argv.slice(2);
7
8 if (!outputPath || !version) {
9 - throw new Error("Usage: render-main-package.cjs <output-path> <version>");
9 + throw new Error("Usage: render-main-package.cjs <output-path> <version> [product]");
10 +}
11 +
12 +// The five platform binary packages the wrapper resolves at runtime. Kept in
13 +// lockstep with the release build matrix and the `optionalDependencies` below.
14 +const platformSuffixes = [
15 + "darwin-arm64",
16 + "darwin-x64",
17 + "linux-x64",
18 + "windows-arm64",
19 + "windows-x64",
20 +];
21 +
22 +const products = {
23 + smb: {
24 + name: "@smbcloud/cli",
25 + // Ownership proof for the MCP Registry: must match `name` in ../../server.json.
26 + mcpName: "io.github.smbcloudXYZ/smbcloud-cli",
27 + binName: "smb",
28 + platformPrefix: "cli",
29 + description: "A CLI for accessing the smbCloud platform.",
30 + keywords: [
31 + "smbcloud",
32 + "cli",
33 + "smb",
34 + "pndk",
35 + "smbcloud-cli",
36 + "cloud",
37 + "smbcloud",
38 + "developer",
39 + "tools",
40 + "web3",
41 + "web3js",
42 + "web3.js",
43 + "web3js",
44 + "bitcoin",
45 + "btc",
46 + "ethereum",
47 + "solana",
48 + "eth",
49 + "sol",
50 + "blockchain",
51 + "smart-contracts",
52 + "dapps",
53 + "dapp",
54 + "dapp-tools",
55 + "dapp-tool",
56 + "dapp-toolkit",
57 + "dapp-toolkit-cli",
58 + ],
59 + },
60 + xcrs: {
61 + name: "@smbcloud/xcrs",
62 + // Ownership proof for the MCP Registry: must match `name` in ../../server-xcrs.json.
63 + mcpName: "io.github.smbcloudXYZ/xcrs",
64 + binName: "xcrs",
65 + platformPrefix: "xcrs",
66 + description: "Cross-platform mobile and TV app automation over MCP.",
67 + keywords: [
68 + "xcrs",
69 + "mcp",
70 + "model-context-protocol",
71 + "mobile",
72 + "ios",
73 + "android",
74 + "tv",
75 + "apple-tv",
76 + "android-tv",
77 + "automation",
78 + "app-testing",
79 + "device",
80 + "simulator",
81 + "adb",
82 + "cli",
83 + ],
84 + },
85 +};
86 +
87 +const selected = products[product];
88 +
89 +if (!selected) {
90 + throw new Error(
91 + `Unknown product "${product}". Expected one of: ${Object.keys(products).join(", ")}.`
92 + );
93 +}
94 +
95 +const optionalDependencies = {};
96 +for (const suffix of platformSuffixes) {
97 + optionalDependencies[`@smbcloud/${selected.platformPrefix}-${suffix}`] = version;
98 }
99
100 const packageJson = {
13 - name: "@smbcloud/cli",
101 + name: selected.name,
102 version,
15 - // Ownership proof for the MCP Registry: must match `name` in ../../server.json.
16 - mcpName: "io.github.smbcloudXYZ/smbcloud-cli",
17 - keywords: [
18 - "smbcloud",
19 - "cli",
20 - "smb",
21 - "pndk",
22 - "smbcloud-cli",
23 - "cloud",
24 - "smbcloud",
25 - "developer",
26 - "tools",
27 - "web3",
28 - "web3js",
29 - "web3.js",
30 - "web3js",
31 - "bitcoin",
32 - "btc",
33 - "ethereum",
34 - "solana",
35 - "eth",
36 - "sol",
37 - "blockchain",
38 - "smart-contracts",
39 - "dapps",
40 - "dapp",
41 - "dapp-tools",
42 - "dapp-tool",
43 - "dapp-toolkit",
44 - "dapp-toolkit-cli",
45 - ],
103 + mcpName: selected.mcpName,
104 + keywords: selected.keywords,
105 bin: {
47 - smb: "lib/index.js",
106 + [selected.binName]: "lib/index.js",
107 },
108 files: ["lib", "README.md"],
50 - description: "A CLI for accessing the smbCloud platform.",
109 + description: selected.description,
110 license: "Apache-2.0",
111 repository: {
112 type: "git",
@@ -67,13 +126,7 @@ const packageJson = {
126 eslint: "^8.31.0",
127 typescript: "^5.0.0",
128 },
70 - optionalDependencies: {
71 - "@smbcloud/cli-darwin-arm64": version,
72 - "@smbcloud/cli-darwin-x64": version,
73 - "@smbcloud/cli-linux-x64": version,
74 - "@smbcloud/cli-windows-arm64": version,
75 - "@smbcloud/cli-windows-x64": version,
76 - },
129 + optionalDependencies,
130 };
131
132 fs.writeFileSync(path.resolve(outputPath), `${JSON.stringify(packageJson, null, 2)}
npm/scripts/render-platform-package.cjs
+3 -3
@@ -3,11 +3,11 @@
3 const fs = require("fs");
4 const path = require("path");
5
6 -const [packageName, version, operatingSystem, architecture] = process.argv.slice(2);
6 +const [packageName, version, operatingSystem, architecture, description] = process.argv.slice(2);
7
8 if (!packageName || !version || !operatingSystem || !architecture) {
9 throw new Error(
10 - "Usage: render-platform-package.cjs <package-name> <version> <os> <arch>"
10 + "Usage: render-platform-package.cjs <package-name> <version> <os> <arch> [description]"
11 );
12 }
13
@@ -18,7 +18,7 @@ fs.mkdirSync(packageDirectory, { recursive: true });
18 const packageJson = {
19 name: `@smbcloud/${packageName}`,
20 version,
21 - description: "Platform binary for the smbCloud CLI.",
21 + description: description || "Platform binary for the smbCloud CLI.",
22 license: "Apache-2.0",
23 repository: {
24 type: "git",
npm/xcrs/.gitignore new
+133
@@ -0,0 +1,133 @@
1 +# Typescript build artifacts
2 +lib
3 +
4 +# Logs
5 +logs
6 +*.log
7 +npm-debug.log*
8 +yarn-debug.log*
9 +yarn-error.log*
10 +lerna-debug.log*
11 +.pnpm-debug.log*
12 +
13 +# Diagnostic reports (https://nodejs.org/api/report.html)
14 +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
15 +
16 +# Runtime data
17 +pids
18 +*.pid
19 +*.seed
20 +*.pid.lock
21 +
22 +# Directory for instrumented libs generated by jscoverage/JSCover
23 +lib-cov
24 +
25 +# Coverage directory used by tools like istanbul
26 +coverage
27 +*.lcov
28 +
29 +# nyc test coverage
30 +.nyc_output
31 +
32 +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
33 +.grunt
34 +
35 +# Bower dependency directory (https://bower.io/)
36 +bower_components
37 +
38 +# node-waf configuration
39 +.lock-wscript
40 +
41 +# Compiled binary addons (https://nodejs.org/api/addons.html)
42 +build/Release
43 +
44 +# Dependency directories
45 +node_modules/
46 +jspm_packages/
47 +
48 +# Snowpack dependency directory (https://snowpack.dev/)
49 +web_modules/
50 +
51 +# TypeScript cache
52 +*.tsbuildinfo
53 +
54 +# Optional npm cache directory
55 +.npm
56 +
57 +# Optional eslint cache
58 +.eslintcache
59 +
60 +# Optional stylelint cache
61 +.stylelintcache
62 +
63 +# Microbundle cache
64 +.rpt2_cache/
65 +.rts2_cache_cjs/
66 +.rts2_cache_es/
67 +.rts2_cache_umd/
68 +
69 +# Optional REPL history
70 +.node_repl_history
71 +
72 +# Output of 'npm pack'
73 +*.tgz
74 +
75 +# Yarn Integrity file
76 +.yarn-integrity
77 +
78 +# dotenv environment variable files
79 +.env
80 +.env.development.local
81 +.env.test.local
82 +.env.production.local
83 +.env.local
84 +
85 +# parcel-bundler cache (https://parceljs.org/)
86 +.cache
87 +.parcel-cache
88 +
89 +# Next.js build output
90 +.next
91 +out
92 +
93 +# Nuxt.js build / generate output
94 +.nuxt
95 +dist
96 +
97 +# Gatsby files
98 +.cache/
99 +# Comment in the public line in if your project uses Gatsby and not Next.js
100 +# https://nextjs.org/blog/next-9-1#public-directory-support
101 +# public
102 +
103 +# vuepress build output
104 +.vuepress/dist
105 +
106 +# vuepress v2.x temp and cache directory
107 +.temp
108 +.cache
109 +
110 +# Docusaurus cache and generated files
111 +.docusaurus
112 +
113 +# Serverless directories
114 +.serverless/
115 +
116 +# FuseBox cache
117 +.fusebox/
118 +
119 +# DynamoDB Local files
120 +.dynamodb/
121 +
122 +# TernJS port file
123 +.tern-port
124 +
125 +# Stores VSCode versions used for testing VSCode extensions
126 +.vscode-test
127 +
128 +# yarn v2
129 +.yarn/cache
130 +.yarn/unplugged
131 +.yarn/build-state.yml
132 +.yarn/install-state.gz
133 +.pnp.*
\ No newline at end of file
npm/xcrs/README.md new
+87
@@ -0,0 +1,87 @@
1 +<!-- LOGO -->
2 +<h1>
3 +<p align="center">
4 + <img src="https://avatars.githubusercontent.com/u/89791739?s=200&v=4" alt="smbCloud Logo" width="128">
5 + <br>xcrs
6 +</h1>
7 + <p align="center">
8 + Cross-platform mobile and TV app automation over MCP.
9 + <br />
10 + <br />
11 + <a href="https://smbcloud.xyz/">Website</a>
12 + ·
13 + <a href="https://smbcloud.xyz/posts">Documentation</a>
14 + ·
15 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/releases">Releases</a>
16 + ·
17 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/issues">Issues</a>
18 + </p>
19 + <p align="center">
20 + <a href="https://www.npmjs.com/package/@smbcloud/xcrs"><img alt="npm" src="https://img.shields.io/npm/v/@smbcloud/xcrs"></a>
21 + <a href="https://www.nuget.org/packages/SmbCloud.Xcrs"><img alt="NuGet" src="https://img.shields.io/nuget/v/SmbCloud.Xcrs"></a>
22 + <a href="https://pypi.org/project/xcrs/"><img alt="PyPI" src="https://img.shields.io/pypi/v/xcrs"></a>
23 + <a href="https://crates.io/crates/xcrs"><img alt="Crates.io" src="https://img.shields.io/crates/v/xcrs"></a>
24 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/smbcloudXYZ/smbcloud-cli"></a>
25 + </p>
26 +</p>
27 +
28 +## About
29 +
30 +**`xcrs`** drives mobile and TV apps — on iOS simulators, physical Apple
31 +devices, and adb-connected Android phones, tablets, emulators, and TVs — through
32 +the [Model Context Protocol](https://modelcontextprotocol.io/). It is the
33 +standalone automation profile of the [smbCloud CLI](https://smbcloud.xyz/); the
34 +same tools are also available via `smb --mcp --scope automation`.
35 +
36 +This package installs the native `xcrs` executable for your platform directly —
37 +no runtime dependencies.
38 +
39 +## Install
40 +
41 +```sh
42 +npm install -g @smbcloud/xcrs
43 +```
44 +
45 +## Quick start
46 +
47 +Run it as an MCP server over stdio and point your MCP client at it:
48 +
49 +```sh
50 +xcrs --mcp
51 +```
52 +
53 +**Recommended flow:** `device_list` → `device_select` → `device_capabilities`,
54 +then inspect with `screen_capture` / `ui_describe` and drive with the `input_*`
55 +tools.
56 +
57 +## Other installation methods
58 +
59 +- Cargo: `cargo install xcrs`
60 +- pip: `pip install xcrs`
61 +- NuGet: `dotnet tool install --global SmbCloud.Xcrs`
62 +
63 +## Platform support
64 +
65 +| Platform | Architecture |
66 +| ------------- | ------------ |
67 +| macOS | arm64, x64 |
68 +| Linux (glibc) | arm64, x64 |
69 +| Windows | arm64, x64 |
70 +
71 +The full Apple automation surface (`ui_describe`, `ui_element_list`, simulator
72 +control) requires macOS with Xcode command-line tools. Android automation over
73 +`adb` works from any platform.
74 +
75 +## Source
76 +
77 +- Repository: <https://github.com/smbcloudXYZ/smbcloud-cli>
78 +- Documentation: <https://smbcloud.xyz/posts>
79 +- Issues: <https://github.com/smbcloudXYZ/smbcloud-cli/issues>
80 +
81 +## License
82 +
83 +Apache-2.0
84 +
85 +## Copyright
86 +
87 +© 2026 [Splitfire AB](https://5mb.app) ([smbCloud](https://smbcloud.xyz)).
npm/xcrs/package-lock.json new
+1790
@@ -0,0 +1,1790 @@
1 +{
2 + "name": "@smbcloud/xcrs",
3 + "version": "0.5.0",
4 + "lockfileVersion": 3,
5 + "requires": true,
6 + "packages": {
7 + "": {
8 + "name": "@smbcloud/xcrs",
9 + "version": "0.5.0",
10 + "license": "Apache-2.0",
11 + "bin": {
12 + "xcrs": "lib/index.js"
13 + },
14 + "devDependencies": {
15 + "@types/node": "^18.15.11",
16 + "@typescript-eslint/eslint-plugin": "^5.48.0",
17 + "@typescript-eslint/parser": "^5.48.0",
18 + "eslint": "^8.31.0",
19 + "typescript": "^5.0.0"
20 + },
21 + "optionalDependencies": {
22 + "@smbcloud/xcrs-darwin-arm64": "0.5.0",
23 + "@smbcloud/xcrs-darwin-x64": "0.5.0",
24 + "@smbcloud/xcrs-linux-x64": "0.5.0",
25 + "@smbcloud/xcrs-windows-arm64": "0.5.0",
26 + "@smbcloud/xcrs-windows-x64": "0.5.0"
27 + }
28 + },
29 + "node_modules/@eslint-community/eslint-utils": {
30 + "version": "4.10.1",
31 + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz",
32 + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==",
33 + "dev": true,
34 + "license": "MIT",
35 + "dependencies": {
36 + "eslint-visitor-keys": "^3.4.3"
37 + },
38 + "engines": {
39 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
40 + },
41 + "funding": {
42 + "url": "https://opencollective.com/eslint"
43 + },
44 + "peerDependencies": {
45 + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
46 + }
47 + },
48 + "node_modules/@eslint-community/regexpp": {
49 + "version": "4.12.2",
50 + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
51 + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
52 + "dev": true,
53 + "license": "MIT",
54 + "engines": {
55 + "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
56 + }
57 + },
58 + "node_modules/@eslint/eslintrc": {
59 + "version": "2.1.4",
60 + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
61 + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
62 + "dev": true,
63 + "license": "MIT",
64 + "dependencies": {
65 + "ajv": "^6.12.4",
66 + "debug": "^4.3.2",
67 + "espree": "^9.6.0",
68 + "globals": "^13.19.0",
69 + "ignore": "^5.2.0",
70 + "import-fresh": "^3.2.1",
71 + "js-yaml": "^4.1.0",
72 + "minimatch": "^3.1.2",
73 + "strip-json-comments": "^3.1.1"
74 + },
75 + "engines": {
76 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
77 + },
78 + "funding": {
79 + "url": "https://opencollective.com/eslint"
80 + }
81 + },
82 + "node_modules/@eslint/js": {
83 + "version": "8.57.1",
84 + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
85 + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
86 + "dev": true,
87 + "license": "MIT",
88 + "engines": {
89 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
90 + }
91 + },
92 + "node_modules/@humanwhocodes/config-array": {
93 + "version": "0.13.0",
94 + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
95 + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
96 + "deprecated": "Use @eslint/config-array instead",
97 + "dev": true,
98 + "license": "Apache-2.0",
99 + "dependencies": {
100 + "@humanwhocodes/object-schema": "^2.0.3",
101 + "debug": "^4.3.1",
102 + "minimatch": "^3.0.5"
103 + },
104 + "engines": {
105 + "node": ">=10.10.0"
106 + }
107 + },
108 + "node_modules/@humanwhocodes/module-importer": {
109 + "version": "1.0.1",
110 + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
111 + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
112 + "dev": true,
113 + "license": "Apache-2.0",
114 + "engines": {
115 + "node": ">=12.22"
116 + },
117 + "funding": {
118 + "type": "github",
119 + "url": "https://github.com/sponsors/nzakas"
120 + }
121 + },
122 + "node_modules/@humanwhocodes/object-schema": {
123 + "version": "2.0.3",
124 + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
125 + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
126 + "deprecated": "Use @eslint/object-schema instead",
127 + "dev": true,
128 + "license": "BSD-3-Clause"
129 + },
130 + "node_modules/@nodelib/fs.scandir": {
131 + "version": "2.1.5",
132 + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
133 + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
134 + "dev": true,
135 + "license": "MIT",
136 + "dependencies": {
137 + "@nodelib/fs.stat": "2.0.5",
138 + "run-parallel": "^1.1.9"
139 + },
140 + "engines": {
141 + "node": ">= 8"
142 + }
143 + },
144 + "node_modules/@nodelib/fs.stat": {
145 + "version": "2.0.5",
146 + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
147 + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
148 + "dev": true,
149 + "license": "MIT",
150 + "engines": {
151 + "node": ">= 8"
152 + }
153 + },
154 + "node_modules/@nodelib/fs.walk": {
155 + "version": "1.2.8",
156 + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
157 + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
158 + "dev": true,
159 + "license": "MIT",
160 + "dependencies": {
161 + "@nodelib/fs.scandir": "2.1.5",
162 + "fastq": "^1.6.0"
163 + },
164 + "engines": {
165 + "node": ">= 8"
166 + }
167 + },
168 + "node_modules/@smbcloud/xcrs-darwin-arm64": {
169 + "optional": true
170 + },
171 + "node_modules/@smbcloud/xcrs-darwin-x64": {
172 + "optional": true
173 + },
174 + "node_modules/@smbcloud/xcrs-linux-x64": {
175 + "optional": true
176 + },
177 + "node_modules/@smbcloud/xcrs-windows-arm64": {
178 + "optional": true
179 + },
180 + "node_modules/@smbcloud/xcrs-windows-x64": {
181 + "optional": true
182 + },
183 + "node_modules/@types/json-schema": {
184 + "version": "7.0.15",
185 + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
186 + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
187 + "dev": true,
188 + "license": "MIT"
189 + },
190 + "node_modules/@types/node": {
191 + "version": "18.19.130",
192 + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
193 + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
194 + "dev": true,
195 + "license": "MIT",
196 + "dependencies": {
197 + "undici-types": "~5.26.4"
198 + }
199 + },
200 + "node_modules/@types/semver": {
201 + "version": "7.8.0",
202 + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.8.0.tgz",
203 + "integrity": "sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==",
204 + "dev": true,
205 + "license": "MIT"
206 + },
207 + "node_modules/@typescript-eslint/eslint-plugin": {
208 + "version": "5.62.0",
209 + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
210 + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
211 + "dev": true,
212 + "license": "MIT",
213 + "dependencies": {
214 + "@eslint-community/regexpp": "^4.4.0",
215 + "@typescript-eslint/scope-manager": "5.62.0",
216 + "@typescript-eslint/type-utils": "5.62.0",
217 + "@typescript-eslint/utils": "5.62.0",
218 + "debug": "^4.3.4",
219 + "graphemer": "^1.4.0",
220 + "ignore": "^5.2.0",
221 + "natural-compare-lite": "^1.4.0",
222 + "semver": "^7.3.7",
223 + "tsutils": "^3.21.0"
224 + },
225 + "engines": {
226 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
227 + },
228 + "funding": {
229 + "type": "opencollective",
230 + "url": "https://opencollective.com/typescript-eslint"
231 + },
232 + "peerDependencies": {
233 + "@typescript-eslint/parser": "^5.0.0",
234 + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
235 + },
236 + "peerDependenciesMeta": {
237 + "typescript": {
238 + "optional": true
239 + }
240 + }
241 + },
242 + "node_modules/@typescript-eslint/parser": {
243 + "version": "5.62.0",
244 + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
245 + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
246 + "dev": true,
247 + "license": "BSD-2-Clause",
248 + "dependencies": {
249 + "@typescript-eslint/scope-manager": "5.62.0",
250 + "@typescript-eslint/types": "5.62.0",
251 + "@typescript-eslint/typescript-estree": "5.62.0",
252 + "debug": "^4.3.4"
253 + },
254 + "engines": {
255 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
256 + },
257 + "funding": {
258 + "type": "opencollective",
259 + "url": "https://opencollective.com/typescript-eslint"
260 + },
261 + "peerDependencies": {
262 + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
263 + },
264 + "peerDependenciesMeta": {
265 + "typescript": {
266 + "optional": true
267 + }
268 + }
269 + },
270 + "node_modules/@typescript-eslint/scope-manager": {
271 + "version": "5.62.0",
272 + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
273 + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
274 + "dev": true,
275 + "license": "MIT",
276 + "dependencies": {
277 + "@typescript-eslint/types": "5.62.0",
278 + "@typescript-eslint/visitor-keys": "5.62.0"
279 + },
280 + "engines": {
281 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
282 + },
283 + "funding": {
284 + "type": "opencollective",
285 + "url": "https://opencollective.com/typescript-eslint"
286 + }
287 + },
288 + "node_modules/@typescript-eslint/type-utils": {
289 + "version": "5.62.0",
290 + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
291 + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
292 + "dev": true,
293 + "license": "MIT",
294 + "dependencies": {
295 + "@typescript-eslint/typescript-estree": "5.62.0",
296 + "@typescript-eslint/utils": "5.62.0",
297 + "debug": "^4.3.4",
298 + "tsutils": "^3.21.0"
299 + },
300 + "engines": {
301 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
302 + },
303 + "funding": {
304 + "type": "opencollective",
305 + "url": "https://opencollective.com/typescript-eslint"
306 + },
307 + "peerDependencies": {
308 + "eslint": "*"
309 + },
310 + "peerDependenciesMeta": {
311 + "typescript": {
312 + "optional": true
313 + }
314 + }
315 + },
316 + "node_modules/@typescript-eslint/types": {
317 + "version": "5.62.0",
318 + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
319 + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
320 + "dev": true,
321 + "license": "MIT",
322 + "engines": {
323 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
324 + },
325 + "funding": {
326 + "type": "opencollective",
327 + "url": "https://opencollective.com/typescript-eslint"
328 + }
329 + },
330 + "node_modules/@typescript-eslint/typescript-estree": {
331 + "version": "5.62.0",
332 + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
333 + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
334 + "dev": true,
335 + "license": "BSD-2-Clause",
336 + "dependencies": {
337 + "@typescript-eslint/types": "5.62.0",
338 + "@typescript-eslint/visitor-keys": "5.62.0",
339 + "debug": "^4.3.4",
340 + "globby": "^11.1.0",
341 + "is-glob": "^4.0.3",
342 + "semver": "^7.3.7",
343 + "tsutils": "^3.21.0"
344 + },
345 + "engines": {
346 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
347 + },
348 + "funding": {
349 + "type": "opencollective",
350 + "url": "https://opencollective.com/typescript-eslint"
351 + },
352 + "peerDependenciesMeta": {
353 + "typescript": {
354 + "optional": true
355 + }
356 + }
357 + },
358 + "node_modules/@typescript-eslint/utils": {
359 + "version": "5.62.0",
360 + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
361 + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
362 + "dev": true,
363 + "license": "MIT",
364 + "dependencies": {
365 + "@eslint-community/eslint-utils": "^4.2.0",
366 + "@types/json-schema": "^7.0.9",
367 + "@types/semver": "^7.3.12",
368 + "@typescript-eslint/scope-manager": "5.62.0",
369 + "@typescript-eslint/types": "5.62.0",
370 + "@typescript-eslint/typescript-estree": "5.62.0",
371 + "eslint-scope": "^5.1.1",
372 + "semver": "^7.3.7"
373 + },
374 + "engines": {
375 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
376 + },
377 + "funding": {
378 + "type": "opencollective",
379 + "url": "https://opencollective.com/typescript-eslint"
380 + },
381 + "peerDependencies": {
382 + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
383 + }
384 + },
385 + "node_modules/@typescript-eslint/visitor-keys": {
386 + "version": "5.62.0",
387 + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
388 + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
389 + "dev": true,
390 + "license": "MIT",
391 + "dependencies": {
392 + "@typescript-eslint/types": "5.62.0",
393 + "eslint-visitor-keys": "^3.3.0"
394 + },
395 + "engines": {
396 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
397 + },
398 + "funding": {
399 + "type": "opencollective",
400 + "url": "https://opencollective.com/typescript-eslint"
401 + }
402 + },
403 + "node_modules/@ungap/structured-clone": {
404 + "version": "1.3.3",
405 + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz",
406 + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==",
407 + "dev": true,
408 + "license": "ISC"
409 + },
410 + "node_modules/acorn": {
411 + "version": "8.18.0",
412 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
413 + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
414 + "dev": true,
415 + "license": "MIT",
416 + "bin": {
417 + "acorn": "bin/acorn"
418 + },
419 + "engines": {
420 + "node": ">=0.4.0"
421 + }
422 + },
423 + "node_modules/acorn-jsx": {
424 + "version": "5.3.2",
425 + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
426 + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
427 + "dev": true,
428 + "license": "MIT",
429 + "peerDependencies": {
430 + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
431 + }
432 + },
433 + "node_modules/ajv": {
434 + "version": "6.15.0",
435 + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
436 + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
437 + "dev": true,
438 + "license": "MIT",
439 + "dependencies": {
440 + "fast-deep-equal": "^3.1.1",
441 + "fast-json-stable-stringify": "^2.0.0",
442 + "json-schema-traverse": "^0.4.1",
443 + "uri-js": "^4.2.2"
444 + },
445 + "funding": {
446 + "type": "github",
447 + "url": "https://github.com/sponsors/epoberezkin"
448 + }
449 + },
450 + "node_modules/ansi-regex": {
451 + "version": "5.0.1",
452 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
453 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
454 + "dev": true,
455 + "license": "MIT",
456 + "engines": {
457 + "node": ">=8"
458 + }
459 + },
460 + "node_modules/ansi-styles": {
461 + "version": "4.3.0",
462 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
463 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
464 + "dev": true,
465 + "license": "MIT",
466 + "dependencies": {
467 + "color-convert": "^2.0.1"
468 + },
469 + "engines": {
470 + "node": ">=8"
471 + },
472 + "funding": {
473 + "url": "https://github.com/chalk/ansi-styles?sponsor=1"
474 + }
475 + },
476 + "node_modules/argparse": {
477 + "version": "2.0.1",
478 + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
479 + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
480 + "dev": true,
481 + "license": "Python-2.0"
482 + },
483 + "node_modules/array-union": {
484 + "version": "2.1.0",
485 + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
486 + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
487 + "dev": true,
488 + "license": "MIT",
489 + "engines": {
490 + "node": ">=8"
491 + }
492 + },
493 + "node_modules/balanced-match": {
494 + "version": "1.0.2",
495 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
496 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
497 + "dev": true,
498 + "license": "MIT"
499 + },
500 + "node_modules/brace-expansion": {
501 + "version": "1.1.18",
502 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
503 + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
504 + "dev": true,
505 + "license": "MIT",
506 + "dependencies": {
507 + "balanced-match": "^1.0.0",
508 + "concat-map": "0.0.1"
509 + }
510 + },
511 + "node_modules/braces": {
512 + "version": "3.0.3",
513 + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
514 + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
515 + "dev": true,
516 + "license": "MIT",
517 + "dependencies": {
518 + "fill-range": "^7.1.1"
519 + },
520 + "engines": {
521 + "node": ">=8"
522 + }
523 + },
524 + "node_modules/callsites": {
525 + "version": "3.1.0",
526 + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
527 + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
528 + "dev": true,
529 + "license": "MIT",
530 + "engines": {
531 + "node": ">=6"
532 + }
533 + },
534 + "node_modules/chalk": {
535 + "version": "4.1.2",
536 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
537 + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
538 + "dev": true,
539 + "license": "MIT",
540 + "dependencies": {
541 + "ansi-styles": "^4.1.0",
542 + "supports-color": "^7.1.0"
543 + },
544 + "engines": {
545 + "node": ">=10"
546 + },
547 + "funding": {
548 + "url": "https://github.com/chalk/chalk?sponsor=1"
549 + }
550 + },
551 + "node_modules/color-convert": {
552 + "version": "2.0.1",
553 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
554 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
555 + "dev": true,
556 + "license": "MIT",
557 + "dependencies": {
558 + "color-name": "~1.1.4"
559 + },
560 + "engines": {
561 + "node": ">=7.0.0"
562 + }
563 + },
564 + "node_modules/color-name": {
565 + "version": "1.1.4",
566 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
567 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
568 + "dev": true,
569 + "license": "MIT"
570 + },
571 + "node_modules/concat-map": {
572 + "version": "0.0.1",
573 + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
574 + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
575 + "dev": true,
576 + "license": "MIT"
577 + },
578 + "node_modules/cross-spawn": {
579 + "version": "7.0.6",
580 + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
581 + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
582 + "dev": true,
583 + "license": "MIT",
584 + "dependencies": {
585 + "path-key": "^3.1.0",
586 + "shebang-command": "^2.0.0",
587 + "which": "^2.0.1"
588 + },
589 + "engines": {
590 + "node": ">= 8"
591 + }
592 + },
593 + "node_modules/debug": {
594 + "version": "4.4.3",
595 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
596 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
597 + "dev": true,
598 + "license": "MIT",
599 + "dependencies": {
600 + "ms": "^2.1.3"
601 + },
602 + "engines": {
603 + "node": ">=6.0"
604 + },
605 + "peerDependenciesMeta": {
606 + "supports-color": {
607 + "optional": true
608 + }
609 + }
610 + },
611 + "node_modules/deep-is": {
612 + "version": "0.1.4",
613 + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
614 + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
615 + "dev": true,
616 + "license": "MIT"
617 + },
618 + "node_modules/dir-glob": {
619 + "version": "3.0.1",
620 + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
621 + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
622 + "dev": true,
623 + "license": "MIT",
624 + "dependencies": {
625 + "path-type": "^4.0.0"
626 + },
627 + "engines": {
628 + "node": ">=8"
629 + }
630 + },
631 + "node_modules/doctrine": {
632 + "version": "3.0.0",
633 + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
634 + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
635 + "dev": true,
636 + "license": "Apache-2.0",
637 + "dependencies": {
638 + "esutils": "^2.0.2"
639 + },
640 + "engines": {
641 + "node": ">=6.0.0"
642 + }
643 + },
644 + "node_modules/escape-string-regexp": {
645 + "version": "4.0.0",
646 + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
647 + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
648 + "dev": true,
649 + "license": "MIT",
650 + "engines": {
651 + "node": ">=10"
652 + },
653 + "funding": {
654 + "url": "https://github.com/sponsors/sindresorhus"
655 + }
656 + },
657 + "node_modules/eslint": {
658 + "version": "8.57.1",
659 + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
660 + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
661 + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
662 + "dev": true,
663 + "license": "MIT",
664 + "dependencies": {
665 + "@eslint-community/eslint-utils": "^4.2.0",
666 + "@eslint-community/regexpp": "^4.6.1",
667 + "@eslint/eslintrc": "^2.1.4",
668 + "@eslint/js": "8.57.1",
669 + "@humanwhocodes/config-array": "^0.13.0",
670 + "@humanwhocodes/module-importer": "^1.0.1",
671 + "@nodelib/fs.walk": "^1.2.8",
672 + "@ungap/structured-clone": "^1.2.0",
673 + "ajv": "^6.12.4",
674 + "chalk": "^4.0.0",
675 + "cross-spawn": "^7.0.2",
676 + "debug": "^4.3.2",
677 + "doctrine": "^3.0.0",
678 + "escape-string-regexp": "^4.0.0",
679 + "eslint-scope": "^7.2.2",
680 + "eslint-visitor-keys": "^3.4.3",
681 + "espree": "^9.6.1",
682 + "esquery": "^1.4.2",
683 + "esutils": "^2.0.2",
684 + "fast-deep-equal": "^3.1.3",
685 + "file-entry-cache": "^6.0.1",
686 + "find-up": "^5.0.0",
687 + "glob-parent": "^6.0.2",
688 + "globals": "^13.19.0",
689 + "graphemer": "^1.4.0",
690 + "ignore": "^5.2.0",
691 + "imurmurhash": "^0.1.4",
692 + "is-glob": "^4.0.0",
693 + "is-path-inside": "^3.0.3",
694 + "js-yaml": "^4.1.0",
695 + "json-stable-stringify-without-jsonify": "^1.0.1",
696 + "levn": "^0.4.1",
697 + "lodash.merge": "^4.6.2",
698 + "minimatch": "^3.1.2",
699 + "natural-compare": "^1.4.0",
700 + "optionator": "^0.9.3",
701 + "strip-ansi": "^6.0.1",
702 + "text-table": "^0.2.0"
703 + },
704 + "bin": {
705 + "eslint": "bin/eslint.js"
706 + },
707 + "engines": {
708 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
709 + },
710 + "funding": {
711 + "url": "https://opencollective.com/eslint"
712 + }
713 + },
714 + "node_modules/eslint-scope": {
715 + "version": "5.1.1",
716 + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
717 + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
718 + "dev": true,
719 + "license": "BSD-2-Clause",
720 + "dependencies": {
721 + "esrecurse": "^4.3.0",
722 + "estraverse": "^4.1.1"
723 + },
724 + "engines": {
725 + "node": ">=8.0.0"
726 + }
727 + },
728 + "node_modules/eslint-visitor-keys": {
729 + "version": "3.4.3",
730 + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
731 + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
732 + "dev": true,
733 + "license": "Apache-2.0",
734 + "engines": {
735 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
736 + },
737 + "funding": {
738 + "url": "https://opencollective.com/eslint"
739 + }
740 + },
741 + "node_modules/eslint/node_modules/eslint-scope": {
742 + "version": "7.2.2",
743 + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
744 + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
745 + "dev": true,
746 + "license": "BSD-2-Clause",
747 + "dependencies": {
748 + "esrecurse": "^4.3.0",
749 + "estraverse": "^5.2.0"
750 + },
751 + "engines": {
752 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
753 + },
754 + "funding": {
755 + "url": "https://opencollective.com/eslint"
756 + }
757 + },
758 + "node_modules/eslint/node_modules/estraverse": {
759 + "version": "5.3.0",
760 + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
761 + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
762 + "dev": true,
763 + "license": "BSD-2-Clause",
764 + "engines": {
765 + "node": ">=4.0"
766 + }
767 + },
768 + "node_modules/espree": {
769 + "version": "9.6.1",
770 + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
771 + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
772 + "dev": true,
773 + "license": "BSD-2-Clause",
774 + "dependencies": {
775 + "acorn": "^8.9.0",
776 + "acorn-jsx": "^5.3.2",
777 + "eslint-visitor-keys": "^3.4.1"
778 + },
779 + "engines": {
780 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
781 + },
782 + "funding": {
783 + "url": "https://opencollective.com/eslint"
784 + }
785 + },
786 + "node_modules/esquery": {
787 + "version": "1.7.0",
788 + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
789 + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
790 + "dev": true,
791 + "license": "BSD-3-Clause",
792 + "dependencies": {
793 + "estraverse": "^5.1.0"
794 + },
795 + "engines": {
796 + "node": ">=0.10"
797 + }
798 + },
799 + "node_modules/esquery/node_modules/estraverse": {
800 + "version": "5.3.0",
801 + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
802 + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
803 + "dev": true,
804 + "license": "BSD-2-Clause",
805 + "engines": {
806 + "node": ">=4.0"
807 + }
808 + },
809 + "node_modules/esrecurse": {
810 + "version": "4.3.0",
811 + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
812 + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
813 + "dev": true,
814 + "license": "BSD-2-Clause",
815 + "dependencies": {
816 + "estraverse": "^5.2.0"
817 + },
818 + "engines": {
819 + "node": ">=4.0"
820 + }
821 + },
822 + "node_modules/esrecurse/node_modules/estraverse": {
823 + "version": "5.3.0",
824 + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
825 + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
826 + "dev": true,
827 + "license": "BSD-2-Clause",
828 + "engines": {
829 + "node": ">=4.0"
830 + }
831 + },
832 + "node_modules/estraverse": {
833 + "version": "4.3.0",
834 + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
835 + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
836 + "dev": true,
837 + "license": "BSD-2-Clause",
838 + "engines": {
839 + "node": ">=4.0"
840 + }
841 + },
842 + "node_modules/esutils": {
843 + "version": "2.0.3",
844 + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
845 + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
846 + "dev": true,
847 + "license": "BSD-2-Clause",
848 + "engines": {
849 + "node": ">=0.10.0"
850 + }
851 + },
852 + "node_modules/fast-deep-equal": {
853 + "version": "3.1.3",
854 + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
855 + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
856 + "dev": true,
857 + "license": "MIT"
858 + },
859 + "node_modules/fast-glob": {
860 + "version": "3.3.3",
861 + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
862 + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
863 + "dev": true,
864 + "license": "MIT",
865 + "dependencies": {
866 + "@nodelib/fs.stat": "^2.0.2",
867 + "@nodelib/fs.walk": "^1.2.3",
868 + "glob-parent": "^5.1.2",
869 + "merge2": "^1.3.0",
870 + "micromatch": "^4.0.8"
871 + },
872 + "engines": {
873 + "node": ">=8.6.0"
874 + }
875 + },
876 + "node_modules/fast-glob/node_modules/glob-parent": {
877 + "version": "5.1.2",
878 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
879 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
880 + "dev": true,
881 + "license": "ISC",
882 + "dependencies": {
883 + "is-glob": "^4.0.1"
884 + },
885 + "engines": {
886 + "node": ">= 6"
887 + }
888 + },
889 + "node_modules/fast-json-stable-stringify": {
890 + "version": "2.1.0",
891 + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
892 + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
893 + "dev": true,
894 + "license": "MIT"
895 + },
896 + "node_modules/fast-levenshtein": {
897 + "version": "2.0.6",
898 + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
899 + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
900 + "dev": true,
901 + "license": "MIT"
902 + },
903 + "node_modules/fastq": {
904 + "version": "1.20.1",
905 + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
906 + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
907 + "dev": true,
908 + "license": "ISC",
909 + "dependencies": {
910 + "reusify": "^1.0.4"
911 + }
912 + },
913 + "node_modules/file-entry-cache": {
914 + "version": "6.0.1",
915 + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
916 + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
917 + "dev": true,
918 + "license": "MIT",
919 + "dependencies": {
920 + "flat-cache": "^3.0.4"
921 + },
922 + "engines": {
923 + "node": "^10.12.0 || >=12.0.0"
924 + }
925 + },
926 + "node_modules/fill-range": {
927 + "version": "7.1.1",
928 + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
929 + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
930 + "dev": true,
931 + "license": "MIT",
932 + "dependencies": {
933 + "to-regex-range": "^5.0.1"
934 + },
935 + "engines": {
936 + "node": ">=8"
937 + }
938 + },
939 + "node_modules/find-up": {
940 + "version": "5.0.0",
941 + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
942 + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
943 + "dev": true,
944 + "license": "MIT",
945 + "dependencies": {
946 + "locate-path": "^6.0.0",
947 + "path-exists": "^4.0.0"
948 + },
949 + "engines": {
950 + "node": ">=10"
951 + },
952 + "funding": {
953 + "url": "https://github.com/sponsors/sindresorhus"
954 + }
955 + },
956 + "node_modules/flat-cache": {
957 + "version": "3.2.0",
958 + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
959 + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
960 + "dev": true,
961 + "license": "MIT",
962 + "dependencies": {
963 + "flatted": "^3.2.9",
964 + "keyv": "^4.5.3",
965 + "rimraf": "^3.0.2"
966 + },
967 + "engines": {
968 + "node": "^10.12.0 || >=12.0.0"
969 + }
970 + },
971 + "node_modules/flatted": {
972 + "version": "3.4.4",
973 + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
974 + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
975 + "dev": true,
976 + "license": "ISC"
977 + },
978 + "node_modules/fs.realpath": {
979 + "version": "1.0.0",
980 + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
981 + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
982 + "dev": true,
983 + "license": "ISC"
984 + },
985 + "node_modules/glob": {
986 + "version": "7.2.3",
987 + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
988 + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
989 + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
990 + "dev": true,
991 + "license": "ISC",
992 + "dependencies": {
993 + "fs.realpath": "^1.0.0",
994 + "inflight": "^1.0.4",
995 + "inherits": "2",
996 + "minimatch": "^3.1.1",
997 + "once": "^1.3.0",
998 + "path-is-absolute": "^1.0.0"
999 + },
1000 + "engines": {
1001 + "node": "*"
1002 + },
1003 + "funding": {
1004 + "url": "https://github.com/sponsors/isaacs"
1005 + }
1006 + },
1007 + "node_modules/glob-parent": {
1008 + "version": "6.0.2",
1009 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
1010 + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
1011 + "dev": true,
1012 + "license": "ISC",
1013 + "dependencies": {
1014 + "is-glob": "^4.0.3"
1015 + },
1016 + "engines": {
1017 + "node": ">=10.13.0"
1018 + }
1019 + },
1020 + "node_modules/globals": {
1021 + "version": "13.24.0",
1022 + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
1023 + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
1024 + "dev": true,
1025 + "license": "MIT",
1026 + "dependencies": {
1027 + "type-fest": "^0.20.2"
1028 + },
1029 + "engines": {
1030 + "node": ">=8"
1031 + },
1032 + "funding": {
1033 + "url": "https://github.com/sponsors/sindresorhus"
1034 + }
1035 + },
1036 + "node_modules/globby": {
1037 + "version": "11.1.0",
1038 + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
1039 + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
1040 + "dev": true,
1041 + "license": "MIT",
1042 + "dependencies": {
1043 + "array-union": "^2.1.0",
1044 + "dir-glob": "^3.0.1",
1045 + "fast-glob": "^3.2.9",
1046 + "ignore": "^5.2.0",
1047 + "merge2": "^1.4.1",
1048 + "slash": "^3.0.0"
1049 + },
1050 + "engines": {
1051 + "node": ">=10"
1052 + },
1053 + "funding": {
1054 + "url": "https://github.com/sponsors/sindresorhus"
1055 + }
1056 + },
1057 + "node_modules/graphemer": {
1058 + "version": "1.4.0",
1059 + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
1060 + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
1061 + "dev": true,
1062 + "license": "MIT"
1063 + },
1064 + "node_modules/has-flag": {
1065 + "version": "4.0.0",
1066 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1067 + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1068 + "dev": true,
1069 + "license": "MIT",
1070 + "engines": {
1071 + "node": ">=8"
1072 + }
1073 + },
1074 + "node_modules/ignore": {
1075 + "version": "5.3.2",
1076 + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
1077 + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
1078 + "dev": true,
1079 + "license": "MIT",
1080 + "engines": {
1081 + "node": ">= 4"
1082 + }
1083 + },
1084 + "node_modules/import-fresh": {
1085 + "version": "3.3.1",
1086 + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
1087 + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
1088 + "dev": true,
1089 + "license": "MIT",
1090 + "dependencies": {
1091 + "parent-module": "^1.0.0",
1092 + "resolve-from": "^4.0.0"
1093 + },
1094 + "engines": {
1095 + "node": ">=6"
1096 + },
1097 + "funding": {
1098 + "url": "https://github.com/sponsors/sindresorhus"
1099 + }
1100 + },
1101 + "node_modules/imurmurhash": {
1102 + "version": "0.1.4",
1103 + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1104 + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
1105 + "dev": true,
1106 + "license": "MIT",
1107 + "engines": {
1108 + "node": ">=0.8.19"
1109 + }
1110 + },
1111 + "node_modules/inflight": {
1112 + "version": "1.0.6",
1113 + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1114 + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
1115 + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
1116 + "dev": true,
1117 + "license": "ISC",
1118 + "dependencies": {
1119 + "once": "^1.3.0",
1120 + "wrappy": "1"
1121 + }
1122 + },
1123 + "node_modules/inherits": {
1124 + "version": "2.0.4",
1125 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1126 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1127 + "dev": true,
1128 + "license": "ISC"
1129 + },
1130 + "node_modules/is-extglob": {
1131 + "version": "2.1.1",
1132 + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1133 + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1134 + "dev": true,
1135 + "license": "MIT",
1136 + "engines": {
1137 + "node": ">=0.10.0"
1138 + }
1139 + },
1140 + "node_modules/is-glob": {
1141 + "version": "4.0.3",
1142 + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1143 + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1144 + "dev": true,
1145 + "license": "MIT",
1146 + "dependencies": {
1147 + "is-extglob": "^2.1.1"
1148 + },
1149 + "engines": {
1150 + "node": ">=0.10.0"
1151 + }
1152 + },
1153 + "node_modules/is-number": {
1154 + "version": "7.0.0",
1155 + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1156 + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1157 + "dev": true,
1158 + "license": "MIT",
1159 + "engines": {
1160 + "node": ">=0.12.0"
1161 + }
1162 + },
1163 + "node_modules/is-path-inside": {
1164 + "version": "3.0.3",
1165 + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
1166 + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
1167 + "dev": true,
1168 + "license": "MIT",
1169 + "engines": {
1170 + "node": ">=8"
1171 + }
1172 + },
1173 + "node_modules/isexe": {
1174 + "version": "2.0.0",
1175 + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1176 + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
1177 + "dev": true,
1178 + "license": "ISC"
1179 + },
1180 + "node_modules/js-yaml": {
1181 + "version": "4.3.1",
1182 + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
1183 + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
1184 + "dev": true,
1185 + "funding": [
1186 + {
1187 + "type": "github",
1188 + "url": "https://github.com/sponsors/puzrin"
1189 + },
1190 + {
1191 + "type": "github",
1192 + "url": "https://github.com/sponsors/nodeca"
1193 + }
1194 + ],
1195 + "license": "MIT",
1196 + "dependencies": {
1197 + "argparse": "^2.0.1"
1198 + },
1199 + "bin": {
1200 + "js-yaml": "bin/js-yaml.js"
1201 + }
1202 + },
1203 + "node_modules/json-buffer": {
1204 + "version": "3.0.1",
1205 + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
1206 + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
1207 + "dev": true,
1208 + "license": "MIT"
1209 + },
1210 + "node_modules/json-schema-traverse": {
1211 + "version": "0.4.1",
1212 + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1213 + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1214 + "dev": true,
1215 + "license": "MIT"
1216 + },
1217 + "node_modules/json-stable-stringify-without-jsonify": {
1218 + "version": "1.0.1",
1219 + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
1220 + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
1221 + "dev": true,
1222 + "license": "MIT"
1223 + },
1224 + "node_modules/keyv": {
1225 + "version": "4.5.4",
1226 + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
1227 + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
1228 + "dev": true,
1229 + "license": "MIT",
1230 + "dependencies": {
1231 + "json-buffer": "3.0.1"
1232 + }
1233 + },
1234 + "node_modules/levn": {
1235 + "version": "0.4.1",
1236 + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
1237 + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
1238 + "dev": true,
1239 + "license": "MIT",
1240 + "dependencies": {
1241 + "prelude-ls": "^1.2.1",
1242 + "type-check": "~0.4.0"
1243 + },
1244 + "engines": {
1245 + "node": ">= 0.8.0"
1246 + }
1247 + },
1248 + "node_modules/locate-path": {
1249 + "version": "6.0.0",
1250 + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
1251 + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
1252 + "dev": true,
1253 + "license": "MIT",
1254 + "dependencies": {
1255 + "p-locate": "^5.0.0"
1256 + },
1257 + "engines": {
1258 + "node": ">=10"
1259 + },
1260 + "funding": {
1261 + "url": "https://github.com/sponsors/sindresorhus"
1262 + }
1263 + },
1264 + "node_modules/lodash.merge": {
1265 + "version": "4.6.2",
1266 + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
1267 + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
1268 + "dev": true,
1269 + "license": "MIT"
1270 + },
1271 + "node_modules/merge2": {
1272 + "version": "1.4.1",
1273 + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
1274 + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
1275 + "dev": true,
1276 + "license": "MIT",
1277 + "engines": {
1278 + "node": ">= 8"
1279 + }
1280 + },
1281 + "node_modules/micromatch": {
1282 + "version": "4.0.8",
1283 + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
1284 + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
1285 + "dev": true,
1286 + "license": "MIT",
1287 + "dependencies": {
1288 + "braces": "^3.0.3",
1289 + "picomatch": "^2.3.1"
1290 + },
1291 + "engines": {
1292 + "node": ">=8.6"
1293 + }
1294 + },
1295 + "node_modules/minimatch": {
1296 + "version": "3.1.5",
1297 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
1298 + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
1299 + "dev": true,
1300 + "license": "ISC",
1301 + "dependencies": {
1302 + "brace-expansion": "^1.1.7"
1303 + },
1304 + "engines": {
1305 + "node": "*"
1306 + }
1307 + },
1308 + "node_modules/ms": {
1309 + "version": "2.1.3",
1310 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1311 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1312 + "dev": true,
1313 + "license": "MIT"
1314 + },
1315 + "node_modules/natural-compare": {
1316 + "version": "1.4.0",
1317 + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
1318 + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
1319 + "dev": true,
1320 + "license": "MIT"
1321 + },
1322 + "node_modules/natural-compare-lite": {
1323 + "version": "1.4.0",
1324 + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
1325 + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
1326 + "dev": true,
1327 + "license": "MIT"
1328 + },
1329 + "node_modules/once": {
1330 + "version": "1.4.0",
1331 + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1332 + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1333 + "dev": true,
1334 + "license": "ISC",
1335 + "dependencies": {
1336 + "wrappy": "1"
1337 + }
1338 + },
1339 + "node_modules/optionator": {
1340 + "version": "0.9.4",
1341 + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
1342 + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
1343 + "dev": true,
1344 + "license": "MIT",
1345 + "dependencies": {
1346 + "deep-is": "^0.1.3",
1347 + "fast-levenshtein": "^2.0.6",
1348 + "levn": "^0.4.1",
1349 + "prelude-ls": "^1.2.1",
1350 + "type-check": "^0.4.0",
1351 + "word-wrap": "^1.2.5"
1352 + },
1353 + "engines": {
1354 + "node": ">= 0.8.0"
1355 + }
1356 + },
1357 + "node_modules/p-limit": {
1358 + "version": "3.1.0",
1359 + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
1360 + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
1361 + "dev": true,
1362 + "license": "MIT",
1363 + "dependencies": {
1364 + "yocto-queue": "^0.1.0"
1365 + },
1366 + "engines": {
1367 + "node": ">=10"
1368 + },
1369 + "funding": {
1370 + "url": "https://github.com/sponsors/sindresorhus"
1371 + }
1372 + },
1373 + "node_modules/p-locate": {
1374 + "version": "5.0.0",
1375 + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
1376 + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
1377 + "dev": true,
1378 + "license": "MIT",
1379 + "dependencies": {
1380 + "p-limit": "^3.0.2"
1381 + },
1382 + "engines": {
1383 + "node": ">=10"
1384 + },
1385 + "funding": {
1386 + "url": "https://github.com/sponsors/sindresorhus"
1387 + }
1388 + },
1389 + "node_modules/parent-module": {
1390 + "version": "1.0.1",
1391 + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
1392 + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
1393 + "dev": true,
1394 + "license": "MIT",
1395 + "dependencies": {
1396 + "callsites": "^3.0.0"
1397 + },
1398 + "engines": {
1399 + "node": ">=6"
1400 + }
1401 + },
1402 + "node_modules/path-exists": {
1403 + "version": "4.0.0",
1404 + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1405 + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
1406 + "dev": true,
1407 + "license": "MIT",
1408 + "engines": {
1409 + "node": ">=8"
1410 + }
1411 + },
1412 + "node_modules/path-is-absolute": {
1413 + "version": "1.0.1",
1414 + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1415 + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1416 + "dev": true,
1417 + "license": "MIT",
1418 + "engines": {
1419 + "node": ">=0.10.0"
1420 + }
1421 + },
1422 + "node_modules/path-key": {
1423 + "version": "3.1.1",
1424 + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1425 + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1426 + "dev": true,
1427 + "license": "MIT",
1428 + "engines": {
1429 + "node": ">=8"
1430 + }
1431 + },
1432 + "node_modules/path-type": {
1433 + "version": "4.0.0",
1434 + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
1435 + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
1436 + "dev": true,
1437 + "license": "MIT",
1438 + "engines": {
1439 + "node": ">=8"
1440 + }
1441 + },
1442 + "node_modules/picomatch": {
1443 + "version": "2.3.2",
1444 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
1445 + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
1446 + "dev": true,
1447 + "license": "MIT",
1448 + "engines": {
1449 + "node": ">=8.6"
1450 + },
1451 + "funding": {
1452 + "url": "https://github.com/sponsors/jonschlinkert"
1453 + }
1454 + },
1455 + "node_modules/prelude-ls": {
1456 + "version": "1.2.1",
1457 + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
1458 + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
1459 + "dev": true,
1460 + "license": "MIT",
1461 + "engines": {
1462 + "node": ">= 0.8.0"
1463 + }
1464 + },
1465 + "node_modules/punycode": {
1466 + "version": "2.3.1",
1467 + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1468 + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1469 + "dev": true,
1470 + "license": "MIT",
1471 + "engines": {
1472 + "node": ">=6"
1473 + }
1474 + },
1475 + "node_modules/queue-microtask": {
1476 + "version": "1.2.3",
1477 + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1478 + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1479 + "dev": true,
1480 + "funding": [
1481 + {
1482 + "type": "github",
1483 + "url": "https://github.com/sponsors/feross"
1484 + },
1485 + {
1486 + "type": "patreon",
1487 + "url": "https://www.patreon.com/feross"
1488 + },
1489 + {
1490 + "type": "consulting",
1491 + "url": "https://feross.org/support"
1492 + }
1493 + ],
1494 + "license": "MIT"
1495 + },
1496 + "node_modules/resolve-from": {
1497 + "version": "4.0.0",
1498 + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
1499 + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
1500 + "dev": true,
1501 + "license": "MIT",
1502 + "engines": {
1503 + "node": ">=4"
1504 + }
1505 + },
1506 + "node_modules/reusify": {
1507 + "version": "1.1.0",
1508 + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
1509 + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
1510 + "dev": true,
1511 + "license": "MIT",
1512 + "engines": {
1513 + "iojs": ">=1.0.0",
1514 + "node": ">=0.10.0"
1515 + }
1516 + },
1517 + "node_modules/rimraf": {
1518 + "version": "3.0.2",
1519 + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1520 + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1521 + "deprecated": "Rimraf versions prior to v4 are no longer supported",
1522 + "dev": true,
1523 + "license": "ISC",
1524 + "dependencies": {
1525 + "glob": "^7.1.3"
1526 + },
1527 + "bin": {
1528 + "rimraf": "bin.js"
1529 + },
1530 + "funding": {
1531 + "url": "https://github.com/sponsors/isaacs"
1532 + }
1533 + },
1534 + "node_modules/run-parallel": {
1535 + "version": "1.2.0",
1536 + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1537 + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1538 + "dev": true,
1539 + "funding": [
1540 + {
1541 + "type": "github",
1542 + "url": "https://github.com/sponsors/feross"
1543 + },
1544 + {
1545 + "type": "patreon",
1546 + "url": "https://www.patreon.com/feross"
1547 + },
1548 + {
1549 + "type": "consulting",
1550 + "url": "https://feross.org/support"
1551 + }
1552 + ],
1553 + "license": "MIT",
1554 + "dependencies": {
1555 + "queue-microtask": "^1.2.2"
1556 + }
1557 + },
1558 + "node_modules/semver": {
1559 + "version": "7.8.5",
1560 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
1561 + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
1562 + "dev": true,
1563 + "license": "ISC",
1564 + "bin": {
1565 + "semver": "bin/semver.js"
1566 + },
1567 + "engines": {
1568 + "node": ">=10"
1569 + }
1570 + },
1571 + "node_modules/shebang-command": {
1572 + "version": "2.0.0",
1573 + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1574 + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1575 + "dev": true,
1576 + "license": "MIT",
1577 + "dependencies": {
1578 + "shebang-regex": "^3.0.0"
1579 + },
1580 + "engines": {
1581 + "node": ">=8"
1582 + }
1583 + },
1584 + "node_modules/shebang-regex": {
1585 + "version": "3.0.0",
1586 + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1587 + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1588 + "dev": true,
1589 + "license": "MIT",
1590 + "engines": {
1591 + "node": ">=8"
1592 + }
1593 + },
1594 + "node_modules/slash": {
1595 + "version": "3.0.0",
1596 + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
1597 + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
1598 + "dev": true,
1599 + "license": "MIT",
1600 + "engines": {
1601 + "node": ">=8"
1602 + }
1603 + },
1604 + "node_modules/strip-ansi": {
1605 + "version": "6.0.1",
1606 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1607 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1608 + "dev": true,
1609 + "license": "MIT",
1610 + "dependencies": {
1611 + "ansi-regex": "^5.0.1"
1612 + },
1613 + "engines": {
1614 + "node": ">=8"
1615 + }
1616 + },
1617 + "node_modules/strip-json-comments": {
1618 + "version": "3.1.1",
1619 + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
1620 + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
1621 + "dev": true,
1622 + "license": "MIT",
1623 + "engines": {
1624 + "node": ">=8"
1625 + },
1626 + "funding": {
1627 + "url": "https://github.com/sponsors/sindresorhus"
1628 + }
1629 + },
1630 + "node_modules/supports-color": {
1631 + "version": "7.2.0",
1632 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1633 + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1634 + "dev": true,
1635 + "license": "MIT",
1636 + "dependencies": {
1637 + "has-flag": "^4.0.0"
1638 + },
1639 + "engines": {
1640 + "node": ">=8"
1641 + }
1642 + },
1643 + "node_modules/text-table": {
1644 + "version": "0.2.0",
1645 + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
1646 + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
1647 + "dev": true,
1648 + "license": "MIT"
1649 + },
1650 + "node_modules/to-regex-range": {
1651 + "version": "5.0.1",
1652 + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1653 + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1654 + "dev": true,
1655 + "license": "MIT",
1656 + "dependencies": {
1657 + "is-number": "^7.0.0"
1658 + },
1659 + "engines": {
1660 + "node": ">=8.0"
1661 + }
1662 + },
1663 + "node_modules/tslib": {
1664 + "version": "1.14.1",
1665 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
1666 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
1667 + "dev": true,
1668 + "license": "0BSD"
1669 + },
1670 + "node_modules/tsutils": {
1671 + "version": "3.21.0",
1672 + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
1673 + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
1674 + "dev": true,
1675 + "license": "MIT",
1676 + "dependencies": {
1677 + "tslib": "^1.8.1"
1678 + },
1679 + "engines": {
1680 + "node": ">= 6"
1681 + },
1682 + "peerDependencies": {
1683 + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
1684 + }
1685 + },
1686 + "node_modules/type-check": {
1687 + "version": "0.4.0",
1688 + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
1689 + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
1690 + "dev": true,
1691 + "license": "MIT",
1692 + "dependencies": {
1693 + "prelude-ls": "^1.2.1"
1694 + },
1695 + "engines": {
1696 + "node": ">= 0.8.0"
1697 + }
1698 + },
1699 + "node_modules/type-fest": {
1700 + "version": "0.20.2",
1701 + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
1702 + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
1703 + "dev": true,
1704 + "license": "(MIT OR CC0-1.0)",
1705 + "engines": {
1706 + "node": ">=10"
1707 + },
1708 + "funding": {
1709 + "url": "https://github.com/sponsors/sindresorhus"
1710 + }
1711 + },
1712 + "node_modules/typescript": {
1713 + "version": "5.9.3",
1714 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
1715 + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
1716 + "dev": true,
1717 + "license": "Apache-2.0",
1718 + "bin": {
1719 + "tsc": "bin/tsc",
1720 + "tsserver": "bin/tsserver"
1721 + },
1722 + "engines": {
1723 + "node": ">=14.17"
1724 + }
1725 + },
1726 + "node_modules/undici-types": {
1727 + "version": "5.26.5",
1728 + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
1729 + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
1730 + "dev": true,
1731 + "license": "MIT"
1732 + },
1733 + "node_modules/uri-js": {
1734 + "version": "4.4.1",
1735 + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1736 + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1737 + "dev": true,
1738 + "license": "BSD-2-Clause",
1739 + "dependencies": {
1740 + "punycode": "^2.1.0"
1741 + }
1742 + },
1743 + "node_modules/which": {
1744 + "version": "2.0.2",
1745 + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1746 + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1747 + "dev": true,
1748 + "license": "ISC",
1749 + "dependencies": {
1750 + "isexe": "^2.0.0"
1751 + },
1752 + "bin": {
1753 + "node-which": "bin/node-which"
1754 + },
1755 + "engines": {
1756 + "node": ">= 8"
1757 + }
1758 + },
1759 + "node_modules/word-wrap": {
1760 + "version": "1.2.5",
1761 + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
1762 + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
1763 + "dev": true,
1764 + "license": "MIT",
1765 + "engines": {
1766 + "node": ">=0.10.0"
1767 + }
1768 + },
1769 + "node_modules/wrappy": {
1770 + "version": "1.0.2",
1771 + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1772 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1773 + "dev": true,
1774 + "license": "ISC"
1775 + },
1776 + "node_modules/yocto-queue": {
1777 + "version": "0.1.0",
1778 + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1779 + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
1780 + "dev": true,
1781 + "license": "MIT",
1782 + "engines": {
1783 + "node": ">=10"
1784 + },
1785 + "funding": {
1786 + "url": "https://github.com/sponsors/sindresorhus"
1787 + }
1788 + }
1789 + }
1790 +}
npm/xcrs/package.json new
+55
@@ -0,0 +1,55 @@
1 +{
2 + "name": "@smbcloud/xcrs",
3 + "version": "0.5.0",
4 + "keywords": [
5 + "xcrs",
6 + "mcp",
7 + "model-context-protocol",
8 + "mobile",
9 + "ios",
10 + "android",
11 + "tv",
12 + "apple-tv",
13 + "android-tv",
14 + "automation",
15 + "app-testing",
16 + "device",
17 + "simulator",
18 + "adb",
19 + "cli"
20 + ],
21 + "bin": {
22 + "xcrs": "lib/index.js"
23 + },
24 + "files": [
25 + "lib",
26 + "README.md"
27 + ],
28 + "description": "Cross-platform mobile and TV app automation over MCP.",
29 + "license": "Apache-2.0",
30 + "repository": {
31 + "type": "git",
32 + "url": "git+https://github.com/smbcloudXYZ/smbcloud-cli.git"
33 + },
34 + "scripts": {
35 + "typecheck": "tsc --noEmit",
36 + "lint": "eslint .",
37 + "lint:fix": "eslint . --fix",
38 + "build": "tsc",
39 + "dev": "npm run build && node lib/index.js"
40 + },
41 + "devDependencies": {
42 + "@types/node": "^18.15.11",
43 + "@typescript-eslint/eslint-plugin": "^5.48.0",
44 + "@typescript-eslint/parser": "^5.48.0",
45 + "eslint": "^8.31.0",
46 + "typescript": "^5.0.0"
47 + },
48 + "optionalDependencies": {
49 + "@smbcloud/xcrs-darwin-arm64": "0.5.0",
50 + "@smbcloud/xcrs-darwin-x64": "0.5.0",
51 + "@smbcloud/xcrs-linux-x64": "0.5.0",
52 + "@smbcloud/xcrs-windows-arm64": "0.5.0",
53 + "@smbcloud/xcrs-windows-x64": "0.5.0"
54 + }
55 +}
npm/xcrs/src/index.ts new
+43
@@ -0,0 +1,43 @@
1 +#!/usr/bin/env node
2 +
3 +import { spawnSync } from "child_process";
4 +
5 +/**
6 + * Returns the executable path which is located inside `node_modules`
7 + * The naming convention is xcrs-${os}-${arch}
8 + * If the platform is `win32` or `cygwin`, executable will include a `.exe` extension.
9 + * @see https://nodejs.org/api/os.html#osarch
10 + * @see https://nodejs.org/api/os.html#osplatform
11 + * @example "x/xx/node_modules/xcrs-darwin-arm64"
12 + */
13 +function getExePath() {
14 + const arch = process.arch;
15 + let os = process.platform as string;
16 + let extension = "";
17 + if (["win32", "cygwin"].includes(process.platform)) {
18 + os = "windows";
19 + extension = ".exe";
20 + }
21 +
22 + try {
23 + // The binary lives in `node_modules`, so `require.resolve` gives us the installed path.
24 + return require.resolve(
25 + `@smbcloud/xcrs-${os}-${arch}/bin/xcrs${extension}`,
26 + );
27 + } catch (e) {
28 + throw new Error(
29 + `Couldn't find application binary inside node_modules for ${os}-${arch}`,
30 + );
31 + }
32 +}
33 +
34 +/**
35 + * Runs the native CLI with the current process arguments.
36 + */
37 +function run() {
38 + const args = process.argv.slice(2);
39 + const processResult = spawnSync(getExePath(), args, { stdio: "inherit" });
40 + process.exit(processResult.status ?? 0);
41 +}
42 +
43 +run();
npm/xcrs/tsconfig.json new
+12
@@ -0,0 +1,12 @@
1 +{
2 + "compilerOptions": {
3 + "target": "es2016",
4 + "module": "commonjs",
5 + "esModuleInterop": true,
6 + "baseUrl": "./",
7 + "outDir": "lib",
8 + "forceConsistentCasingInFileNames": true,
9 + "strict": true,
10 + "skipLibCheck": true
11 + }
12 +}
nuget/.gitignore
+3
@@ -2,3 +2,6 @@ dist/
2 smbcloud-cli/bin/
3 smbcloud-cli/obj/
4 smbcloud-cli/native/
5 +xcrs/bin/
6 +xcrs/obj/
7 +xcrs/native/
nuget/xcrs/Program.cs new
+109
@@ -0,0 +1,109 @@
1 +using System.ComponentModel;
2 +using System.Diagnostics;
3 +using System.Runtime.InteropServices;
4 +
5 +internal static class Program
6 +{
7 + private const string CommandName = "xcrs";
8 +
9 + public static async Task<int> Main(string[] arguments)
10 + {
11 + try
12 + {
13 + string executablePath = ResolveExecutablePath();
14 + EnsureExecutablePermissions(executablePath);
15 + return await RunAsync(executablePath, arguments);
16 + }
17 + catch (Exception exception) when (
18 + exception is FileNotFoundException or
19 + PlatformNotSupportedException or
20 + Win32Exception)
21 + {
22 + Console.Error.WriteLine($"{CommandName}: {exception.Message}");
23 + return 1;
24 + }
25 + }
26 +
27 + private static string ResolveExecutablePath()
28 + {
29 + string runtimeIdentifier = GetRuntimeIdentifier();
30 + string executableName = OperatingSystem.IsWindows() ? $"{CommandName}.exe" : CommandName;
31 + string executablePath = Path.GetFullPath(
32 + Path.Combine(AppContext.BaseDirectory, "native", runtimeIdentifier, executableName));
33 +
34 + if (!File.Exists(executablePath))
35 + {
36 + throw new FileNotFoundException(
37 + $"The native {CommandName} executable for '{runtimeIdentifier}' is not bundled in this package.",
38 + executablePath);
39 + }
40 +
41 + return executablePath;
42 + }
43 +
44 + private static string GetRuntimeIdentifier()
45 + {
46 + string operatingSystem = OperatingSystem.IsWindows()
47 + ? "windows"
48 + : OperatingSystem.IsMacOS()
49 + ? "darwin"
50 + : OperatingSystem.IsLinux()
51 + ? "linux"
52 + : throw new PlatformNotSupportedException(
53 + $"{CommandName} does not support this operating system through the .NET tool package.");
54 +
55 + string architecture = RuntimeInformation.ProcessArchitecture switch
56 + {
57 + Architecture.X64 => "x64",
58 + Architecture.Arm64 => "arm64",
59 + _ => throw new PlatformNotSupportedException(
60 + $"{CommandName} does not support the '{RuntimeInformation.ProcessArchitecture}' architecture through the .NET tool package."),
61 + };
62 +
63 + return $"{operatingSystem}-{architecture}";
64 + }
65 +
66 + private static void EnsureExecutablePermissions(string executablePath)
67 + {
68 + if (OperatingSystem.IsWindows())
69 + {
70 + return;
71 + }
72 +
73 + UnixFileMode currentMode = File.GetUnixFileMode(executablePath);
74 + UnixFileMode requiredMode = UnixFileMode.UserRead |
75 + UnixFileMode.UserWrite |
76 + UnixFileMode.UserExecute |
77 + UnixFileMode.GroupRead |
78 + UnixFileMode.GroupExecute |
79 + UnixFileMode.OtherRead |
80 + UnixFileMode.OtherExecute;
81 +
82 + if ((currentMode & requiredMode) == requiredMode)
83 + {
84 + return;
85 + }
86 +
87 + File.SetUnixFileMode(executablePath, currentMode | requiredMode);
88 + }
89 +
90 + private static async Task<int> RunAsync(string executablePath, IReadOnlyList<string> arguments)
91 + {
92 + ProcessStartInfo startInfo = new(executablePath)
93 + {
94 + UseShellExecute = false,
95 + WorkingDirectory = Environment.CurrentDirectory,
96 + };
97 +
98 + foreach (string argument in arguments)
99 + {
100 + startInfo.ArgumentList.Add(argument);
101 + }
102 +
103 + using Process process = Process.Start(startInfo)
104 + ?? throw new Win32Exception($"Failed to start '{CommandName}'.");
105 +
106 + await process.WaitForExitAsync();
107 + return process.ExitCode;
108 + }
109 +}
nuget/xcrs/README.md new
+59
@@ -0,0 +1,59 @@
1 +# xcrs for .NET
2 +
3 +<!-- mcp-name: io.github.smbcloudXYZ/xcrs -->
4 +
5 +`xcrs` drives mobile and TV apps — on iOS simulators, physical Apple devices, and
6 +adb-connected Android phones, tablets, emulators, and TVs — through the
7 +[Model Context Protocol](https://modelcontextprotocol.io/). It is the standalone
8 +automation profile of the [smbCloud CLI](https://smbcloud.xyz/).
9 +
10 +## Install
11 +
12 +```sh
13 +dotnet tool install --global SmbCloud.Xcrs
14 +```
15 +
16 +## Update
17 +
18 +```sh
19 +dotnet tool update --global SmbCloud.Xcrs
20 +```
21 +
22 +## Quick start
23 +
24 +Run it as an MCP server over stdio and point your MCP client at it:
25 +
26 +```sh
27 +xcrs --mcp
28 +```
29 +
30 +## Platform support
31 +
32 +This .NET tool bundles native `xcrs` binaries for:
33 +
34 +- macOS `arm64`, `x64`
35 +- Linux `arm64`, `x64` (glibc)
36 +- Windows `arm64`, `x64`
37 +
38 +The full Apple automation surface requires macOS with Xcode command-line tools.
39 +Android automation over `adb` works from any platform.
40 +
41 +## Other installation methods
42 +
43 +- Cargo: `cargo install xcrs`
44 +- npm: `npm install -g @smbcloud/xcrs`
45 +- pip: `pip install xcrs`
46 +
47 +## Source
48 +
49 +- Repository: <https://github.com/smbcloudXYZ/smbcloud-cli>
50 +- Documentation: <https://smbcloud.xyz/posts>
51 +- Issues: <https://github.com/smbcloudXYZ/smbcloud-cli/issues>
52 +
53 +## License
54 +
55 +Apache-2.0
56 +
57 +## Copyright
58 +
59 +© 2026 [Splitfire AB](https://5mb.app) ([smbCloud](https://smbcloud.xyz)).
nuget/xcrs/Xcrs.csproj new
+26
@@ -0,0 +1,26 @@
1 +<Project Sdk="Microsoft.NET.Sdk">
2 + <PropertyGroup>
3 + <OutputType>Exe</OutputType>
4 + <TargetFramework>net8.0</TargetFramework>
5 + <ImplicitUsings>enable</ImplicitUsings>
6 + <Nullable>enable</Nullable>
7 + <PackAsTool>true</PackAsTool>
8 + <ToolCommandName>xcrs</ToolCommandName>
9 + <PackageId>SmbCloud.Xcrs</PackageId>
10 + <PackageVersion>0.5.0</PackageVersion>
11 + <Version>$(PackageVersion)</Version>
12 + <Authors>Seto Elkahfi</Authors>
13 + <Description>Cross-platform mobile and TV app automation over MCP.</Description>
14 + <PackageReadmeFile>README.md</PackageReadmeFile>
15 + <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
16 + <PackageProjectUrl>https://smbcloud.xyz/</PackageProjectUrl>
17 + <RepositoryUrl>https://github.com/smbcloudXYZ/smbcloud-cli</RepositoryUrl>
18 + <PackageTags>mcp;mobile;ios;android;tv;automation;developer-tools;dotnet-tool</PackageTags>
19 + <PublishRepositoryUrl>true</PublishRepositoryUrl>
20 + </PropertyGroup>
21 +
22 + <ItemGroup>
23 + <None Include="README.md" Pack="true" PackagePath="" />
24 + <Content Include="native/**/*" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" Pack="false" Visible="false" />
25 + </ItemGroup>
26 +</Project>
pypi-xcrs/README.md new
+93
@@ -0,0 +1,93 @@
1 +<!-- LOGO -->
2 +<h1>
3 +<p align="center">
4 + <img src="https://avatars.githubusercontent.com/u/89791739?s=200&v=4" alt="smbCloud Logo" width="128">
5 + <br>xcrs
6 +</h1>
7 + <p align="center">
8 + Cross-platform mobile and TV app automation over MCP.
9 + <br />
10 + <br />
11 + <a href="https://smbcloud.xyz/">Website</a>
12 + ·
13 + <a href="https://smbcloud.xyz/posts">Documentation</a>
14 + ·
15 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/releases">Releases</a>
16 + ·
17 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/issues">Issues</a>
18 + </p>
19 + <p align="center">
20 + <a href="https://pypi.org/project/xcrs/"><img alt="PyPI" src="https://img.shields.io/pypi/v/xcrs"></a>
21 + <a href="https://www.npmjs.com/package/@smbcloud/xcrs"><img alt="npm" src="https://img.shields.io/npm/v/@smbcloud/xcrs"></a>
22 + <a href="https://www.nuget.org/packages/SmbCloud.Xcrs"><img alt="NuGet" src="https://img.shields.io/nuget/v/SmbCloud.Xcrs"></a>
23 + <a href="https://crates.io/crates/xcrs"><img alt="Crates.io" src="https://img.shields.io/crates/v/xcrs"></a>
24 + <a href="https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/smbcloudXYZ/smbcloud-cli"></a>
25 + </p>
26 +</p>
27 +
28 +## About
29 +
30 +**`xcrs`** drives mobile and TV apps — on iOS simulators, physical Apple
31 +devices, and adb-connected Android phones, tablets, emulators, and TVs — through
32 +the [Model Context Protocol](https://modelcontextprotocol.io/). It is the
33 +standalone automation profile of the [smbCloud CLI](https://smbcloud.xyz/); the
34 +same tools are also available via `smb --mcp --scope automation`.
35 +
36 +This package installs the native `xcrs` executable for your platform directly —
37 +no Node.js, no Docker, no runtime dependencies.
38 +
39 +## Install
40 +
41 +```sh
42 +pip install xcrs
43 +```
44 +
45 +Or run it without installing:
46 +
47 +```sh
48 +uvx xcrs --mcp
49 +```
50 +
51 +## Quick start
52 +
53 +Run it as an MCP server over stdio and point your MCP client at it:
54 +
55 +```sh
56 +xcrs --mcp
57 +```
58 +
59 +**Recommended flow:** `device_list` → `device_select` → `device_capabilities`,
60 +then inspect with `screen_capture` / `ui_describe` and drive with the `input_*`
61 +tools.
62 +
63 +## Other installation methods
64 +
65 +- Cargo: `cargo install xcrs`
66 +- npm: `npm install -g @smbcloud/xcrs`
67 +- NuGet: `dotnet tool install --global SmbCloud.Xcrs`
68 +
69 +## Platform support
70 +
71 +| Platform | Architecture |
72 +| ------------- | ------------ |
73 +| macOS | arm64, x64 |
74 +| Linux (glibc) | arm64, x64 |
75 +| Windows | x64 |
76 +
77 +The full Apple automation surface (`ui_describe`, `ui_element_list`, simulator
78 +control) requires macOS with Xcode command-line tools. Android automation over
79 +`adb` works from any platform.
80 +
81 +## Source
82 +
83 +- Repository: <https://github.com/smbcloudXYZ/smbcloud-cli>
84 +- Documentation: <https://smbcloud.xyz/posts>
85 +- Issues: <https://github.com/smbcloudXYZ/smbcloud-cli/issues>
86 +
87 +## License
88 +
89 +Apache-2.0
90 +
91 +## Copyright
92 +
93 +© 2026 [Splitfire AB](https://5mb.app) ([smbCloud](https://smbcloud.xyz)).
pypi-xcrs/pyproject.toml new
+38
@@ -0,0 +1,38 @@
1 +[build-system]
2 +requires = ["maturin>=1.7,<2.0"]
3 +build-backend = "maturin"
4 +
5 +[project]
6 +name = "xcrs"
7 +description = "Cross-platform mobile and TV app automation over MCP."
8 +readme = "README.md"
9 +requires-python = ">=3.8"
10 +dynamic = ["version"]
11 +license = { text = "Apache-2.0" }
12 +authors = [{ name = "Seto Elkahfi", email = "seto@smbcloud.xyz" }]
13 +keywords = ["mcp", "mobile", "ios", "android", "tv", "automation", "adb", "cli"]
14 +classifiers = [
15 + "Development Status :: 4 - Beta",
16 + "Environment :: Console",
17 + "Intended Audience :: Developers",
18 + "License :: OSI Approved :: Apache Software License",
19 + "Operating System :: MacOS",
20 + "Operating System :: Microsoft :: Windows",
21 + "Operating System :: POSIX :: Linux",
22 + "Programming Language :: Python :: 3",
23 + "Programming Language :: Rust",
24 + "Topic :: Software Development :: Testing",
25 + "Topic :: Software Development :: Build Tools",
26 + "Topic :: Utilities",
27 +]
28 +
29 +[project.urls]
30 +Homepage = "https://smbcloud.xyz/"
31 +Documentation = "https://smbcloud.xyz/posts"
32 +Repository = "https://github.com/smbcloudXYZ/smbcloud-cli"
33 +Issues = "https://github.com/smbcloudXYZ/smbcloud-cli/issues"
34 +
35 +[tool.maturin]
36 +manifest-path = "../crates/xcrs/Cargo.toml"
37 +bindings = "bin"
38 +strip = true
scripts/check-release-versions.mjs
+11
@@ -74,6 +74,13 @@ const npmLock = JSON.parse(read("npm/smbcloud-cli/package-lock.json"));
74 check("npm/smbcloud-cli/package-lock.json", npmLock.version);
75 check("npm/smbcloud-cli/package-lock.json packages root", npmLock.packages?.[""]?.version);
76
77 +const npmXcrsPackage = JSON.parse(read("npm/xcrs/package.json"));
78 +check("npm/xcrs/package.json", npmXcrsPackage.version);
79 +
80 +const npmXcrsLock = JSON.parse(read("npm/xcrs/package-lock.json"));
81 +check("npm/xcrs/package-lock.json", npmXcrsLock.version);
82 +check("npm/xcrs/package-lock.json packages root", npmXcrsLock.packages?.[""]?.version);
83 +
84 for (const path of ["server.json", "server-xcrs.json"]) {
85 const server = JSON.parse(read(path));
86 check(path, server.version);
@@ -86,6 +93,10 @@ check(
93 "nuget/smbcloud-cli/SmbCloud.Cli.csproj",
94 read("nuget/smbcloud-cli/SmbCloud.Cli.csproj").match(/<PackageVersion>([^<]+)<\/PackageVersion>/)?.[1],
95 );
96 +check(
97 + "nuget/xcrs/Xcrs.csproj",
98 + read("nuget/xcrs/Xcrs.csproj").match(/<PackageVersion>([^<]+)<\/PackageVersion>/)?.[1],
99 +);
100 check(
101 "sdk/gems/email/Gemfile.lock",
102 read("sdk/gems/email/Gemfile.lock").match(/smbcloud-email \(([^)]+)\)/)?.[1],
scripts/sync-release-version.mjs
+47
@@ -6,6 +6,9 @@ const cliCargoTomlPath = resolve(repoRoot, "crates/cli/Cargo.toml");
6 const npmCliPackageJsonPath = resolve(repoRoot, "npm/smbcloud-cli/package.json");
7 const npmCliPackageLockPath = resolve(repoRoot, "npm/smbcloud-cli/package-lock.json");
8 const nugetCliProjectPath = resolve(repoRoot, "nuget/smbcloud-cli/SmbCloud.Cli.csproj");
9 +const npmXcrsPackageJsonPath = resolve(repoRoot, "npm/xcrs/package.json");
10 +const npmXcrsPackageLockPath = resolve(repoRoot, "npm/xcrs/package-lock.json");
11 +const nugetXcrsProjectPath = resolve(repoRoot, "nuget/xcrs/Xcrs.csproj");
12 const sdkNpmPackageJsonPath = resolve(repoRoot, "sdk/npm/smbcloud-auth/package.json");
13 const authGemVersionPath = resolve(repoRoot, "sdk/gems/auth/lib/auth/version.rb");
14 const authGemCargoTomlPath = resolve(repoRoot, "sdk/gems/auth/ext/auth/Cargo.toml");
@@ -104,6 +107,50 @@ if (
107 updatedPaths.push(nugetCliProjectPath);
108 }
109
110 +if (
111 + updateFile(npmXcrsPackageJsonPath, (content) => {
112 + const parsed = JSON.parse(content);
113 + parsed.version = releaseVersion;
114 +
115 + for (const packageName of Object.keys(parsed.optionalDependencies ?? {})) {
116 + parsed.optionalDependencies[packageName] = releaseVersion;
117 + }
118 +
119 + return `${JSON.stringify(parsed, null, 2)}\n`;
120 + })
121 +) {
122 + updatedPaths.push(npmXcrsPackageJsonPath);
123 +}
124 +
125 +if (
126 + updateFile(npmXcrsPackageLockPath, (content) => {
127 + const parsed = JSON.parse(content);
128 + parsed.version = releaseVersion;
129 + parsed.packages[""].version = releaseVersion;
130 +
131 + for (const packageName of Object.keys(parsed.packages[""].optionalDependencies ?? {})) {
132 + parsed.packages[""].optionalDependencies[packageName] = releaseVersion;
133 + }
134 +
135 + return `${JSON.stringify(parsed, null, 2)}\n`;
136 + })
137 +) {
138 + updatedPaths.push(npmXcrsPackageLockPath);
139 +}
140 +
141 +if (
142 + updateFile(nugetXcrsProjectPath, (content) =>
143 + replaceOrThrow(
144 + content,
145 + /<PackageVersion>[^<]+<\/PackageVersion>/,
146 + `<PackageVersion>${releaseVersion}</PackageVersion>`,
147 + `${nugetXcrsProjectPath} package version`,
148 + ),
149 + )
150 +) {
151 + updatedPaths.push(nugetXcrsProjectPath);
152 +}
153 +
154 if (
155 updateFile(sdkNpmPackageJsonPath, (content) => {
156 const parsed = JSON.parse(content);