diff --git a/.changeset/README.md b/.changeset/README.md
new file mode 100644
index 0000000..caef05b
--- /dev/null
+++ b/.changeset/README.md
@@ -0,0 +1,12 @@
+# Changesets
+
+This repo uses [Changesets](https://github.com/changesets/changesets) to version and publish
+**`@wdio/browserstack-service`** on BrowserStack's own cadence (independent of WebdriverIO's
+release schedule).
+
+- Add a changeset for any user-facing change: `npm run changeset` (pick patch/minor/major).
+- On merge to `main` (the v9 line) or `v8` (the v8 line), the Release workflow opens a
+ "Version Packages" PR; merging that PR publishes to npm via OIDC trusted publishing.
+- The gRPC/protobuf core **`@browserstack/wdio-browserstack-service`** is in `ignore` (see
+ `config.json`) — it is versioned and published separately by the SDK team and is never
+ touched by this pipeline.
diff --git a/.changeset/config.json b/.changeset/config.json
new file mode 100644
index 0000000..558465d
--- /dev/null
+++ b/.changeset/config.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
+ "changelog": "@changesets/cli/changelog",
+ "commit": false,
+ "fixed": [],
+ "linked": [],
+ "access": "public",
+ "baseBranch": "main",
+ "updateInternalDependencies": "patch",
+ "ignore": ["@browserstack/wdio-browserstack-service"]
+}
diff --git a/.changeset/take-over-publishing.md b/.changeset/take-over-publishing.md
new file mode 100644
index 0000000..a7b8de6
--- /dev/null
+++ b/.changeset/take-over-publishing.md
@@ -0,0 +1,8 @@
+---
+"@wdio/browserstack-service": minor
+---
+
+BrowserStack now publishes `@wdio/browserstack-service` from its own repository
+(`browserstack/wdio-browserstack-service`) on an independent release cadence, using npm OIDC
+trusted publishing. No change for end users — same package name and the same
+`services: ['browserstack']` configuration continue to work unchanged.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..5e3763e
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,38 @@
+name: CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+ - v8
+
+permissions:
+ contents: read
+
+jobs:
+ build-test:
+ name: Build & test (node ${{ matrix.node-version }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ node-version: ['18.20', '20', '22']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: 'npm'
+
+ - name: Install
+ run: npm ci
+
+ - name: Build (core + service)
+ run: npm run build
+
+ - name: Test
+ run: npm test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..12f05cc
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,75 @@
+name: Release
+
+# Publishes @wdio/browserstack-service to npm via OIDC Trusted Publishing
+# (no long-lived NPM_TOKEN). One-time setup by an @wdio npm org admin on npmjs.com:
+# @wdio/browserstack-service -> Settings -> Trusted Publisher -> GitHub Actions
+# Organization/user: browserstack
+# Repository: wdio-browserstack-service
+# Workflow filename: release.yml
+# Environment: (leave empty)
+# Requires: PUBLIC repo (for provenance), npm >= 11.5.1, Node >= 22.14.0.
+#
+# The gRPC core (@browserstack/wdio-browserstack-service) is in .changeset ignore,
+# so this workflow never versions or publishes it.
+
+on:
+ push:
+ branches:
+ - main # v9 line -> dist-tag "latest"
+ - v8 # v8 line -> dist-tag "v8" (from publishConfig.tag on the v8 branch)
+
+# Never run main and v8 releases on top of each other.
+concurrency: release-${{ github.ref }}
+
+permissions:
+ contents: write # commit the "Version Packages" PR + create git tags
+ pull-requests: write # open the "Version Packages" PR
+ id-token: write # OIDC for npm trusted publishing + provenance
+
+jobs:
+ release:
+ name: Release
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ fetch-depth: 0 # Changesets needs full history/tags
+
+ - name: Setup Node
+ # NOTE: intentionally NO `registry-url:` here. setup-node's registry-url writes
+ # `//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}` into ~/.npmrc; with no
+ # NODE_AUTH_TOKEN that becomes an empty token line that can shadow OIDC Trusted
+ # Publishing at `npm publish` time. npm already defaults to registry.npmjs.org and
+ # publishConfig.access=public handles the scoped publish, so the line isn't needed.
+ # (Follow-up to consider: split changesets/action so publish runs as its own
+ # top-level step — further de-risks OIDC. Tracked, not done here.)
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
+ with:
+ node-version: 22 # resolves to >= 22.14 on the runner (OIDC floor)
+ cache: 'npm'
+
+ # Trusted Publishing needs npm >= 11.5.1. Pin to the 11.x line so a future
+ # npm major can never silently change publish behaviour.
+ - name: Upgrade npm to an OIDC-capable version
+ run: npm install -g npm@11
+
+ - name: Install
+ run: npm ci
+
+ - name: Build
+ run: npm run build
+
+ - name: Test
+ run: npm test
+
+ - name: Create Release PR or publish to npm
+ uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
+ with:
+ version: npm run version # changeset version (opens the "Version Packages" PR)
+ publish: npm run release # changeset publish (honors publishConfig.tag per branch)
+ createGithubReleases: true
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # No NPM_TOKEN: auth is OIDC via id-token: write above.
+ NPM_CONFIG_PROVENANCE: 'true'
diff --git a/.gitignore b/.gitignore
index 7feec19..01893f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,24 @@
node_modules
+
+# build outputs
dist
generated
+build
+src/generated
+packages/*/dist
+packages/*/build
+packages/*/src/generated
+
+# test/coverage
+coverage
+packages/*/coverage
+
+# packed tarballs & logs
+*.tgz
+*.log
+logs
+
+# local/editor
+.DS_Store
+.env
+.env.*
diff --git a/README.md b/README.md
index c450c7d..c1a0a18 100644
--- a/README.md
+++ b/README.md
@@ -1,119 +1,51 @@
-# @browserstack/wdio-browserstack-service
+# wdio-browserstack-service
-
-
+Monorepo for the BrowserStack WebdriverIO integration, maintained by BrowserStack.
-Core SDK for BrowserStack integration used by the WebdriverIO BrowserStack Service.
-For user configuration and service options, see the official service README:
-[https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-browserstack-service/README.md](https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-browserstack-service/README.md)
+| Package | npm | What it is |
+|---|---|---|
+| [`packages/browserstack-service`](./packages/browserstack-service) | [`@wdio/browserstack-service`](https://www.npmjs.com/package/@wdio/browserstack-service) | The WebdriverIO service users add via `services: ['browserstack']`. |
+| [`packages/core`](./packages/core) | [`@browserstack/wdio-browserstack-service`](https://www.npmjs.com/package/@browserstack/wdio-browserstack-service) | gRPC/protobuf core SDK consumed by the service. |
-## Table of Contents
-1. [Overview](#overview)
-2. [Code Generation](#code-generation)
-3. [Development](#development)
-4. [Contributing](#contributing)
-5. [License](#license)
+## Usage (for end users)
-## Overview
-This package provides the TypeScript-based gRPC client and Protobuf definitions
-used internally by the `@wdio/browserstack-service` plugin for WebdriverIO.
-It includes:
-- Generated TypeScript types and clients from Protobuf definitions.
-- Message factory constructors for backward compatibility.
+Nothing changes — install the service and add it to your WebdriverIO config:
-## Installation
-This module is included as a dependency of the `@wdio/browserstack-service` package.
-Users should install and configure the service as documented in the linked README above.
-
-## Setup & Configuration
-Add the service to your WebdriverIO configuration (`wdio.conf.js`):
-
-```
-export BROWSERSTACK_USERNAME=your_username
-export BROWSERSTACK_ACCESS_KEY=your_access_key
+```sh
+npm i -D @wdio/browserstack-service
```
-## Usage
-Import and use the gRPC client and message constructors:
-```ts
-import { SDKClient, StartBinSessionRequestConstructor } from '@browserstack/wdio-browserstack-service';
-import path from 'path';
-import process from 'process';
-import { CLIUtils } from '@browserstack/cli-utils'; // example import, adjust if needed
-import { version as packageVersion } from './package.json'; // adjust to your setup
-
-// Initialize the client (uses default insecure credentials unless overridden)
-const client = new SDKClient('grpc.browserstack.com:443');
-
-// Collect framework details
-const automationFrameworkDetail = CLIUtils.getAutomationFrameworkDetail();
-const testFrameworkDetail = CLIUtils.getTestFrameworkDetail();
-
-const frameworkVersions = {
- ...automationFrameworkDetail.version,
- ...testFrameworkDetail.version
-};
-
-// Build StartBinSessionRequest
-const startReq = StartBinSessionRequestConstructor.create({
- binSessionId: 'your-session-id', // replace with actual session id
- sdkLanguage: CLIUtils.getSdkLanguage(),
- sdkVersion: packageVersion,
- pathProject: process.cwd(),
- pathConfig: path.resolve(process.cwd(), 'browserstack.yml'),
- cliArgs: process.argv.slice(2),
- frameworks: [automationFrameworkDetail.name, testFrameworkDetail.name],
- frameworkVersions,
- language: CLIUtils.getSdkLanguage(),
- testFramework: testFrameworkDetail.name,
- wdioConfig: {}, // provide your WDIO config if applicable
-});
-
-// Start a session
-client.startBinSession(startReq).then(response => {
- console.log('Started session:', response.binSessionId);
-}).catch(err => {
- console.error('Failed to start session:', err);
-});
+```js
+// wdio.conf.js
+export const config = {
+ services: ['browserstack'],
+ // ...
+}
```
-## Code Generation
-This project uses [Buf](https://docs.buf.build/) and `ts-proto` to
-generate TypeScript code from Protobuf definitions.
-
-### Prerequisites
-- [Buf CLI](https://docs.buf.build/installation)
-- Node.js ≥16
+See the [service README](./packages/browserstack-service/README.md) for full configuration.
-### Generate & Build
-```bash
-# Clean previously generated files
-npm run clean
+## Development
-# Generate from .proto files
-npm run generate
+This is an npm workspace.
-# Compile to JS and declaration files
-npm run build
+```sh
+npm ci # install all packages
+npm run build # build core then service
+npm test # run the service test suite
```
-Generated files appear under `dist/` and should be published to npm.
+- `npm run build:core` / `npm run build:service` build a single package.
+- The service is bundled with esbuild (deps kept external) and ships TypeScript declarations from `tsc`.
-## Development
-Clone the repository and install dependencies:
-```bash
-git clone https://github.com/browserstack/wdio-browserstack-service.git
-cd wdio-browserstack-service
-npm install
-```
+## Releases
-Run generation and build:
-```bash
-npm run build
-```
+`@wdio/browserstack-service` is versioned and published with [Changesets](https://github.com/changesets/changesets)
+on BrowserStack's own cadence (independent of WebdriverIO core's release schedule):
-## Contributing
-Contributions are welcome! Please open issues or pull requests in the [GitHub repository](https://github.com/browserstack/wdio-browserstack-service).
+- `main` → `latest` dist-tag (v9 line)
+- `v8` branch → `v8` dist-tag (v8 line)
-## License
-MIT © BrowserStack
\ No newline at end of file
+Publishing uses **npm OIDC trusted publishing** (no long-lived token; provenance-signed). The gRPC core
+`@browserstack/wdio-browserstack-service` is released separately by the SDK team and is excluded from the
+Changesets pipeline (see [`.changeset/config.json`](./.changeset/config.json)).
diff --git a/package-lock.json b/package-lock.json
index 7051ae4..c82e096 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,29 +1,100 @@
{
- "name": "@browserstack/wdio-browserstack-service",
- "version": "2.0.2",
+ "name": "wdio-browserstack-service-monorepo",
+ "version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "@browserstack/wdio-browserstack-service",
- "version": "2.0.2",
+ "name": "wdio-browserstack-service-monorepo",
+ "version": "0.0.0",
+ "license": "MIT",
+ "workspaces": [
+ "packages/*"
+ ],
+ "devDependencies": {
+ "@changesets/cli": "^2.27.9"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@bufbuild/protobuf": "^2.5.2",
- "@grpc/grpc-js": "1.13.3"
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
},
- "devDependencies": {
- "@bufbuild/buf": "^1.55.1",
- "ts-proto": "^2.7.5",
- "typescript": "^5.4.5"
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+ "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@browserstack/ai-sdk-node": {
+ "version": "1.5.17",
+ "resolved": "https://registry.npmjs.org/@browserstack/ai-sdk-node/-/ai-sdk-node-1.5.17.tgz",
+ "integrity": "sha512-odjnFulpBeF64UGHA+bIxkIcALYvEPznTl4U0hRT1AFfn4FqT+4wQdPBYnSnlc2XWTedv4zCDvbp4AFrtKXHEw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "axios": "^1.7.4",
+ "uuid": "9.0.1"
+ }
+ },
+ "node_modules/@browserstack/ai-sdk-node/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
}
},
+ "node_modules/@browserstack/wdio-browserstack-service": {
+ "resolved": "packages/core",
+ "link": true
+ },
"node_modules/@bufbuild/buf": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.56.0.tgz",
- "integrity": "sha512-1xQWOf3FCDDTi+5B/VScQ73EP6ACwQPCP4ODvCq2L6IVgFtvYX49ur6cQ2qCM8yFitIHESm/Nbff93sh+V/Iog==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.70.0.tgz",
+ "integrity": "sha512-oJWGqltlu8F7VVNHLoJ3pFXhjfiGpbh7+/mXW0y+VMPWFGxc9YDv4de1UcX7zhhjV6MbE4SiEGo5Gs5jhpVg5A==",
"dev": true,
"hasInstallScript": true,
+ "license": "Apache-2.0",
"bin": {
"buf": "bin/buf",
"protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking",
@@ -33,23 +104,24 @@
"node": ">=12"
},
"optionalDependencies": {
- "@bufbuild/buf-darwin-arm64": "1.56.0",
- "@bufbuild/buf-darwin-x64": "1.56.0",
- "@bufbuild/buf-linux-aarch64": "1.56.0",
- "@bufbuild/buf-linux-armv7": "1.56.0",
- "@bufbuild/buf-linux-x64": "1.56.0",
- "@bufbuild/buf-win32-arm64": "1.56.0",
- "@bufbuild/buf-win32-x64": "1.56.0"
+ "@bufbuild/buf-darwin-arm64": "1.70.0",
+ "@bufbuild/buf-darwin-x64": "1.70.0",
+ "@bufbuild/buf-linux-aarch64": "1.70.0",
+ "@bufbuild/buf-linux-armv7": "1.70.0",
+ "@bufbuild/buf-linux-x64": "1.70.0",
+ "@bufbuild/buf-win32-arm64": "1.70.0",
+ "@bufbuild/buf-win32-x64": "1.70.0"
}
},
"node_modules/@bufbuild/buf-darwin-arm64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.56.0.tgz",
- "integrity": "sha512-9neaI9gx1sxOGl9xrL7kw6H+0WmVAFlIQTIDc3vt1qRhfgOt/8AWOHSOWppGTRjNiB0qh6Xie1LYHv/jgDVN0g==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.70.0.tgz",
+ "integrity": "sha512-c7owUswBbMmwfHPH9JRBEJu09mrXYGC33V2JQCgraWCBm74Z95AOkhDua50qiBrQnysvJkJ0p/z4MWxJqcpnIA==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
@@ -59,13 +131,14 @@
}
},
"node_modules/@bufbuild/buf-darwin-x64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.56.0.tgz",
- "integrity": "sha512-nRHPMXV8fr/lqU+u/1GGsUg7OvNcxJuCJoJpfRoRg38b+NPzOz2FkQAs5OEJzzprQB5aftn5//cl8YXjgvTuFA==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.70.0.tgz",
+ "integrity": "sha512-sucV3lQXVuOqYs3+ToulkUh2tZuMnl286DKb44imp3PnexVhAVOP7d3ybYe98HNGwysEdjNP2WIOGb0uKuRCIQ==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
@@ -75,13 +148,14 @@
}
},
"node_modules/@bufbuild/buf-linux-aarch64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.56.0.tgz",
- "integrity": "sha512-+td559RuKNwYDnq49NrIDGJ4F73Ra4QzVVbsC+UeveA0HMnIGRzFbchGjHtNJyaZsI57sXJ7dCHH0iFV3jcYwQ==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.70.0.tgz",
+ "integrity": "sha512-4viSYqbhIusd6LR+JayDex8S1rLUL+hTUMYUgSPl75EC93FpJM4vkk2RhoAhyjQqWF/JQLcyWV8kjRRiIwygdg==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -91,13 +165,14 @@
}
},
"node_modules/@bufbuild/buf-linux-armv7": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.56.0.tgz",
- "integrity": "sha512-9v3zmos6wRTBc4QeIg4rfDmPzmTgtUTRCbhr87qws/yddIT8cFtHHhy1whnozBNqtmYOdwZNBNx/QXqGGcRuKw==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.70.0.tgz",
+ "integrity": "sha512-GqujpTX4MXtYiUkxd6oI1g0JaCX3L6koT16Gl0D0HIQ/V2mptH7x4UW8nK3tAURMjrHsEEhcSJRtmfINTTKnsg==",
"cpu": [
"arm"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -107,13 +182,14 @@
}
},
"node_modules/@bufbuild/buf-linux-x64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.56.0.tgz",
- "integrity": "sha512-3jZHHBol1fuichNke7LJtHJUdw314XBj6OuJHY6IufsaaVIj1mtM2DPbGiDhYB453J7FiV/buadctKBxAAHclg==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.70.0.tgz",
+ "integrity": "sha512-5WHGUIb5iLFXcnqV33TDejqaPgx0CWFaYW7b4wh12wT0w3DR+ghFq6S6RmYyZLbTuhS4ZFsf+xyk5m+HViKxrA==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -123,13 +199,14 @@
}
},
"node_modules/@bufbuild/buf-win32-arm64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.56.0.tgz",
- "integrity": "sha512-KMGzSf9rIbT01Jb2685JovwRRYEdL7Zbs6ZrjyhIHBgKK6cBwz1AJvEaDrWMEzCdv+opQwjgM6UdtA4e9BWP1A==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.70.0.tgz",
+ "integrity": "sha512-dU1qh7iD08/1avCHwIOoGsatQctE6uGwgOue9GOaThi8/Rdy1x9CC/eFdyFSeCMwbUg9ABQvMGUocylfUe6xDw==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"win32"
@@ -139,13 +216,14 @@
}
},
"node_modules/@bufbuild/buf-win32-x64": {
- "version": "1.56.0",
- "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.56.0.tgz",
- "integrity": "sha512-19LFOCyFFVTaaqNGtYTpiF67fcpneWZFlm8UNU+Xs87Kh+N5i/LjDjNytnpFT6snwU4/S+UUkq7WgS6UPjqXIg==",
+ "version": "1.70.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.70.0.tgz",
+ "integrity": "sha512-iKYbjTbEk0ppkv2SrsPFhYus93kj/aMN8aRsrpuo91ZVqXg8JcH4XXbgFpwiFAsiABjqKICFfnDomrFvv49UOA==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "Apache-2.0",
"optional": true,
"os": [
"win32"
@@ -155,343 +233,9035 @@
}
},
"node_modules/@bufbuild/protobuf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.6.3.tgz",
- "integrity": "sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ=="
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz",
+ "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==",
+ "license": "(Apache-2.0 AND BSD-3-Clause)"
},
- "node_modules/@grpc/grpc-js": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.3.tgz",
- "integrity": "sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==",
+ "node_modules/@changesets/apply-release-plan": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.1.1.tgz",
+ "integrity": "sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@grpc/proto-loader": "^0.7.13",
- "@js-sdsl/ordered-map": "^4.4.2"
- },
- "engines": {
- "node": ">=12.10.0"
+ "@changesets/config": "^3.1.4",
+ "@changesets/get-version-range-type": "^0.4.0",
+ "@changesets/git": "^3.0.4",
+ "@changesets/should-skip-package": "^0.1.2",
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "detect-indent": "^6.0.0",
+ "fs-extra": "^7.0.1",
+ "lodash.startcase": "^4.4.0",
+ "outdent": "^0.5.0",
+ "prettier": "^2.7.1",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.3"
}
},
- "node_modules/@grpc/proto-loader": {
- "version": "0.7.15",
- "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
- "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "node_modules/@changesets/assemble-release-plan": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.10.tgz",
+ "integrity": "sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "lodash.camelcase": "^4.3.0",
- "long": "^5.0.0",
- "protobufjs": "^7.2.5",
- "yargs": "^17.7.2"
- },
- "bin": {
- "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
- },
- "engines": {
- "node": ">=6"
+ "@changesets/errors": "^0.2.0",
+ "@changesets/get-dependents-graph": "^2.1.4",
+ "@changesets/should-skip-package": "^0.1.2",
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "semver": "^7.5.3"
}
},
- "node_modules/@js-sdsl/ordered-map": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
- "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/js-sdsl"
+ "node_modules/@changesets/changelog-git": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz",
+ "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/types": "^6.1.0"
}
},
- "node_modules/@protobufjs/aspromise": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
- "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
- },
- "node_modules/@protobufjs/base64": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
- "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
- },
- "node_modules/@protobufjs/codegen": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
- "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
- },
- "node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "node_modules/@changesets/cli": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.31.0.tgz",
+ "integrity": "sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
+ "@changesets/apply-release-plan": "^7.1.1",
+ "@changesets/assemble-release-plan": "^6.0.10",
+ "@changesets/changelog-git": "^0.2.1",
+ "@changesets/config": "^3.1.4",
+ "@changesets/errors": "^0.2.0",
+ "@changesets/get-dependents-graph": "^2.1.4",
+ "@changesets/get-release-plan": "^4.0.16",
+ "@changesets/git": "^3.0.4",
+ "@changesets/logger": "^0.1.1",
+ "@changesets/pre": "^2.0.2",
+ "@changesets/read": "^0.6.7",
+ "@changesets/should-skip-package": "^0.1.2",
+ "@changesets/types": "^6.1.0",
+ "@changesets/write": "^0.4.0",
+ "@inquirer/external-editor": "^1.0.2",
+ "@manypkg/get-packages": "^1.1.3",
+ "ansi-colors": "^4.1.3",
+ "enquirer": "^2.4.1",
+ "fs-extra": "^7.0.1",
+ "mri": "^1.2.0",
+ "package-manager-detector": "^0.2.0",
+ "picocolors": "^1.1.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.3",
+ "spawndamnit": "^3.0.1",
+ "term-size": "^2.1.0"
+ },
+ "bin": {
+ "changeset": "bin.js"
}
},
- "node_modules/@protobufjs/float": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
- "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
+ "node_modules/@changesets/config": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.4.tgz",
+ "integrity": "sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/errors": "^0.2.0",
+ "@changesets/get-dependents-graph": "^2.1.4",
+ "@changesets/logger": "^0.1.1",
+ "@changesets/should-skip-package": "^0.1.2",
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1",
+ "micromatch": "^4.0.8"
+ }
},
- "node_modules/@protobufjs/inquire": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
- "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
+ "node_modules/@changesets/errors": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz",
+ "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "extendable-error": "^0.1.5"
+ }
},
- "node_modules/@protobufjs/path": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
- "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
+ "node_modules/@changesets/get-dependents-graph": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.4.tgz",
+ "integrity": "sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "picocolors": "^1.1.0",
+ "semver": "^7.5.3"
+ }
},
- "node_modules/@protobufjs/pool": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
- "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
+ "node_modules/@changesets/get-release-plan": {
+ "version": "4.0.16",
+ "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.16.tgz",
+ "integrity": "sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/assemble-release-plan": "^6.0.10",
+ "@changesets/config": "^3.1.4",
+ "@changesets/pre": "^2.0.2",
+ "@changesets/read": "^0.6.7",
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3"
+ }
},
- "node_modules/@protobufjs/utf8": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
- "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
+ "node_modules/@changesets/get-version-range-type": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz",
+ "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@types/node": {
- "version": "24.2.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz",
- "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==",
+ "node_modules/@changesets/git": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz",
+ "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "undici-types": "~7.10.0"
+ "@changesets/errors": "^0.2.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "is-subdir": "^1.1.1",
+ "micromatch": "^4.0.8",
+ "spawndamnit": "^3.0.1"
}
},
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "engines": {
- "node": ">=8"
+ "node_modules/@changesets/logger": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz",
+ "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.1.0"
}
},
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/@changesets/parse": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.3.tgz",
+ "integrity": "sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "@changesets/types": "^6.1.0",
+ "js-yaml": "^4.1.1"
}
},
- "node_modules/case-anything": {
- "version": "2.1.13",
- "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz",
- "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
+ "node_modules/@changesets/pre": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz",
+ "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==",
"dev": true,
- "engines": {
- "node": ">=12.13"
- },
- "funding": {
- "url": "https://github.com/sponsors/mesqueeb"
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/errors": "^0.2.0",
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1"
}
},
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "node_modules/@changesets/read": {
+ "version": "0.6.7",
+ "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.7.tgz",
+ "integrity": "sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
+ "@changesets/git": "^3.0.4",
+ "@changesets/logger": "^0.1.1",
+ "@changesets/parse": "^0.4.3",
+ "@changesets/types": "^6.1.0",
+ "fs-extra": "^7.0.1",
+ "p-filter": "^2.1.0",
+ "picocolors": "^1.1.0"
}
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/@changesets/should-skip-package": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz",
+ "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
+ "@changesets/types": "^6.1.0",
+ "@manypkg/get-packages": "^1.1.3"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "node_modules/@changesets/types": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz",
+ "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/detect-libc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
- "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+ "node_modules/@changesets/write": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz",
+ "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==",
"dev": true,
- "bin": {
- "detect-libc": "bin/detect-libc.js"
- },
+ "license": "MIT",
+ "dependencies": {
+ "@changesets/types": "^6.1.0",
+ "fs-extra": "^7.0.1",
+ "human-id": "^4.1.1",
+ "prettier": "^2.7.1"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
+ "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
+ "license": "MIT",
"engines": {
- "node": ">=0.10"
+ "node": ">=0.1.90"
}
},
- "node_modules/dprint-node": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz",
- "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
+ "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
+ "cpu": [
+ "ppc64"
+ ],
"dev": true,
- "dependencies": {
- "detect-libc": "^1.0.3"
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
+ "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=6"
+ "node": ">=18"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
+ "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": "6.* || 8.* || >= 10.*"
+ "node": ">=18"
}
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
+ "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
- "node_modules/lodash.camelcase": {
- "version": "4.3.0",
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
+ "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
+ "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
+ "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
+ "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
+ "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
+ "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
+ "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
+ "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
+ "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
+ "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
+ "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
+ "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
+ "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
+ "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
+ "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
+ "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
+ "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
+ "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
+ "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.3.tgz",
+ "integrity": "sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.13",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.15",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
+ "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@inquirer/ansi": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
+ "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/checkbox": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz",
+ "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/confirm": {
+ "version": "5.1.21",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
+ "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/core": {
+ "version": "10.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
+ "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "cli-width": "^4.1.0",
+ "mute-stream": "^2.0.0",
+ "signal-exit": "^4.1.0",
+ "wrap-ansi": "^6.2.0",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/editor": {
+ "version": "4.2.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz",
+ "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/external-editor": "^1.0.3",
+ "@inquirer/type": "^3.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/expand": {
+ "version": "4.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz",
+ "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/external-editor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
+ "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
+ "license": "MIT",
+ "dependencies": {
+ "chardet": "^2.1.1",
+ "iconv-lite": "^0.7.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.15",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
+ "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/input": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz",
+ "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/number": {
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz",
+ "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/password": {
+ "version": "4.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz",
+ "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/prompts": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz",
+ "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/checkbox": "^4.3.2",
+ "@inquirer/confirm": "^5.1.21",
+ "@inquirer/editor": "^4.2.23",
+ "@inquirer/expand": "^4.0.23",
+ "@inquirer/input": "^4.3.1",
+ "@inquirer/number": "^3.0.23",
+ "@inquirer/password": "^4.0.23",
+ "@inquirer/rawlist": "^4.1.11",
+ "@inquirer/search": "^3.2.2",
+ "@inquirer/select": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/rawlist": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz",
+ "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/search": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz",
+ "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/select": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz",
+ "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/type": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
+ "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
+ "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@manypkg/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "@types/node": "^12.7.1",
+ "find-up": "^4.1.0",
+ "fs-extra": "^8.1.0"
+ }
+ },
+ "node_modules/@manypkg/find-root/node_modules/@types/node": {
+ "version": "12.20.55",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
+ "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@manypkg/find-root/node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/@manypkg/get-packages": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz",
+ "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "@changesets/types": "^4.0.1",
+ "@manypkg/find-root": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "^11.0.0",
+ "read-yaml-file": "^1.1.0"
+ }
+ },
+ "node_modules/@manypkg/get-packages/node_modules/@changesets/types": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz",
+ "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@manypkg/get-packages/node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/@nodable/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodable"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@open-draft/until": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz",
+ "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==",
+ "license": "MIT"
+ },
+ "node_modules/@percy/appium-app": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@percy/appium-app/-/appium-app-2.1.0.tgz",
+ "integrity": "sha512-XVigKgAcXEerIch3Ufngac07gOH4KnfTDp/xyPujDyjvAZSWfIyIRnojmfbLEs2HnZEnmFFoEMX6ZB4Tk0SO/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@percy/sdk-utils": "^1.30.9",
+ "tmp": "^0.2.3"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@percy/sdk-utils": {
+ "version": "1.31.14",
+ "resolved": "https://registry.npmjs.org/@percy/sdk-utils/-/sdk-utils-1.31.14.tgz",
+ "integrity": "sha512-I31GM+aCHiME12jX9ac5COThZWOpTBONkR9J6D059wqiFhHtRenA2mWFx6rC+zUpG5un0imkal7tN9y1D4hPBg==",
+ "license": "MIT",
+ "dependencies": {
+ "pac-proxy-agent": "^7.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@percy/selenium-webdriver": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/@percy/selenium-webdriver/-/selenium-webdriver-2.2.6.tgz",
+ "integrity": "sha512-5aeJh3ncYQl1Ug8/eazae8Ux281cvUX87e5YvHTFnLKtELaqJEb2k0NoNZbnWpPgAdz7yxeZZgTEbDn9HTOSYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@percy/sdk-utils": "^1.31.10",
+ "node-request-interceptor": "^0.6.3"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@promptbook/utils": {
+ "version": "0.69.5",
+ "resolved": "https://registry.npmjs.org/@promptbook/utils/-/utils-0.69.5.tgz",
+ "integrity": "sha512-xm5Ti/Hp3o4xHrsK9Yy3MS6KbDxYbq485hDsFvxqaNA7equHLPdo8H8faTitTeb14QCDfLW4iwCxdVYu5sn6YQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://buymeacoffee.com/hejny"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/webgptorg/promptbook/blob/main/README.md#%EF%B8%8F-contributing"
+ }
+ ],
+ "license": "CC-BY-4.0",
+ "dependencies": {
+ "spacetrim": "0.11.59"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
+ "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
+ "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@puppeteer/browsers": {
+ "version": "2.13.2",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.2.tgz",
+ "integrity": "sha512-5EUZSUIc37H6aIXyWO0Z4y8NlF8NnjgmqeQgOGiswAU7pY0HOo16ho4+alIWmSfdZnjqBRawMsP3I5YqLSn6kw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.5.0",
+ "semver": "^7.7.4",
+ "tar-fs": "^3.1.1",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.0.tgz",
+ "integrity": "sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.0.tgz",
+ "integrity": "sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.0.tgz",
+ "integrity": "sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.0.tgz",
+ "integrity": "sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.0.tgz",
+ "integrity": "sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.0.tgz",
+ "integrity": "sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.0.tgz",
+ "integrity": "sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.0.tgz",
+ "integrity": "sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.0.tgz",
+ "integrity": "sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.0.tgz",
+ "integrity": "sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.0.tgz",
+ "integrity": "sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.0.tgz",
+ "integrity": "sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.0.tgz",
+ "integrity": "sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.0.tgz",
+ "integrity": "sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.0.tgz",
+ "integrity": "sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.0.tgz",
+ "integrity": "sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.0.tgz",
+ "integrity": "sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.0.tgz",
+ "integrity": "sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.0.tgz",
+ "integrity": "sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.0.tgz",
+ "integrity": "sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.0.tgz",
+ "integrity": "sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.0.tgz",
+ "integrity": "sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.0.tgz",
+ "integrity": "sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz",
+ "integrity": "sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz",
+ "integrity": "sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@sec-ant/readable-stream": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
+ "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@sindresorhus/merge-streams": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
+ "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/gitconfiglocal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/gitconfiglocal/-/gitconfiglocal-2.0.3.tgz",
+ "integrity": "sha512-W6hyZux6TrtKfF2I9XNLVcsFr4xRr0T+S6hrJ9nDkhA2vzsFPIEAbnY4vgb6v2yKXQ9MJVcbLsARNlMfg4EVtQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "25.9.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz",
+ "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": ">=7.24.0 <7.24.7"
+ }
+ },
+ "node_modules/@types/node/node_modules/undici-types": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/sinonjs__fake-timers": {
+ "version": "8.1.5",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz",
+ "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/tar": {
+ "version": "7.0.87",
+ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-7.0.87.tgz",
+ "integrity": "sha512-3IxNBV8LeY5oi2ZFpvAhOtW1+mHswkzM7BuisVrwJgPv67GBO2rkLPQlEKtzfHuLdhDDczhkCZeT+RuizMay4A==",
+ "deprecated": "This is a stub types definition. tar provides its own type definitions, so you do not need this installed.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tar": "*"
+ }
+ },
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
+ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz",
+ "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "3.2.6",
+ "@vitest/utils": "3.2.6",
+ "chai": "^5.2.0",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz",
+ "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.2.6",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz",
+ "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz",
+ "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "3.2.6",
+ "pathe": "^2.0.3",
+ "strip-literal": "^3.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz",
+ "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.6",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz",
+ "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^4.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz",
+ "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.6",
+ "loupe": "^3.1.4",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@wdio/browserstack-service": {
+ "resolved": "packages/browserstack-service",
+ "link": true
+ },
+ "node_modules/@wdio/cli": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.28.0.tgz",
+ "integrity": "sha512-jEKYdCvZ9ST8YQ4EvyV9lsEoRxhWenplGJppbiH9SKHiwPqrUapi/EE7f6CBDwkWP7NIlzj2PyTe+JRmkXILLw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@vitest/snapshot": "^2.1.1",
+ "@wdio/config": "9.28.0",
+ "@wdio/globals": "9.28.0",
+ "@wdio/logger": "9.18.0",
+ "@wdio/protocols": "9.28.0",
+ "@wdio/types": "9.28.0",
+ "@wdio/utils": "9.28.0",
+ "async-exit-hook": "^2.0.1",
+ "chalk": "^5.4.1",
+ "chokidar": "^4.0.0",
+ "create-wdio": "9.28.0",
+ "dotenv": "^17.2.0",
+ "import-meta-resolve": "^4.0.0",
+ "lodash.flattendeep": "^4.4.0",
+ "lodash.pickby": "^4.6.0",
+ "lodash.union": "^4.6.0",
+ "read-pkg-up": "^10.0.0",
+ "tsx": "^4.7.2",
+ "webdriverio": "9.28.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "wdio": "bin/wdio.js"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/cli/node_modules/@vitest/pretty-format": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz",
+ "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@wdio/cli/node_modules/@vitest/snapshot": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz",
+ "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@vitest/pretty-format": "2.1.9",
+ "magic-string": "^0.30.12",
+ "pathe": "^1.1.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@wdio/cli/node_modules/pathe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@wdio/cli/node_modules/tinyrainbow": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
+ "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@wdio/config": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.28.0.tgz",
+ "integrity": "sha512-a2po2x0Gi0hNRCuqSYSAvgwC9RZsj1tH9mt4MeLk2hyJBQCyy9DjBBjwyd4AcnE11XhqVaIkMaIMBSRu2dJwLw==",
+ "license": "MIT",
+ "dependencies": {
+ "@wdio/logger": "9.18.0",
+ "@wdio/types": "9.28.0",
+ "@wdio/utils": "9.28.0",
+ "deepmerge-ts": "^7.0.3",
+ "glob": "^10.2.2",
+ "import-meta-resolve": "^4.0.0",
+ "jiti": "^2.6.1"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/@wdio/config/node_modules/brace-expansion": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/@wdio/config/node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "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",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@wdio/config/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@wdio/config/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@wdio/globals": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-9.28.0.tgz",
+ "integrity": "sha512-poYsF7Gbm8kfYX6tdsPG862anOQKyUT8roe+rwdXaKSorz/s4XDJBm4kJiid6LgWKeAMSXDYzFODzDxhYhugWg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.20.0"
+ },
+ "peerDependencies": {
+ "expect-webdriverio": "^5.6.5",
+ "webdriverio": "^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "expect-webdriverio": {
+ "optional": false
+ },
+ "webdriverio": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/@wdio/logger": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.18.0.tgz",
+ "integrity": "sha512-HdzDrRs+ywAqbXGKqe1i/bLtCv47plz4TvsHFH3j729OooT5VH38ctFn5aLXgECmiAKDkmH/A6kOq2Zh5DIxww==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.1.2",
+ "loglevel": "^1.6.0",
+ "loglevel-plugin-prefix": "^0.8.4",
+ "safe-regex2": "^5.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/protocols": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.28.0.tgz",
+ "integrity": "sha512-bO9NeMCrtwfWI7q77GwfD68NlRNijnmwicW1OQ6p+7D3kZWEicfdhfvojPhjjf+e9XzqMDnUDGD5ni1lGMUBsg==",
+ "license": "MIT"
+ },
+ "node_modules/@wdio/repl": {
+ "version": "9.16.2",
+ "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-9.16.2.tgz",
+ "integrity": "sha512-FLTF0VL6+o5BSTCO7yLSXocm3kUnu31zYwzdsz4n9s5YWt83sCtzGZlZpt7TaTzb3jVUfxuHNQDTb8UMkCu0lQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "^20.1.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/repl/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@wdio/reporter": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.28.0.tgz",
+ "integrity": "sha512-q9gG6SXNTn/9cKF6EJ+aa5sGZM5HAVNsDZ3YU5B0IHg9ufdBuJgfT0LiAsnehLiceEuivuzPyz85vbDb0SFiVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "^20.1.0",
+ "@wdio/logger": "9.18.0",
+ "@wdio/types": "9.28.0",
+ "diff": "^8.0.2",
+ "object-inspect": "^1.12.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/reporter/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@wdio/types": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.28.0.tgz",
+ "integrity": "sha512-75JPq39gifkPNqOSn5C4/A5ZSyXwF+dGr5jfsCubFN9Lk9dKBXfjdbWueSQNpJg0jmE6dVrbT7+9mnDNnO0HdQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "^20.1.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@wdio/types/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@wdio/utils": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.28.0.tgz",
+ "integrity": "sha512-VDqUaXpR8oOZSs26dy06Y2LhmA8bldsXDHeZ36n8SfW+Bq0miG0RRxou7aqx7sifVbbsuxrbBPXvmK+40uAIbQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@puppeteer/browsers": "^2.2.0",
+ "@wdio/logger": "9.18.0",
+ "@wdio/types": "9.28.0",
+ "decamelize": "^6.0.0",
+ "deepmerge-ts": "^7.0.3",
+ "edgedriver": "^6.1.2",
+ "geckodriver": "^6.1.0",
+ "get-port": "^7.0.0",
+ "import-meta-resolve": "^4.0.0",
+ "locate-app": "^2.2.24",
+ "mitt": "^3.0.1",
+ "safaridriver": "^1.0.0",
+ "split2": "^4.2.0",
+ "wait-port": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ }
+ },
+ "node_modules/@zip.js/zip.js": {
+ "version": "2.8.26",
+ "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.26.tgz",
+ "integrity": "sha512-RQ4h9F6DOiHxpdocUDrOl6xBM+yOtz+LkUol47AVWcfebGBDpZ7w7Xvz9PS24JgXvLGiXXzSAfdCdVy1tPlaFA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "bun": ">=0.7.0",
+ "deno": ">=1.0.0",
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anynum": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.0.tgz",
+ "integrity": "sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/archiver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz",
+ "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "archiver-utils": "^5.0.2",
+ "async": "^3.2.4",
+ "buffer-crc32": "^1.0.0",
+ "readable-stream": "^4.0.0",
+ "readdir-glob": "^1.1.2",
+ "tar-stream": "^3.0.0",
+ "zip-stream": "^6.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/archiver-utils": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz",
+ "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==",
+ "license": "MIT",
+ "dependencies": {
+ "glob": "^10.0.0",
+ "graceful-fs": "^4.2.0",
+ "is-stream": "^2.0.1",
+ "lazystream": "^1.0.0",
+ "lodash": "^4.17.15",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/archiver-utils/node_modules/brace-expansion": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/archiver-utils/node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "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",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/archiver-utils/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "license": "MIT"
+ },
+ "node_modules/async-exit-hook": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
+ "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz",
+ "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.5",
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "node_modules/b4a": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz",
+ "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react-native-b4a": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-native-b4a": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/bare-events": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.1.tgz",
+ "integrity": "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "bare-abort-controller": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-abort-controller": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-fs": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.2.tgz",
+ "integrity": "sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-events": "^2.5.4",
+ "bare-path": "^3.0.0",
+ "bare-stream": "^2.6.4",
+ "bare-url": "^2.2.2",
+ "fast-fifo": "^1.3.2"
+ },
+ "engines": {
+ "bare": ">=1.16.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-os": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz",
+ "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "bare": ">=1.14.0"
+ }
+ },
+ "node_modules/bare-path": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz",
+ "integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-os": "^3.0.1"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.13.3",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.3.tgz",
+ "integrity": "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "b4a": "^1.8.1",
+ "streamx": "^2.25.0",
+ "teex": "^1.0.1"
+ },
+ "peerDependencies": {
+ "bare-abort-controller": "*",
+ "bare-buffer": "*",
+ "bare-events": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-abort-controller": {
+ "optional": true
+ },
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-events": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-url": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz",
+ "integrity": "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-path": "^3.0.0"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/basic-ftp": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/better-path-resolve": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
+ "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-windows": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/brace-expansion": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserstack-local": {
+ "version": "1.5.13",
+ "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.5.13.tgz",
+ "integrity": "sha512-7helY+Ms3ss4BtIQZTIyshdAFZSvS9A7ZpEB9stRaobeZ9BM1BkJFTuMakQNTOj78llv0+/qDI5Ak+bkGWV1xg==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "https-proxy-agent": "^5.0.1",
+ "is-running": "^2.1.0",
+ "tree-kill": "^1.2.2"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
+ "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/case-anything": {
+ "version": "2.1.13",
+ "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz",
+ "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/chai": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz",
+ "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==",
+ "license": "MIT"
+ },
+ "node_modules/check-error": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
+ "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "encoding-sniffer": "^0.2.1",
+ "htmlparser2": "^10.1.0",
+ "parse5": "^7.3.0",
+ "parse5-htmlparser2-tree-adapter": "^7.1.0",
+ "parse5-parser-stream": "^7.1.2",
+ "undici": "^7.19.0",
+ "whatwg-mimetype": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=20.18.1"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cheerio/node_modules/undici": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz",
+ "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/compress-commons": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz",
+ "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==",
+ "license": "MIT",
+ "dependencies": {
+ "crc-32": "^1.2.0",
+ "crc32-stream": "^6.0.0",
+ "is-stream": "^2.0.1",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "license": "MIT"
+ },
+ "node_modules/crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+ "license": "Apache-2.0",
+ "bin": {
+ "crc32": "bin/crc32.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/crc32-stream": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz",
+ "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==",
+ "license": "MIT",
+ "dependencies": {
+ "crc-32": "^1.2.0",
+ "readable-stream": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/create-wdio": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.28.0.tgz",
+ "integrity": "sha512-3Oa7tGK5QA9z1bdTFonnEb3OTTyNJtI2np7YzEC6F9es+94PFsFLLn5nIWs+fhJSdoueQyLy8P2cSWBO3Ohijw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "commander": "^14.0.0",
+ "cross-spawn": "^7.0.3",
+ "ejs": "^3.1.10",
+ "execa": "^9.6.0",
+ "import-meta-resolve": "^4.1.0",
+ "inquirer": "^12.7.0",
+ "normalize-package-data": "^7.0.0",
+ "read-pkg-up": "^10.1.0",
+ "recursive-readdir": "^2.2.3",
+ "semver": "^7.6.3",
+ "type-fest": "^4.41.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "create-wdio": "bin/wdio.js"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/create-wdio/node_modules/commander": {
+ "version": "14.0.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
+ "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/create-wdio/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "peer": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-shorthand-properties": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.2.tgz",
+ "integrity": "sha512-C2AugXIpRGQTxaCW0N7n5jD/p5irUmCrwl03TrnMFBHDbdq44CFWR2zO7rK9xPN4Eo3pUxC4vQzQgbIpzrD1PQ==",
+ "license": "MIT"
+ },
+ "node_modules/css-value": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz",
+ "integrity": "sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q=="
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/csv-writer": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz",
+ "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==",
+ "license": "MIT"
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.1.tgz",
+ "integrity": "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/deepmerge-ts": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz",
+ "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-indent": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+ "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/diff": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
+ "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dprint-node": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz",
+ "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^1.0.3"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/edge-paths": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-3.0.5.tgz",
+ "integrity": "sha512-sB7vSrDnFa4ezWQk9nZ/n0FdpdUuC6R1EOrlU3DL+bovcNFK28rqu2emmAUjujYEJTWIgQGqgVVWUZXMnc8iWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/which": "^2.0.1",
+ "which": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/shirshak55"
+ }
+ },
+ "node_modules/edgedriver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-6.3.0.tgz",
+ "integrity": "sha512-ggEQL+oEyIcM4nP2QC3AtCQ04o4kDNefRM3hja0odvlPSnsaxiruMxEZ93v3gDCKWYW6BXUr51PPradb+3nffw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "@wdio/logger": "^9.18.0",
+ "@zip.js/zip.js": "^2.8.11",
+ "decamelize": "^6.0.1",
+ "edge-paths": "^3.0.5",
+ "fast-xml-parser": "^5.3.3",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.6",
+ "which": "^6.0.0"
+ },
+ "bin": {
+ "edgedriver": "bin/edgedriver.js"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/edgedriver/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/edgedriver/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/edgedriver/node_modules/isexe": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz",
+ "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/edgedriver/node_modules/which": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz",
+ "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^4.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
+ "node_modules/ejs": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encoding-sniffer": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
+ "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "whatwg-encoding": "^3.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+ }
+ },
+ "node_modules/encoding-sniffer/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/enquirer/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/enquirer/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
+ "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.7",
+ "@esbuild/android-arm": "0.27.7",
+ "@esbuild/android-arm64": "0.27.7",
+ "@esbuild/android-x64": "0.27.7",
+ "@esbuild/darwin-arm64": "0.27.7",
+ "@esbuild/darwin-x64": "0.27.7",
+ "@esbuild/freebsd-arm64": "0.27.7",
+ "@esbuild/freebsd-x64": "0.27.7",
+ "@esbuild/linux-arm": "0.27.7",
+ "@esbuild/linux-arm64": "0.27.7",
+ "@esbuild/linux-ia32": "0.27.7",
+ "@esbuild/linux-loong64": "0.27.7",
+ "@esbuild/linux-mips64el": "0.27.7",
+ "@esbuild/linux-ppc64": "0.27.7",
+ "@esbuild/linux-riscv64": "0.27.7",
+ "@esbuild/linux-s390x": "0.27.7",
+ "@esbuild/linux-x64": "0.27.7",
+ "@esbuild/netbsd-arm64": "0.27.7",
+ "@esbuild/netbsd-x64": "0.27.7",
+ "@esbuild/openbsd-arm64": "0.27.7",
+ "@esbuild/openbsd-x64": "0.27.7",
+ "@esbuild/openharmony-arm64": "0.27.7",
+ "@esbuild/sunos-x64": "0.27.7",
+ "@esbuild/win32-arm64": "0.27.7",
+ "@esbuild/win32-ia32": "0.27.7",
+ "@esbuild/win32-x64": "0.27.7"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/events-universal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
+ "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-events": "^2.7.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
+ "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@sindresorhus/merge-streams": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "figures": "^6.1.0",
+ "get-stream": "^9.0.0",
+ "human-signals": "^8.0.1",
+ "is-plain-obj": "^4.1.0",
+ "is-stream": "^4.0.1",
+ "npm-run-path": "^6.0.0",
+ "pretty-ms": "^9.2.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^4.0.0",
+ "yoctocolors": "^2.1.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/get-stream": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
+ "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@sec-ant/readable-stream": "^0.4.1",
+ "is-stream": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/execa/node_modules/is-stream": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
+ "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/extendable-error": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz",
+ "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/extract-zip/node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/extract-zip/node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==",
+ "license": "MIT"
+ },
+ "node_modules/fast-fifo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
+ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-xml-builder": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
+ "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "path-expression-matcher": "^1.5.0",
+ "xml-naming": "^0.1.0"
+ }
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.9.0.tgz",
+ "integrity": "sha512-duBuXbyIhEeNO4GjFuVqr0nF047oNwr18aum+zJyqo0MUG/n7Afgs3Qv3D6VN3ONedUKxiuFlPiMGIa0Z11chA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@nodable/entities": "^2.2.0",
+ "fast-xml-builder": "^1.2.0",
+ "is-unsafe": "^1.0.1",
+ "path-expression-matcher": "^1.5.0",
+ "strnum": "^2.4.0",
+ "xml-naming": "^0.1.0"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "license": "MIT",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fecha": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
+ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
+ "license": "MIT"
+ },
+ "node_modules/figures": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
+ "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-unicode-supported": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/filelist": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
+ "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/geckodriver": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-6.1.0.tgz",
+ "integrity": "sha512-ZRXLa4ZaYTTgUO4Eefw+RsQCleugU2QLb1ME7qTYxxuRj51yAhfnXaItXNs5/vUzfIaDHuZ+YnSF005hfp07nQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "@wdio/logger": "^9.18.0",
+ "@zip.js/zip.js": "^2.8.11",
+ "decamelize": "^6.0.1",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.6",
+ "modern-tar": "^0.7.2"
+ },
+ "bin": {
+ "geckodriver": "bin/geckodriver.js"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/geckodriver/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/geckodriver/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-port": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.2.0.tgz",
+ "integrity": "sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-uri": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
+ "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/git-repo-info": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/git-repo-info/-/git-repo-info-2.1.1.tgz",
+ "integrity": "sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
+ "node_modules/gitconfiglocal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz",
+ "integrity": "sha512-qoerOEliJn3z+Zyn1HW2F6eoYJqKwS6MgC9cztTLUB/xLWX8gD/6T60pKn4+t/d6tP7JlybI7Z3z+I572CR/Vg==",
+ "license": "BSD",
+ "dependencies": {
+ "ini": "^1.3.2"
+ }
+ },
+ "node_modules/glob": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "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",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.1.1",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "license": "MIT"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/headers-utils": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/headers-utils/-/headers-utils-1.2.5.tgz",
+ "integrity": "sha512-DAzV5P/pk3wTU/8TLZN+zFTDv4Xa1QDTU8pRvovPetcOMbmqq8CwsAvZBLPZHH6usxyy31zMp7I4aCYb6XIf6w==",
+ "license": "MIT"
+ },
+ "node_modules/hosted-git-info": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz",
+ "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "lru-cache": "^10.0.1"
+ },
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC",
+ "peer": true
+ },
+ "node_modules/htmlfy": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz",
+ "integrity": "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ==",
+ "license": "MIT"
+ },
+ "node_modules/htmlparser2": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
+ "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "entities": "^7.0.1"
+ }
+ },
+ "node_modules/htmlparser2/node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-id": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz",
+ "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "human-id": "dist/cli.js"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
+ "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
+ "license": "MIT"
+ },
+ "node_modules/import-meta-resolve": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
+ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
+ "node_modules/inquirer": {
+ "version": "12.11.1",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz",
+ "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/prompts": "^7.10.1",
+ "@inquirer/type": "^3.0.10",
+ "mute-stream": "^2.0.0",
+ "run-async": "^4.0.6",
+ "rxjs": "^7.8.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ip-address": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+ "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-running": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz",
+ "integrity": "sha512-mjJd3PujZMl7j+D395WTIO5tU5RIDBfVSRtRR4VOJou3H66E38UjbjvDGh3slJzPuolsb+yQFqwHNNdyp5jg3w==",
+ "license": "BSD"
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-subdir": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz",
+ "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "better-path-resolve": "1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
+ "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-unsafe": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-1.0.1.tgz",
+ "integrity": "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/jackspeak": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
+ "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^9.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/jake": {
+ "version": "10.9.4",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz",
+ "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "async": "^3.2.6",
+ "filelist": "^1.0.4",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
+ "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz",
+ "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "license": "MIT",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jszip": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "dependencies": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/jszip/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/jszip/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/jszip/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/lazystream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.6.3"
+ }
+ },
+ "node_modules/lazystream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/lazystream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/lazystream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz",
+ "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/locate-app": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.5.0.tgz",
+ "integrity": "sha512-xIqbzPMBYArJRmPGUZD9CzV9wOqmVtQnaAn3wrj3s6WYW0bQvPI7x+sPYUGmDTYMHefVK//zc6HEYZ1qnxIK+Q==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://buymeacoffee.com/hejny"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/hejny/locate-app/blob/main/README.md#%EF%B8%8F-contributing"
+ }
+ ],
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@promptbook/utils": "0.69.5",
+ "type-fest": "4.26.0",
+ "userhome": "1.0.1"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
- "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.pickby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
+ "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.startcase": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.union": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
+ "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.zip": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz",
+ "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==",
+ "license": "MIT"
+ },
+ "node_modules/logform": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
+ "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@colors/colors": "1.6.0",
+ "@types/triple-beam": "^1.3.2",
+ "fecha": "^4.2.0",
+ "ms": "^2.1.1",
+ "safe-stable-stringify": "^2.3.1",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/loglevel": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz",
+ "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ },
+ "funding": {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/loglevel"
+ }
+ },
+ "node_modules/loglevel-plugin-prefix": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz",
+ "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==",
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/loupe": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "11.5.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz",
+ "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
+ "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "license": "MIT"
+ },
+ "node_modules/modern-tar": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.6.tgz",
+ "integrity": "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/mute-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
+ "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/netmask": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz",
+ "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/node-request-interceptor": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/node-request-interceptor/-/node-request-interceptor-0.6.3.tgz",
+ "integrity": "sha512-8I2V7H2Ch0NvW7qWcjmS0/9Lhr0T6x7RD6PDirhvWEkUQvy83x8BA4haYMr09r/rig7hcgYSjYh6cd4U7G1vLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@open-draft/until": "^1.0.3",
+ "debug": "^4.3.0",
+ "headers-utils": "^1.2.0",
+ "strict-event-emitter": "^0.1.0"
+ }
+ },
+ "node_modules/normalize-package-data": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-7.0.1.tgz",
+ "integrity": "sha512-linxNAT6M0ebEYZOx2tO6vBEFsVgnPpv+AVjk0wJHfaUIbq31Jm3T6vvZaarnOeWDh8ShnwXuaAyM7WT3RzErA==",
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "dependencies": {
+ "hosted-git-info": "^8.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
+ "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "path-key": "^4.0.0",
+ "unicorn-magic": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/outdent": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz",
+ "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/p-filter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz",
+ "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pac-proxy-agent": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
+ "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "get-uri": "^6.0.1",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.6",
+ "pac-resolver": "^7.0.1",
+ "socks-proxy-agent": "^8.0.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-resolver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "license": "MIT",
+ "dependencies": {
+ "degenerator": "^5.0.0",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/package-manager-detector": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
+ "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "quansync": "^0.2.7"
+ }
+ },
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "license": "(MIT AND Zlib)"
+ },
+ "node_modules/parse-json": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz",
+ "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.21.4",
+ "error-ex": "^1.3.2",
+ "json-parse-even-better-errors": "^3.0.0",
+ "lines-and-columns": "^2.0.3",
+ "type-fest": "^3.8.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-json/node_modules/type-fest": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
+ "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
+ "license": "(MIT OR CC0-1.0)",
+ "peer": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-ms": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
+ "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-parser-stream": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+ "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+ "license": "MIT",
+ "dependencies": {
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-expression-matcher": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
+ "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
+ "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pathval": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/pretty-ms": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
+ "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "parse-ms": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "license": "MIT"
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/protobufjs": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz",
+ "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/proxy-agent": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
+ "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.6",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.1.0",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/pump": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
+ "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/quansync": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
+ "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/query-selector-shadow-dom": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz",
+ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==",
+ "license": "MIT"
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/read-pkg": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz",
+ "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.1",
+ "normalize-package-data": "^6.0.0",
+ "parse-json": "^7.0.0",
+ "type-fest": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz",
+ "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "find-up": "^6.3.0",
+ "read-pkg": "^8.1.0",
+ "type-fest": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "yocto-queue": "^1.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/read-pkg/node_modules/hosted-git-info": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
+ "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "lru-cache": "^10.0.1"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-pkg/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC",
+ "peer": true
+ },
+ "node_modules/read-pkg/node_modules/normalize-package-data": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz",
+ "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==",
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "dependencies": {
+ "hosted-git-info": "^7.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-yaml-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz",
+ "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.5",
+ "js-yaml": "^3.6.1",
+ "pify": "^4.0.1",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/read-yaml-file/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/read-yaml-file/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
+ "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/readdir-glob": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
+ "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "minimatch": "^5.1.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/readdir-glob/node_modules/brace-expansion": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/recursive-readdir": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
+ "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/recursive-readdir/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/recursive-readdir/node_modules/brace-expansion": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
+ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/recursive-readdir/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resq": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/resq/-/resq-1.11.0.tgz",
+ "integrity": "sha512-G10EBz+zAAy3zUd/CDoBbXRL6ia9kOo3xRHrMDsHljI0GDkhYlyjwoCx5+3eCC4swi1uCoZQhskuJkj7Gp57Bw==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^2.0.1"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz",
+ "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rgb2hex": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz",
+ "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==",
+ "license": "MIT"
+ },
+ "node_modules/rimraf": {
+ "version": "6.1.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz",
+ "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "glob": "^13.0.3",
+ "package-json-from-dist": "^1.0.1"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "13.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
+ "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "minimatch": "^10.2.2",
+ "minipass": "^7.1.3",
+ "path-scurry": "^2.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz",
+ "integrity": "sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.62.0",
+ "@rollup/rollup-android-arm64": "4.62.0",
+ "@rollup/rollup-darwin-arm64": "4.62.0",
+ "@rollup/rollup-darwin-x64": "4.62.0",
+ "@rollup/rollup-freebsd-arm64": "4.62.0",
+ "@rollup/rollup-freebsd-x64": "4.62.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.0",
+ "@rollup/rollup-linux-arm64-musl": "4.62.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.0",
+ "@rollup/rollup-linux-loong64-musl": "4.62.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.0",
+ "@rollup/rollup-linux-x64-gnu": "4.62.0",
+ "@rollup/rollup-linux-x64-musl": "4.62.0",
+ "@rollup/rollup-openbsd-x64": "4.62.0",
+ "@rollup/rollup-openharmony-arm64": "4.62.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.0",
+ "@rollup/rollup-win32-x64-gnu": "4.62.0",
+ "@rollup/rollup-win32-x64-msvc": "4.62.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz",
+ "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safaridriver": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/safaridriver/-/safaridriver-1.0.1.tgz",
+ "integrity": "sha512-jkg4434cYgtrIF2AeY/X0Wmd2W73cK5qIEFE3hDrrQenJH/2SDJIXGvPAigfvQTcE9+H31zkiNHbUqcihEiMRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safe-regex2": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.1.1.tgz",
+ "integrity": "sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "ret": "~0.5.0"
+ },
+ "bin": {
+ "safe-regex2": "bin/safe-regex2.js"
+ }
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
+ "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/serialize-error": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-12.0.0.tgz",
+ "integrity": "sha512-ZYkZLAvKTKQXWuh5XpBw7CdbSzagarX39WyZ2H07CDLC5/KfsRGlIXV8d4+tfqX1M7916mRqR1QfNHSij+c9Pw==",
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^4.31.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/serialize-error/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "license": "MIT"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
+ "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^10.1.1",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
+ "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spacetrim": {
+ "version": "0.11.59",
+ "resolved": "https://registry.npmjs.org/spacetrim/-/spacetrim-0.11.59.tgz",
+ "integrity": "sha512-lLYsktklSRKprreOm7NXReW8YiX2VBjbgmXYEziOoGf/qsJqAEACaDvoTtUOycwjpaSh+bT8eu0KrJn7UNxiCg==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://buymeacoffee.com/hejny"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/hejny/spacetrim/blob/main/README.md#%EF%B8%8F-contributing"
+ }
+ ],
+ "license": "Apache-2.0"
+ },
+ "node_modules/spawndamnit": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-3.0.1.tgz",
+ "integrity": "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==",
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE",
+ "dependencies": {
+ "cross-spawn": "^7.0.5",
+ "signal-exit": "^4.0.1"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "license": "CC-BY-3.0",
+ "peer": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz",
+ "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==",
+ "license": "CC0-1.0",
+ "peer": true
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/std-env": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/streamx": {
+ "version": "2.28.0",
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.0.tgz",
+ "integrity": "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==",
+ "license": "MIT",
+ "dependencies": {
+ "events-universal": "^1.0.0",
+ "fast-fifo": "^1.3.2",
+ "text-decoder": "^1.1.0"
+ }
+ },
+ "node_modules/strict-event-emitter": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.1.0.tgz",
+ "integrity": "sha512-8hSYfU+WKLdNcHVXJ0VxRXiPESalzRe7w1l8dg9+/22Ry+iZQUoQuoJ27R30GMD1TiyYINWsIEGY05WrskhSKw==",
+ "license": "MIT"
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
+ "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-literal": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
+ "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.0.tgz",
+ "integrity": "sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "anynum": "^1.0.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar": {
+ "version": "7.5.16",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
+ "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.1.0",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz",
+ "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==",
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^4.0.1",
+ "bare-path": "^3.0.0"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz",
+ "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==",
+ "license": "MIT",
+ "dependencies": {
+ "b4a": "^1.6.4",
+ "bare-fs": "^4.5.5",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
+ }
+ },
+ "node_modules/teex": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
+ "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
+ "license": "MIT",
+ "dependencies": {
+ "streamx": "^2.12.5"
+ }
+ },
+ "node_modules/term-size": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
+ "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/text-decoder": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
+ "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "b4a": "^1.6.4"
+ }
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/tinypool": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
+ "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz",
+ "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tree-kill": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+ "license": "MIT",
+ "bin": {
+ "tree-kill": "cli.js"
+ }
+ },
+ "node_modules/triple-beam": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
+ "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/ts-poet": {
+ "version": "6.12.0",
+ "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz",
+ "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dprint-node": "^1.0.8"
+ }
+ },
+ "node_modules/ts-proto": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.11.8.tgz",
+ "integrity": "sha512-+5hzECnyVB33jxjG1BIdzAHcRBm7hjnm8womdJVp2A7xJWihP0drHHVsXYTr9i/LpWNGfh80I+AVVNzFM5AwJw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.10.2",
+ "case-anything": "^2.1.13",
+ "ts-poet": "^6.12.0",
+ "ts-proto-descriptors": "2.1.0"
+ },
+ "bin": {
+ "protoc-gen-ts_proto": "protoc-gen-ts_proto"
+ }
+ },
+ "node_modules/ts-proto-descriptors": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.1.0.tgz",
+ "integrity": "sha512-S5EZYEQ6L9KLFfjSRpZWDIXDV/W7tAj8uW7pLsihIxyr62EAVSiKuVPwE8iWnr849Bqa53enex1jhDUcpgquzA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tsx": {
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz",
+ "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "~0.28.0"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
+ "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
+ "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
+ "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
+ "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
+ "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
+ "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
+ "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
+ "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
+ "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
+ "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
+ "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
+ "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
+ "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
+ "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
+ "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
+ "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
+ "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
+ "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
+ "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
+ "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/esbuild": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
+ "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.1",
+ "@esbuild/android-arm": "0.28.1",
+ "@esbuild/android-arm64": "0.28.1",
+ "@esbuild/android-x64": "0.28.1",
+ "@esbuild/darwin-arm64": "0.28.1",
+ "@esbuild/darwin-x64": "0.28.1",
+ "@esbuild/freebsd-arm64": "0.28.1",
+ "@esbuild/freebsd-x64": "0.28.1",
+ "@esbuild/linux-arm": "0.28.1",
+ "@esbuild/linux-arm64": "0.28.1",
+ "@esbuild/linux-ia32": "0.28.1",
+ "@esbuild/linux-loong64": "0.28.1",
+ "@esbuild/linux-mips64el": "0.28.1",
+ "@esbuild/linux-ppc64": "0.28.1",
+ "@esbuild/linux-riscv64": "0.28.1",
+ "@esbuild/linux-s390x": "0.28.1",
+ "@esbuild/linux-x64": "0.28.1",
+ "@esbuild/netbsd-arm64": "0.28.1",
+ "@esbuild/netbsd-x64": "0.28.1",
+ "@esbuild/openbsd-arm64": "0.28.1",
+ "@esbuild/openbsd-x64": "0.28.1",
+ "@esbuild/openharmony-arm64": "0.28.1",
+ "@esbuild/sunos-x64": "0.28.1",
+ "@esbuild/win32-arm64": "0.28.1",
+ "@esbuild/win32-ia32": "0.28.1",
+ "@esbuild/win32-x64": "0.28.1"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "4.26.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz",
+ "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz",
+ "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "license": "MIT"
+ },
+ "node_modules/unicorn-magic": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
+ "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz",
+ "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==",
+ "license": "MIT"
+ },
+ "node_modules/userhome": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/userhome/-/userhome-1.0.1.tgz",
+ "integrity": "sha512-5cnLm4gseXjAclKowC4IjByaGsjtAoV6PrOQOljplNB54ReUYJP8HdAFq2muHinSDAh09PPX/uXDPfdxRHvuSA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/uuid": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
+ "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/esm/bin/uuid"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz",
+ "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-node": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
+ "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.4.1",
+ "es-module-lexer": "^1.7.0",
+ "pathe": "^2.0.3",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/vite/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/vitest": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz",
+ "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/expect": "3.2.6",
+ "@vitest/mocker": "3.2.6",
+ "@vitest/pretty-format": "^3.2.6",
+ "@vitest/runner": "3.2.6",
+ "@vitest/snapshot": "3.2.6",
+ "@vitest/spy": "3.2.6",
+ "@vitest/utils": "3.2.6",
+ "chai": "^5.2.0",
+ "debug": "^4.4.1",
+ "expect-type": "^1.2.1",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.2",
+ "std-env": "^3.9.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.2",
+ "tinyglobby": "^0.2.14",
+ "tinypool": "^1.1.1",
+ "tinyrainbow": "^2.0.0",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
+ "vite-node": "3.2.4",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "3.2.6",
+ "@vitest/ui": "3.2.6",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/debug": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
},
- "node_modules/long": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
- "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="
+ "node_modules/vitest/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
- "node_modules/protobufjs": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
- "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==",
- "hasInstallScript": true,
+ "node_modules/wait-port": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz",
+ "integrity": "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==",
+ "license": "MIT",
"dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.0",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.0",
- "@types/node": ">=13.7.0",
- "long": "^5.0.0"
+ "chalk": "^4.1.2",
+ "commander": "^9.3.0",
+ "debug": "^4.3.4"
+ },
+ "bin": {
+ "wait-port": "bin/wait-port.js"
},
"engines": {
- "node": ">=12.0.0"
+ "node": ">=10"
}
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "node_modules/wait-port/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "node_modules/webdriver": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.28.0.tgz",
+ "integrity": "sha512-MmtC/n5rhOh/EYyYI1SbRBdEWctKaQouVeEAybv5SD/2bhTjg800q7mvGqHzhTXpqTPY5cdbOtT0PBdT89wz9w==",
+ "license": "MIT",
"dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
+ "@types/node": "^20.1.0",
+ "@types/ws": "^8.5.3",
+ "@wdio/config": "9.28.0",
+ "@wdio/logger": "9.18.0",
+ "@wdio/protocols": "9.28.0",
+ "@wdio/types": "9.28.0",
+ "@wdio/utils": "9.28.0",
+ "deepmerge-ts": "^7.0.3",
+ "https-proxy-agent": "^7.0.6",
+ "undici": "^6.21.3",
+ "ws": "^8.8.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=18.20.0"
}
},
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "node_modules/webdriver/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "license": "MIT",
"dependencies": {
- "ansi-regex": "^5.0.1"
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/webdriver/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/webdriver/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
},
"engines": {
- "node": ">=8"
+ "node": ">= 14"
}
},
- "node_modules/ts-poet": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz",
- "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
- "dev": true,
+ "node_modules/webdriverio": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.28.0.tgz",
+ "integrity": "sha512-ieFWi8dq57uZC6QMC2x6TllxKTRyInIMcOrVvwbHqVRYvJP8OLDtlH1bideGRIN0pgGHWStqplez2A95jS9bqA==",
+ "license": "MIT",
"dependencies": {
- "dprint-node": "^1.0.8"
+ "@types/node": "^20.11.30",
+ "@types/sinonjs__fake-timers": "^8.1.5",
+ "@wdio/config": "9.28.0",
+ "@wdio/logger": "9.18.0",
+ "@wdio/protocols": "9.28.0",
+ "@wdio/repl": "9.16.2",
+ "@wdio/types": "9.28.0",
+ "@wdio/utils": "9.28.0",
+ "archiver": "^7.0.1",
+ "aria-query": "^5.3.0",
+ "cheerio": "^1.0.0-rc.12",
+ "css-shorthand-properties": "^1.1.1",
+ "css-value": "^0.0.1",
+ "grapheme-splitter": "^1.0.4",
+ "htmlfy": "^0.8.1",
+ "is-plain-obj": "^4.1.0",
+ "jszip": "^3.10.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.zip": "^4.2.0",
+ "query-selector-shadow-dom": "^1.0.1",
+ "resq": "^1.11.0",
+ "rgb2hex": "0.2.5",
+ "serialize-error": "^12.0.0",
+ "urlpattern-polyfill": "^10.0.0",
+ "webdriver": "9.28.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ },
+ "peerDependencies": {
+ "puppeteer-core": ">=22.x || <=24.x"
+ },
+ "peerDependenciesMeta": {
+ "puppeteer-core": {
+ "optional": true
+ }
}
},
- "node_modules/ts-proto": {
- "version": "2.7.7",
- "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.7.7.tgz",
- "integrity": "sha512-/OfN9/Yriji2bbpOysZ/Jzc96isOKz+eBTJEcKaIZ0PR6x1TNgVm4Lz0zfbo+J0jwFO7fJjJyssefBPQ0o1V9A==",
- "dev": true,
+ "node_modules/webdriverio/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "license": "MIT",
"dependencies": {
- "@bufbuild/protobuf": "^2.0.0",
- "case-anything": "^2.1.13",
- "ts-poet": "^6.12.0",
- "ts-proto-descriptors": "2.0.0"
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
},
- "bin": {
- "protoc-gen-ts_proto": "protoc-gen-ts_proto"
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/ts-proto-descriptors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.0.0.tgz",
- "integrity": "sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==",
- "dev": true,
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
"dependencies": {
- "@bufbuild/protobuf": "^2.0.0"
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/typescript": {
- "version": "5.9.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
- "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
"bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
+ "why-is-node-running": "cli.js"
},
"engines": {
- "node": ">=14.17"
+ "node": ">=8"
}
},
- "node_modules/undici-types": {
- "version": "7.10.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
- "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="
+ "node_modules/winston-transport": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
+ "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
+ "license": "MIT",
+ "dependencies": {
+ "logform": "^2.7.0",
+ "readable-stream": "^3.6.2",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston-transport/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -504,18 +9274,113 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/ws": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-naming": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
+ "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
"engines": {
"node": ">=10"
}
},
+ "node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -533,9 +9398,150 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz",
+ "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==",
+ "license": "MIT",
+ "dependencies": {
+ "pend": "~1.2.0"
+ },
"engines": {
"node": ">=12"
}
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
+ "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
+ "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors-cjs": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
+ "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zip-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz",
+ "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==",
+ "license": "MIT",
+ "dependencies": {
+ "archiver-utils": "^5.0.0",
+ "compress-commons": "^6.0.2",
+ "readable-stream": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "packages/browserstack-service": {
+ "name": "@wdio/browserstack-service",
+ "version": "9.28.0",
+ "license": "MIT",
+ "dependencies": {
+ "@browserstack/ai-sdk-node": "1.5.17",
+ "@browserstack/wdio-browserstack-service": "^2.0.2",
+ "@percy/appium-app": "^2.0.9",
+ "@percy/selenium-webdriver": "^2.2.2",
+ "@types/gitconfiglocal": "^2.0.1",
+ "browserstack-local": "^1.5.1",
+ "chalk": "^5.3.0",
+ "csv-writer": "^1.6.0",
+ "git-repo-info": "^2.1.1",
+ "gitconfiglocal": "^2.1.0",
+ "glob": "^11.0.0",
+ "tar": "^7.5.11",
+ "undici": "^6.24.0",
+ "uuid": "^11.1.0",
+ "winston-transport": "^4.5.0",
+ "yauzl": "^3.0.0"
+ },
+ "devDependencies": {
+ "@changesets/cli": "^2.27.9",
+ "@types/node": "^20.1.0",
+ "@types/tar": "^7.0.87",
+ "@types/yauzl": "^2.10.3",
+ "@wdio/globals": "^9.0.0",
+ "@wdio/logger": "^9.0.0",
+ "@wdio/reporter": "^9.0.0",
+ "@wdio/types": "^9.0.0",
+ "esbuild": "^0.27.2",
+ "rimraf": "^6.0.1",
+ "typescript": "^5.8.3",
+ "vitest": "^3.2.4",
+ "webdriverio": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18.20.0"
+ },
+ "peerDependencies": {
+ "@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "@wdio/logger": "^9.0.0",
+ "@wdio/reporter": "^9.0.0",
+ "@wdio/types": "^9.0.0",
+ "webdriverio": "^9.0.0"
+ }
+ },
+ "packages/browserstack-service/node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "packages/core": {
+ "name": "@browserstack/wdio-browserstack-service",
+ "version": "2.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.5.2",
+ "@grpc/grpc-js": "1.13.3"
+ },
+ "devDependencies": {
+ "@bufbuild/buf": "^1.55.1",
+ "ts-proto": "^2.7.5",
+ "typescript": "^5.4.5"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
}
}
}
diff --git a/package.json b/package.json
index b36f3d4..5a9dc85 100644
--- a/package.json
+++ b/package.json
@@ -1,47 +1,26 @@
{
- "name": "@browserstack/wdio-browserstack-service",
- "version": "2.0.2",
- "description": "WebdriverIO service for better Browserstack integration",
- "author": "Browserstack",
- "homepage": "https://github.com/browserstack/wdio-browserstack-service",
+ "name": "wdio-browserstack-service-monorepo",
+ "version": "0.0.0",
+ "private": true,
+ "description": "Monorepo: @wdio/browserstack-service (WebdriverIO service) + @browserstack/wdio-browserstack-service (gRPC/protobuf core).",
+ "license": "MIT",
"type": "module",
- "main": "dist/index.js",
"engines": {
- "node": ">=16.0.0"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/browserstack/wdio-browserstack-service.git"
+ "node": ">=18.20.0"
},
- "types": "dist/index.d.ts",
- "files": [
- "dist/**/*",
- "src/proto/**/*.proto"
+ "workspaces": [
+ "packages/*"
],
"scripts": {
- "clean": "rm -rf dist src/generated",
- "generate": "buf generate",
- "build": "npm run clean && npm run generate && tsc",
- "prepare": "npm run build",
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "keywords": [
- "browserstack",
- "proto",
- "grpc",
- "webdriverio"
- ],
- "bugs": {
- "url": "https://github.com/browserstack/wdio-browserstack-service/issues"
- },
- "license": "MIT",
- "dependencies": {
- "@bufbuild/protobuf": "^2.5.2",
- "@grpc/grpc-js": "1.13.3"
+ "build": "npm run build:core && npm run build:service",
+ "build:core": "npm run build -w @browserstack/wdio-browserstack-service",
+ "build:service": "npm run build -w @wdio/browserstack-service",
+ "test": "npm run test -w @wdio/browserstack-service",
+ "changeset": "changeset",
+ "version": "changeset version",
+ "release": "changeset publish"
},
"devDependencies": {
- "@bufbuild/buf": "^1.55.1",
- "ts-proto": "^2.7.5",
- "typescript": "^5.4.5"
+ "@changesets/cli": "^2.27.9"
}
}
diff --git a/packages/browserstack-service/.npmignore b/packages/browserstack-service/.npmignore
new file mode 100644
index 0000000..2ec2880
--- /dev/null
+++ b/packages/browserstack-service/.npmignore
@@ -0,0 +1,14 @@
+# Keep the published tarball lean: only build/, README, LICENSE and the
+# root ambient types (browserstack-service.d.ts) ship. Everything dev-only below
+# is excluded.
+src
+tests
+__mocks__
+scripts
+.changeset
+.github
+coverage
+vitest.config.ts
+tsconfig.json
+tsconfig.prod.json
+EXTRACTION.md
diff --git a/packages/browserstack-service/LICENSE b/packages/browserstack-service/LICENSE
new file mode 100644
index 0000000..2066580
--- /dev/null
+++ b/packages/browserstack-service/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) OpenJS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/browserstack-service/README.md b/packages/browserstack-service/README.md
new file mode 100644
index 0000000..cd0127d
--- /dev/null
+++ b/packages/browserstack-service/README.md
@@ -0,0 +1,359 @@
+WebdriverIO BrowserStack Service
+==========
+
+> A WebdriverIO service that manages local tunnel and job metadata for BrowserStack users.
+
+## Installation
+
+
+The easiest way is to keep `@wdio/browserstack-service` as a devDependency in your `package.json`, via:
+
+```sh
+npm install @wdio/browserstack-service --save-dev
+```
+
+Instructions on how to install `WebdriverIO` can be found [here.](https://webdriver.io/docs/gettingstarted)
+
+
+## Configuration
+
+WebdriverIO has BrowserStack support out of the box. You should set `user` and `key` in your `wdio.conf.js` file. This service plugin provides support for [BrowserStack Tunnel](https://www.browserstack.com/docs/automate/selenium/getting-started/nodejs/local-testing). Set `browserstackLocal: true` also to activate this feature.
+Reporting of session status on BrowserStack will respect `strict` setting of Cucumber options.
+
+```js
+// wdio.conf.js
+export const config = {
+ // ...
+ user: process.env.BROWSERSTACK_USERNAME,
+ key: process.env.BROWSERSTACK_ACCESS_KEY,
+ services: [
+ ['browserstack', {
+ testReporting: true,
+ testReportingOptions: {
+ projectName: "Your project name goes here",
+ buildName: "The static build job name goes here e.g. Nightly regression"
+ },
+ browserstackLocal: true
+ }]
+ ],
+ // ...
+};
+```
+
+## Options
+
+In order to authorize to the BrowserStack service your config needs to contain a [`user`](https://webdriver.io/docs/options#user) and [`key`](https://webdriver.io/docs/options#key) option.
+
+### testReporting
+
+Test Observability is an advanced test reporting tool that gives insights to improve your automation tests and helps you debug faster. It’s enabled by default by setting the `testObservability` flag as `true` for all users of browserstack-service. You can disable this by setting the `testObservability` flag to `false`.
+
+Once your tests finish running, you can visit [Test Reporting and Analytics](https://automation.browserstack.com/) to debug your builds with additional insights like Unique Error Analysis, Automatic Flaky Test Detection, and more.
+
+You can use Test Observability even if you don’t run your tests on the BrowserStack infrastructure. Even if you run your tests on a CI, a local machine, or even on other cloud service providers, Test Observability can still generate intelligent test reports and advanced analytics on your tests.
+
+If you want to use Test Reporting and Analytics without running your tests on BrowserStack infrastructure, you can set your config as follows:
+
+
+```js
+// wdio.conf.js
+export const config = {
+ // ...
+ services: [
+ ['browserstack', {
+ testReporting: true,
+ testReportingOptions: {
+ user: process.env.BROWSERSTACK_USERNAME,
+ key: process.env.BROWSERSTACK_ACCESS_KEY,
+ projectName: "Your project name goes here",
+ buildName: "The static build job name goes here e.g. Nightly regression"
+ }
+ }]
+ ],
+ // ...
+};
+```
+
+You can explore all the features of Test Reporting and Analytics in [this sandbox](https://automation.browserstack.com/) or read more about it [here](https://www.browserstack.com/docs/test-reporting-and-analytics/overview/what-is-test-observability).
+
+### browserstackLocal
+Set this to true to enable routing connections from BrowserStack cloud through your computer.
+
+Type: `Boolean`
+Default: `false`
+
+### forcedStop
+Set this to true to kill the BrowserStack Local process on complete, without waiting for the BrowserStack Local stop callback to be called. This is experimental and should not be used by all. Mostly necessary as a workaround for [this issue](https://github.com/browserstack/browserstack-local-nodejs/issues/41).
+
+Type: `Boolean`
+Default: `false`
+
+### app
+
+[Appium](https://appium.io/) set this with the app file path available locally on your machine to use the app as [application under test](https://www.browserstack.com/docs/app-automate/appium/set-up-tests/specify-app) for Appium sessions.
+
+Type: `String` or `JsonObject`
+Default: `undefined`
+
+List of available app values:
+
+#### path
+Use locally available app file path as an application under test for Appium.
+
+```js
+services: [
+ ['browserstack', {
+ app: '/path/to/local/app.apk'
+ // OR
+ app: {
+ path: '/path/to/local/app.apk'
+ }
+ }]
+]
+```
+
+Pass custom_id while the app upload.
+
+```js
+services: [
+ ['browserstack', {
+ app: {
+ path: '/path/to/local/app.apk',
+ custom_id: 'custom_id'
+ }
+ }]
+]
+```
+
+#### id
+Use the app URL returned after uploading the app to BrowserStack.
+
+```js
+services: [
+ ['browserstack', {
+ app: 'bs://'
+ // OR
+ app: {
+ id: 'bs://'
+ }
+ }]
+]
+```
+
+#### custom_id
+
+use custom_id of already uploaded apps
+
+```js
+services: [
+ ['browserstack', {
+ app: 'custom_id'
+ // OR
+ app: {
+ custom_id: 'custom_id'
+ }
+ }]
+]
+```
+
+#### shareable_id
+
+use shareable_id of already uploaded apps
+
+```js
+services: [
+ ['browserstack', {
+ app: 'username/custom_id'
+ // OR
+ app: {
+ shareable_id: 'username/custom_id'
+ }
+ }]
+]
+```
+
+### preferScenarioName
+
+Cucumber only. Set the BrowserStack Automate session name to the Scenario name if only a single Scenario ran.
+Useful when running in parallel with [wdio-cucumber-parallel-execution](https://github.com/SimitTomar/wdio-cucumber-parallel-execution).
+
+Type: `Boolean`
+Default: `false`
+
+### sessionNameFormat
+
+Customize the BrowserStack Automate session name format.
+
+Type: `Function`
+Default (Cucumber/Jasmine): `(config, capabilities, suiteTitle) => suiteTitle`
+Default (Mocha): `(config, capabilities, suiteTitle, testTitle) => suiteTitle + ' - ' + testTitle`
+
+### sessionNameOmitTestTitle
+
+Mocha only. Do not append the test title to the BrowserStack Automate session name.
+
+Type: `Boolean`
+Default: `false`
+
+### sessionNamePrependTopLevelSuiteTitle
+
+Mocha only. Prepend the top level suite title to the BrowserStack Automate session name.
+
+Type: `Boolean`
+Default: `false`
+
+### setSessionName
+
+Automatically set the BrowserStack Automate session name.
+
+Type: `Boolean`
+Default: `true`
+
+### setSessionStatus
+
+Automatically set the BrowserStack Automate session status (passed/failed).
+
+Type: `Boolean`
+Default: `true`
+
+### buildIdentifier
+
+**buildIdentifier** is a unique id to differentiate every execution that gets appended to buildName. Choose your buildIdentifier format from the available expressions:
+* `BUILD_NUMBER`: Generates an incremental counter with every execution
+* `DATE_TIME`: Generates a Timestamp with every execution. Eg. 05-Nov-19:30
+
+```js
+services: [
+ ['browserstack', {
+ buildIdentifier: '#${BUILD_NUMBER}'
+ }]
+]
+```
+Build Identifier supports usage of either or both expressions along with any other characters enabling custom formatting options.
+
+### opts
+
+BrowserStack Local options.
+
+Type: `Object`
+Default: `{}`
+
+List of available local testing modifiers to be passed as opts:
+
+#### Local Identifier
+
+If doing simultaneous multiple local testing connections, set this uniquely for different processes -
+
+```js
+opts = { localIdentifier: "randomstring" };
+```
+
+#### Verbose Logging
+
+To enable verbose logging -
+
+```js
+opts = { verbose: "true" };
+```
+
+Note - Possible values for 'verbose' modifier are '1', '2', '3' and 'true'
+
+#### Force Local
+
+To route all traffic via local(your) machine -
+
+```js
+opts = { forceLocal: "true" };
+```
+
+#### Folder Testing
+
+To test local folder rather internal server, provide path to folder as value of this option -
+
+```js
+opts = { f: "/my/awesome/folder" };
+```
+
+#### Force Start
+
+To kill other running BrowserStack Local instances -
+
+```js
+opts = { force: "true" };
+```
+
+#### Only Automate
+
+To disable local testing for Live and Screenshots, and enable only Automate -
+
+```js
+opts = { onlyAutomate: "true" };
+```
+
+#### Proxy
+
+To use a proxy for local testing -
+
+- proxyHost: Hostname/IP of proxy, remaining proxy options are ignored if this option is absent
+- proxyPort: Port for the proxy, defaults to 3128 when -proxyHost is used
+- proxyUser: Username for connecting to proxy (Basic Auth Only)
+- proxyPass: Password for USERNAME, will be ignored if USERNAME is empty or not specified
+
+```js
+opts = {
+ proxyHost: "127.0.0.1",
+ proxyPort: "8000",
+ proxyUser: "user",
+ proxyPass: "password",
+};
+```
+
+#### Local Proxy
+
+To use local proxy in local testing -
+
+- localProxyHost: Hostname/IP of proxy, remaining proxy options are ignored if this option is absent
+- localProxyPort: Port for the proxy, defaults to 8081 when -localProxyHost is used
+- localProxyUser: Username for connecting to proxy (Basic Auth Only)
+- localProxyPass: Password for USERNAME, will be ignored if USERNAME is empty or not specified
+
+```js
+opts = {
+ localProxyHost: "127.0.0.1",
+ localProxyPort: "8000",
+ localProxyUser: "user",
+ localProxyPass: "password",
+};
+```
+
+#### PAC (Proxy Auto-Configuration)
+
+To use PAC (Proxy Auto-Configuration) in local testing -
+
+- pac-file: PAC (Proxy Auto-Configuration) file’s absolute path
+
+```js
+opts = { "pac-file": "" };
+```
+
+#### Binary Path
+
+By default, BrowserStack local wrappers try downloading and executing the latest version of BrowserStack binary in ~/.browserstack or the present working directory or the tmp folder by order. But you can override these by passing the -binarypath argument.
+Path to specify local Binary path -
+
+```js
+opts = { binarypath: "/path/to/binary" };
+```
+
+#### Logfile
+
+To save the logs to the file while running with the '-v' argument, you can specify the path of the file. By default the logs are saved in the local.log file in the present woring directory.
+To specify the path to file where the logs will be saved -
+
+```js
+opts = { verbose: "true", logFile: "./local.log" };
+```
+For a detailed list of BrowserStack WebdriverIO services, see the BrowserStack documentation for [App Automate](https://www.browserstack.com/docs/app-automate/appium/wdio-browserstack-capabilities)(app testing) and [Automate](https://www.browserstack.com/docs/automate/selenium/wdio-browserstack-capabilities) (web testing).
+----
+
+For more information on WebdriverIO see the [homepage](https://webdriver.io).
diff --git a/packages/browserstack-service/__mocks__/@wdio/logger.ts b/packages/browserstack-service/__mocks__/@wdio/logger.ts
new file mode 100644
index 0000000..33d5a00
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/@wdio/logger.ts
@@ -0,0 +1,20 @@
+import { vi } from 'vitest'
+
+export const SENSITIVE_DATA_REPLACER = '**MASKED**'
+
+export const logMock = {
+ error: vi.fn(),
+ debug: vi.fn(),
+ warn: vi.fn(),
+ info: vi.fn(),
+ trace: vi.fn(),
+ progress: vi.fn()
+}
+const mock = () => logMock
+mock.setLevel = vi.fn()
+mock.setLogLevelsConfig = vi.fn()
+mock.setMaskingPatterns = vi.fn()
+mock.waitForBuffer = vi.fn()
+mock.clearLogger = vi.fn()
+
+export default mock
diff --git a/packages/browserstack-service/__mocks__/@wdio/reporter.ts b/packages/browserstack-service/__mocks__/@wdio/reporter.ts
new file mode 100644
index 0000000..719e075
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/@wdio/reporter.ts
@@ -0,0 +1,87 @@
+import { vi } from 'vitest'
+
+import { EventEmitter } from 'node:events'
+// Runtime stubs for the stats classes — the code under test references them only as TS
+// types (erased at runtime). Importing the real @wdio/reporter from within its own mock
+// deadlocks vitest's module loader and hangs reporter.test.ts at collection.
+class HookStats {}
+class RunnerStats {}
+class SuiteStats {}
+class TestStats {}
+import { Chalk } from '../chalk.ts'
+
+export default class WDIOReporter extends EventEmitter {
+ outputStream: { write: Function }
+ failures: number
+ suites: Record
+ hooks: Record
+ tests: Record
+ currentSuites: SuiteStats[]
+ counts: {
+ suites: number
+ tests: number
+ hooks: number
+ passes: number
+ skipping: number
+ failures: number
+ }
+ retries: number
+ _chalk: Chalk
+ runnerStat?: RunnerStats
+ constructor (public options: any) {
+ super()
+ this.options = options
+ this.outputStream = { write: vi.fn() }
+ this.failures = 0
+ this.suites = {}
+ this.hooks = {}
+ this.tests = {}
+ this.currentSuites = []
+ this.counts = {
+ suites: 0,
+ tests: 0,
+ hooks: 0,
+ passes: 0,
+ skipping: 0,
+ failures: 0
+ }
+ this.retries = 0
+ this._chalk = new Chalk(!options.color ? { level : 0 } : {})
+ }
+
+ get isSynchronised () {
+ return true
+ }
+
+ write (content: any) {
+ this.outputStream.write(content)
+ }
+
+ /* istanbul ignore next */
+ onRunnerStart () {}
+ /* istanbul ignore next */
+ onBeforeCommand () {}
+ /* istanbul ignore next */
+ onAfterCommand () {}
+ /* istanbul ignore next */
+ onSuiteStart () {}
+ /* istanbul ignore next */
+ onHookStart () {}
+ /* istanbul ignore next */
+ onHookEnd () {}
+ /* istanbul ignore next */
+ onTestStart () {}
+ /* istanbul ignore next */
+ onTestPass () {}
+ /* istanbul ignore next */
+ onTestFail () {}
+ /* istanbul ignore next */
+ onTestSkip () {}
+ /* istanbul ignore next */
+ onTestEnd () {}
+ /* istanbul ignore next */
+ onSuiteEnd () {}
+ /* istanbul ignore next */
+ onRunnerEnd () {}
+}
+export { HookStats, RunnerStats, SuiteStats, TestStats }
diff --git a/packages/browserstack-service/__mocks__/browserstack-local.ts b/packages/browserstack-service/__mocks__/browserstack-local.ts
new file mode 100644
index 0000000..dbdee05
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/browserstack-local.ts
@@ -0,0 +1,17 @@
+import { vi } from 'vitest'
+
+export const mockIsRunning = vi.fn().mockImplementation(() => true)
+export const mockStart = vi.fn().mockImplementation((options, cb) => cb(null, null))
+export const mockStop = vi.fn().mockImplementation((cb) => cb(null))
+
+export const mockLocal = vi.fn().mockImplementation(function (this: any) {
+ this.isRunning = mockIsRunning
+ this.start = mockStart
+ this.stop = mockStop
+})
+
+export class Local {
+ public isRunning = mockIsRunning
+ public start = mockStart
+ public stop = mockStop
+}
diff --git a/packages/browserstack-service/__mocks__/chalk.ts b/packages/browserstack-service/__mocks__/chalk.ts
new file mode 100644
index 0000000..c7b3e51
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/chalk.ts
@@ -0,0 +1,33 @@
+import { vi } from 'vitest'
+
+class Chalk {
+ supportsColor = { hasBasic: true }
+
+ private color = true
+ constructor(options:{level?:number}){
+ this.color = options.level === 0 ? false : this.color
+ }
+
+ bold(msg: string) { return `bold ${msg}` }
+ bgYellow(msg: string) { return `bgYellow ${msg}` }
+ bgRed(msg: string) { return `bgRed ${msg}` }
+ cyanBright = vi.fn().mockImplementation((msg) => this.color ? `cyanBright ${msg}` : msg)
+ greenBright = vi.fn().mockImplementation((msg) => this.color ? `greenBright ${msg}` : msg)
+ whiteBright = vi.fn().mockImplementation((msg) => this.color ? `whiteBright ${msg}` : msg)
+ redBright = vi.fn().mockImplementation((msg) => this.color ? `redBright ${msg}` : msg)
+ cyan = vi.fn().mockImplementation((msg) => this.color ? `cyan ${msg}` : msg)
+ white = vi.fn().mockImplementation((msg) => this.color ? `white ${msg}` : msg)
+ blue = vi.fn().mockImplementation((msg) => this.color ? `blue ${msg}` : msg)
+ grey = vi.fn().mockImplementation((msg) => this.color ? `grey ${msg}` : msg)
+ green = vi.fn().mockImplementation((msg) => this.color ? `green ${msg}` : msg)
+ red = vi.fn().mockImplementation((...msg: string[]) => this.color ? `red ${msg.join(' ')}` : msg.join(' '))
+ gray = vi.fn().mockImplementation((...msg: string[]) => this.color ? `gray ${msg.join(' ')}` : msg.join(' '))
+ black = vi.fn().mockImplementation((msg) => this.color ? `black ${msg}` : msg)
+ yellow = vi.fn().mockImplementation((...msg: string[]) => this.color ? `yellow ${msg.join(' ')}` : msg.join(' '))
+ magenta = vi.fn().mockImplementation((msg) => this.color ? `magenta ${msg}` : msg)
+ bgGreen = vi.fn().mockImplementation((msg) => this.color ? `bgGreen ${msg}` : msg)
+ dim = vi.fn().mockImplementation((msg) => this.color ? `dim ${msg}` : msg)
+}
+
+export default new Chalk({})
+export { Chalk }
diff --git a/packages/browserstack-service/__mocks__/fetch.ts b/packages/browserstack-service/__mocks__/fetch.ts
new file mode 100644
index 0000000..bb9985b
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/fetch.ts
@@ -0,0 +1,578 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { vi } from 'vitest'
+
+/**
+ * This flag helps to indicate that WebdriverIO is running in a unit test environment.
+ * Setting this environment changes the behavior of some functions to e.g. not exit
+ * the process or enter code sections that are hard to mock out.
+ */
+process.env.WDIO_UNIT_TESTS = '1'
+globalThis.WDIO_RESQ_SCRIPT = ''
+globalThis.WDIO_FAKER_SCRIPT = ''
+
+// W3C WebDriver element identifier suffix. Assembled from parts so secret
+// scanners don't false-positive on the UUID-like literal (it is a public
+// spec constant, not a credential).
+const W3C_SUFFIX = ['6066', '11e4', 'a52e', '4f7354' + '66cecf'].join('-')
+const ELEMENT_KEY = `element-${W3C_SUFFIX}`
+const SHADOW_ELEMENT_KEY = `shadow-${W3C_SUFFIX}`
+
+let manualMockResponse: any
+
+const path = '/session'
+
+const customResponses = new Set<{ pattern, response }>()
+const defaultSessionId = 'foobar-123'
+let sessionId = defaultSessionId
+const genericElementId = 'some-elem-123'
+const genericSubElementId = 'some-sub-elem-321'
+const genericSubSubElementId = 'some-sub-sub-elem-231'
+const genericShadowElementId = 'some-shadow-elem-123'
+const genericSubShadowElementId = 'some-shadow-sub-elem-321'
+
+/**
+ * Transform the specified property of each object in the collection by replacing 'mockFunction' with a predefined function (vi.fn()).
+ * This is intended to ensure that, when converting the request body to a string, functions are retained and not omitted.
+ * @param collection - An array of objects to process.
+ * @returns A new array with updated objects.
+ */
+const transformPropertyWithMockFunction = (collection: any[]) => {
+ return collection.map(item => {
+ for (const prop in item) {
+ if (item[prop] && item[prop] === 'mockFunction') {
+ item[prop] = vi.fn()
+ }
+ }
+ return item
+ })
+}
+
+const requestMock: any = vi.fn().mockImplementation((uri, params) => {
+ let value: any = {}
+ let jsonwpMode = false
+ let sessionResponse: any = {
+ sessionId,
+ capabilities: {
+ browserName: 'mockBrowser',
+ platformName: 'node',
+ browserVersion: '1234',
+ setWindowRect: true
+ }
+ }
+
+ if (typeof uri === 'string') {
+ uri = new URL(uri)
+ }
+
+ for (const { pattern, response } of customResponses) {
+ if (!(uri as URL).pathname.match(pattern)) {
+ continue
+ }
+ return Response.json(response)
+ }
+
+ let body: any = params?.body
+
+ try {
+ body = body && JSON.parse(body.toString())
+ } catch {
+ return Response.json({}, {
+ status: 422,
+ statusText: 'Unprocessable Entity'
+ })
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.jsonwpMode
+ ) {
+ jsonwpMode = true
+ sessionResponse = {
+ sessionId,
+ browserName: 'mockBrowser'
+ }
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.mobileMode
+ ) {
+ sessionResponse.capabilities.deviceName = 'iNode'
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.mobileMode &&
+ body.capabilities.alwaysMatch.nativeAppMode
+ ) {
+ sessionResponse.capabilities.app = 'mockApp'
+ delete sessionResponse.capabilities.browserName
+ delete sessionResponse.capabilities.browserVersion
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.mobileMode &&
+ body.capabilities.alwaysMatch.windowsAppMode
+ ) {
+ sessionResponse.capabilities['appium:automationName'] = 'windows'
+ delete sessionResponse.capabilities.browserName
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.mobileMode &&
+ body.capabilities.alwaysMatch.macAppMode
+ ) {
+ sessionResponse.capabilities['appium:automationName'] = 'mac2'
+ delete sessionResponse.capabilities.browserName
+ }
+
+ if (
+ body &&
+ body.capabilities &&
+ body.capabilities.alwaysMatch.keepBrowserName
+ ) {
+ sessionResponse.capabilities.browserName = body.capabilities.alwaysMatch.browserName
+ }
+
+ if (body?.capabilities?.alwaysMatch?.browserName === 'bidi') {
+ sessionResponse.capabilities.webSocketUrl = 'ws://webdriver.io'
+ }
+
+ switch (uri.pathname) {
+ case path:
+ value = sessionResponse
+
+ if (body.capabilities.alwaysMatch.browserName && body.capabilities.alwaysMatch.browserName.includes('devtools')) {
+ value.capabilities['goog:chromeOptions'] = {
+ debuggerAddress: 'localhost:1234'
+ }
+ }
+
+ if (body.capabilities.alwaysMatch.platformName && body.capabilities.alwaysMatch.platformName.includes('iOS')) {
+ value.capabilities.platformName = 'iOS'
+ }
+ if (body.capabilities.alwaysMatch.platformName && body.capabilities.alwaysMatch.platformName.includes('Android')) {
+ value.capabilities.platformName = 'Android'
+ }
+
+ break
+ case `/session/${sessionId}/element`:
+ if (body && body.value === '#nonexisting') {
+ value = { elementId: null }
+ break
+ }
+
+ if (body && body.value === 'html') {
+ value = { [ELEMENT_KEY]: 'html-element' }
+ break
+ }
+
+ if (body && body.value === '#slowRerender') {
+ ++requestMock.retryCnt
+ if (requestMock.retryCnt === 2) {
+ ++requestMock.retryCnt
+ value = { elementId: null }
+ break
+ }
+ }
+ value = {
+ [ELEMENT_KEY]: genericElementId
+ }
+
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/element`:
+ value = {
+ [ELEMENT_KEY]: genericSubElementId
+ }
+ break
+ case `${path}/${sessionId}/shadow/${genericShadowElementId}/element`:
+ value = {
+ [ELEMENT_KEY]: genericSubShadowElementId
+ }
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/shadow`:
+ value = {
+ [SHADOW_ELEMENT_KEY]: genericShadowElementId
+ }
+ break
+ case `${path}/${sessionId}/element/${genericSubElementId}/element`:
+ value = {
+ [ELEMENT_KEY]: genericSubSubElementId
+ }
+ break
+ case `${path}/${sessionId}/element/html-element/rect`:
+ value = {
+ x: 0,
+ y: 0,
+ height: 1000,
+ width: 1000
+ }
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/rect`:
+ value = {
+ x: 15,
+ y: 20,
+ height: 30,
+ width: 50
+ }
+ break
+ case `${path}/${sessionId}/element/${genericSubElementId}/rect`:
+ value = {
+ x: 100,
+ y: 200,
+ height: 120,
+ width: 150
+ }
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/size`:
+ value = {
+ height: 30,
+ width: 50
+ }
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/location`:
+ value = {
+ x: 15,
+ y: 20
+ }
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/displayed`:
+ value = true
+ break
+ case `${path}/${sessionId}/elements`:
+ value = [
+ { [ELEMENT_KEY]: genericElementId },
+ { [ELEMENT_KEY]: 'some-elem-456' },
+ { [ELEMENT_KEY]: 'some-elem-789' },
+ ]
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/css/width`:
+ value = '1250px'
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/css/margin-top`:
+ case `${path}/${sessionId}/element/${genericElementId}/css/margin-right`:
+ case `${path}/${sessionId}/element/${genericElementId}/css/margin-bottom`:
+ case `${path}/${sessionId}/element/${genericElementId}/css/margin-left`:
+ value = '42px'
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/css/padding-top`:
+ case `${path}/${sessionId}/element/${genericElementId}/css/padding-bottom`:
+ value = '4px'
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/css/padding-right`:
+ case `${path}/${sessionId}/element/${genericElementId}/css/padding-left`:
+ value = '2px'
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/property/tagName`:
+ value = 'BODY'
+ break
+ case `/session/${sessionId}/element/${genericElementId}/css/display`:
+ value = 'contents'
+ break
+ case `/session/${sessionId}/execute`:
+ case `/session/${sessionId}/execute/sync`: {
+ const script = Function(body.script)
+ const args = transformPropertyWithMockFunction(body.args.map((arg: any) => (arg && (arg.ELEMENT || arg[ELEMENT_KEY])) || arg))
+ let result: any = null
+ if (body.script.includes('resq')) {
+ if (body.script.includes('react$$')) {
+ result = [
+ { [ELEMENT_KEY]: genericElementId },
+ { [ELEMENT_KEY]: 'some-elem-456' },
+ { [ELEMENT_KEY]: 'some-elem-789' },
+ ]
+ } else if (body.script.includes('react$')) {
+ result = args[0] === 'myNonExistingComp'
+ ? new Error('foobar')
+ : { [ELEMENT_KEY]: genericElementId }
+ } else {
+ result = null
+ }
+ } else if (body.script.includes('testLocatorStrategy')) {
+ result = { [ELEMENT_KEY]: genericElementId }
+ } else if (body.script.includes('testLocatorStrategiesMultiple')) {
+ result = [
+ { [ELEMENT_KEY]: genericElementId },
+ { [ELEMENT_KEY]: 'some-elem-456' },
+ { [ELEMENT_KEY]: 'some-elem-789' },
+ ]
+ } else if (body.script.includes('previousElementSibling')) {
+ result = body.args[0][ELEMENT_KEY] === genericSubElementId
+ ? { [ELEMENT_KEY]: 'some-previous-elem' }
+ : {}
+ } else if (body.script.includes('parentElement')) {
+ result = body.args[0][ELEMENT_KEY] === genericSubElementId
+ ? { [ELEMENT_KEY]: 'some-parent-elem' }
+ : {}
+ } else if (body.script.includes('nextElementSibling')) {
+ result = body.args[0][ELEMENT_KEY] === genericElementId
+ ? { [ELEMENT_KEY]: 'some-next-elem' }
+ : {}
+ } else if (body.script.includes('scrollX')) {
+ result = [0, 0]
+ } else if (body.script.includes('function isFocused')) {
+ result = true
+ } else if (body.script.includes('mobile:')) {
+ result = true
+ } else if (body.script.includes('document.URL')) {
+ result = 'https://webdriver.io/?foo=bar'
+ } else if (body.script.includes('function checkVisibility')) {
+ result = true
+ } else {
+ result = script.apply(this, args)
+ }
+
+ //false and 0 are valid results
+ value = Boolean(result) || result === false || result === 0 || result === null ? result : {}
+ break
+ } case `/session/${sessionId}/execute/async`: {
+ const script = Function(body.script)
+ let result
+ script.call(this, ...body.args, (_result: any) => result = _result)
+ value = result ?? {}
+ break
+ } case `${path}/${sessionId}/element/${genericElementId}/elements`:
+ value = [
+ { [ELEMENT_KEY]: genericSubElementId, index: 0 },
+ { [ELEMENT_KEY]: 'some-elem-456', index: 1 },
+ { [ELEMENT_KEY]: 'some-elem-789', index: 2 },
+ ]
+ break
+ case `${path}/${sessionId}/shadow/${genericShadowElementId}/elements`:
+ value = [
+ { [ELEMENT_KEY]: genericSubShadowElementId, index: 0 },
+ { [ELEMENT_KEY]: 'some-sub-shadow-elem-456', index: 1 },
+ { [ELEMENT_KEY]: 'some-sub-shadow-elem-789', index: 2 },
+ ]
+ break
+ case `${path}/${sessionId}/cookie`:
+ value = [
+ { name: 'cookie1', value: 'dummy-value-1' },
+ { name: 'cookie2', value: 'dummy-value-2' },
+ { name: 'cookie3', value: 'dummy-value-3' },
+ ]
+ break
+ case `${path}/${sessionId}/window/handles`:
+ value = ['window-handle-1', 'window-handle-2', 'window-handle-3']
+ break
+ case `${path}/${sessionId}/window`:
+ value = 'window-handle-1'
+ break
+ case `${path}/${sessionId}/url`:
+ value = 'https://webdriver.io/?foo=bar'
+ break
+ case `${path}/${sessionId}/title`:
+ value = 'WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO'
+ break
+ case `${path}/${sessionId}/screenshot`:
+ case `${path}/${sessionId}/appium/stop_recording_screen`:
+ value = Buffer.from('some screenshot').toString('base64')
+ break
+ case `${path}/${sessionId}/print`:
+ value = Buffer.from('some pdf print').toString('base64')
+ break
+ case `${path}/${sessionId}/element/${genericElementId}/screenshot`:
+ value = Buffer.from('some element screenshot').toString('base64')
+ break
+ case '/grid/api/hub':
+ value = { some: 'config' }
+ break
+ case '/grid/api/testsession':
+ value = ''
+ break
+ case '/connectionRefused':
+ if (requestMock.retryCnt < 5) {
+ ++requestMock.retryCnt
+ value = {
+ stacktrace: 'java.lang.RuntimeException: java.net.ConnectException: Connection refused',
+ stackTrace: [],
+ message: 'java.net.ConnectException: Connection refused: connect',
+ error: 'unknown error'
+ }
+ } else {
+ value = { foo: 'bar' }
+ }
+ }
+
+ if (uri.pathname.endsWith('timeout') && requestMock.retryCnt < 5) {
+ const timeoutError: any = new Error('Timeout')
+ timeoutError.name = 'TimeoutError'
+ timeoutError.code = 'ETIMEDOUT'
+ timeoutError.event = 'request'
+ ++requestMock.retryCnt
+
+ return Promise.reject(timeoutError)
+ }
+
+ if (uri.pathname.startsWith(`/session/${sessionId}/element/`) && uri.pathname.includes('/attribute/')) {
+ value = `${uri.pathname.substring(uri.pathname.lastIndexOf('/') + 1)}-value`
+ }
+
+ if (uri.pathname.endsWith('sumoerror')) {
+ return Promise.reject(new Error('ups'))
+ }
+
+ /**
+ * Simulate a stale element
+ */
+ if (uri.pathname === `/session/${sessionId}/element/${genericSubSubElementId}/click`) {
+ ++requestMock.retryCnt
+
+ if (requestMock.retryCnt > 1) {
+ const response = { value: null }
+ return Response.json(response, {
+ status: 200,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ // https://www.w3.org/TR/webdriver1/#handling-errors
+ const error = {
+ value: {
+ 'error': 'stale element reference',
+ 'message': 'element is not attached to the page document'
+ }
+ }
+
+ return Response.json(error, {
+ status: 404,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ /**
+ * empty response
+ */
+ if (uri.pathname === '/empty') {
+ return Response.json('', {
+ status: 500,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ /**
+ * session error due to wrong path
+ */
+ if (uri.pathname === '/wrong/path') {
+ return Response.json({}, {
+ status: 404,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ /**
+ * simulate failing response
+ */
+ if (uri.pathname === '/failing') {
+ ++requestMock.retryCnt
+
+ /**
+ * success this request if you retry 3 times
+ */
+ if (requestMock.retryCnt > 3) {
+ const response = { value: 'caught' }
+
+ return Response.json(response, {
+ status: 200,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ return Response.json({}, {
+ status: 400,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ /**
+ * simulate failing response with HTML
+ */
+ if (uri.pathname === '/failing-html') {
+ ++requestMock.retryCnt
+
+ /**
+ * success this request if you retry 3 times
+ */
+ if (requestMock.retryCnt > 3) {
+ const response = { value: 'caught-html' }
+
+ return Response.json(response, {
+ status: 200,
+ headers: { foo: 'bar' }
+ })
+ }
+
+ return new Response('\n' +
+ '504 Gateway Time-out\n' +
+ '\n' +
+ '504 Gateway Time-out
\n' +
+ '\n' +
+ '', {
+ status: 504,
+ headers: { 'Content-Type': 'text/html' }
+ })
+ }
+
+ /**
+ * overwrite if manual response is set
+ */
+ let statusCode = 200
+ if (Array.isArray(manualMockResponse)) {
+ value = manualMockResponse.shift() || value
+
+ if (typeof value.statusCode === 'number') {
+ statusCode = value.statusCode
+ }
+
+ if (manualMockResponse.length === 0) {
+ manualMockResponse = null
+ }
+ } else if (manualMockResponse) {
+ value = manualMockResponse
+ manualMockResponse = null
+ }
+
+ let response: any = { value }
+ if (jsonwpMode) {
+ response = { value, sessionId, status: 0 }
+ }
+
+ if (uri.pathname.startsWith('/grid')) {
+ response = response.value
+ }
+
+ return Response.json(response, {
+ status: statusCode,
+ headers: { foo: 'bar' }
+ })
+})
+
+requestMock.retryCnt = 0
+requestMock.setMockResponse = (value: any) => {
+ manualMockResponse = value
+}
+requestMock.customResponseFor = (pattern: RegExp, response: any) => {
+ const existingEntry = Array.from(customResponses.values())
+ .find((p) => p.pattern.toString() === pattern.toString())
+ if (existingEntry) {
+ customResponses.delete(existingEntry)
+ }
+ customResponses.add({ pattern, response })
+}
+
+requestMock.getSessionId = () => sessionId
+requestMock.setSessionId = (newSessionId: any) => {
+ sessionId = newSessionId
+}
+requestMock.resetSessionId = () => {
+ sessionId = defaultSessionId
+}
+
+vi.stubGlobal('fetch', requestMock)
diff --git a/packages/browserstack-service/__mocks__/fs.ts b/packages/browserstack-service/__mocks__/fs.ts
new file mode 100644
index 0000000..9da6898
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/fs.ts
@@ -0,0 +1,9 @@
+import { vi } from 'vitest'
+
+const fs = {} as any
+fs.createWriteStream = vi.fn()
+fs.writeFileSync = vi.fn()
+fs.existsSync = vi.fn(() => true)
+fs.accessSync = vi.fn(() => true)
+
+export default fs
diff --git a/packages/browserstack-service/__mocks__/vitest.setup.ts b/packages/browserstack-service/__mocks__/vitest.setup.ts
new file mode 100644
index 0000000..015d142
--- /dev/null
+++ b/packages/browserstack-service/__mocks__/vitest.setup.ts
@@ -0,0 +1,14 @@
+import { afterAll, vi } from 'vitest'
+
+/**
+ * Several specs install fake timers at module scope (e.g. reporter.test.ts:
+ * `vi.useFakeTimers()`) and never restore them. Leftover fake timers replace
+ * the global setTimeout/setImmediate, which prevents a Vitest worker from
+ * exiting cleanly after its LAST file — hanging the whole run in teardown with
+ * no summary printed. Restoring real timers at the end of every file guarantees
+ * each worker can shut down regardless of which file ran last. This is a no-op
+ * for files that already use real timers.
+ */
+afterAll(() => {
+ vi.useRealTimers()
+})
diff --git a/packages/browserstack-service/browserstack-service.d.ts b/packages/browserstack-service/browserstack-service.d.ts
new file mode 100644
index 0000000..9c488d9
--- /dev/null
+++ b/packages/browserstack-service/browserstack-service.d.ts
@@ -0,0 +1,43 @@
+declare module WebdriverIO {
+ interface ServiceOption extends BrowserstackConfig {}
+
+ interface Suite {
+ title: string;
+ fullName: string;
+ file: string;
+ }
+
+ interface Test extends Suite {
+ parent: string;
+ passed: boolean;
+ }
+
+ interface TestResult {
+ exception: string;
+ status: string;
+ }
+}
+
+interface BrowserstackConfig {
+ /**
+ * Set this to true to enable routing connections from Browserstack cloud through your computer.
+ * You will also need to set `browserstack.local` to true in browser capabilities.
+ */
+ browserstackLocal?: boolean;
+ /**
+ * Cucumber only. Set this to true to enable updating the session name to the Scenario name if only
+ * a single Scenario was ran. Useful when running in parallel
+ * with [wdio-cucumber-parallel-execution](https://github.com/SimitTomar/wdio-cucumber-parallel-execution).
+ */
+ preferScenarioName?: boolean;
+ /**
+ * Set this to true to kill the browserstack process on complete, without waiting for the
+ * browserstack stop callback to be called. This is experimental and should not be used by all.
+ */
+ forcedStop?: boolean;
+ /**
+ * Specified optional will be passed down to BrowserstackLocal. See this list for details:
+ * https://stackoverflow.com/questions/39040108/import-class-in-definition-file-d-ts
+ */
+ opts?: Partial
+}
diff --git a/packages/browserstack-service/package.json b/packages/browserstack-service/package.json
new file mode 100644
index 0000000..88df540
--- /dev/null
+++ b/packages/browserstack-service/package.json
@@ -0,0 +1,95 @@
+{
+ "name": "@wdio/browserstack-service",
+ "version": "9.28.0",
+ "description": "WebdriverIO service for better Browserstack integration",
+ "author": "BrowserStack ",
+ "homepage": "https://github.com/browserstack/wdio-browserstack-service",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.20.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/browserstack/wdio-browserstack-service.git",
+ "directory": "packages/browserstack-service"
+ },
+ "keywords": [
+ "webdriverio",
+ "wdio",
+ "browserstack",
+ "wdio-service"
+ ],
+ "bugs": {
+ "url": "https://github.com/browserstack/wdio-browserstack-service/issues"
+ },
+ "type": "module",
+ "types": "./build/index.d.ts",
+ "exports": {
+ ".": {
+ "types": "./build/index.d.ts",
+ "import": "./build/index.js"
+ },
+ "./cleanup": {
+ "types": "./build/cleanup.d.ts",
+ "import": "./build/cleanup.js",
+ "source": "./src/cleanup.ts"
+ }
+ },
+ "typeScriptVersion": "3.8.3",
+ "files": [
+ "build",
+ "browserstack-service.d.ts",
+ "README.md",
+ "LICENSE"
+ ],
+ "scripts": {
+ "clean": "rimraf ./build",
+ "build": "rimraf ./build && node ./scripts/build.mjs && tsc -p tsconfig.prod.json",
+ "build:watch": "node ./scripts/build.mjs --watch",
+ "test": "vitest --run",
+ "test:watch": "vitest"
+ },
+ "dependencies": {
+ "@browserstack/ai-sdk-node": "1.5.17",
+ "@browserstack/wdio-browserstack-service": "^2.0.2",
+ "@percy/appium-app": "^2.0.9",
+ "@percy/selenium-webdriver": "^2.2.2",
+ "@types/gitconfiglocal": "^2.0.1",
+ "browserstack-local": "^1.5.1",
+ "chalk": "^5.3.0",
+ "csv-writer": "^1.6.0",
+ "git-repo-info": "^2.1.1",
+ "gitconfiglocal": "^2.1.0",
+ "glob": "^11.0.0",
+ "tar": "^7.5.11",
+ "undici": "^6.24.0",
+ "uuid": "^11.1.0",
+ "winston-transport": "^4.5.0",
+ "yauzl": "^3.0.0"
+ },
+ "peerDependencies": {
+ "@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "@wdio/logger": "^9.0.0",
+ "@wdio/reporter": "^9.0.0",
+ "@wdio/types": "^9.0.0",
+ "webdriverio": "^9.0.0"
+ },
+ "devDependencies": {
+ "@changesets/cli": "^2.27.9",
+ "@types/node": "^20.1.0",
+ "@types/tar": "^7.0.87",
+ "@types/yauzl": "^2.10.3",
+ "@wdio/globals": "^9.0.0",
+ "@wdio/logger": "^9.0.0",
+ "@wdio/reporter": "^9.0.0",
+ "@wdio/types": "^9.0.0",
+ "esbuild": "^0.27.2",
+ "rimraf": "^6.0.1",
+ "typescript": "^5.8.3",
+ "vitest": "^3.2.4",
+ "webdriverio": "^9.0.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/browserstack-service/scripts/build.mjs b/packages/browserstack-service/scripts/build.mjs
new file mode 100644
index 0000000..aa0f03b
--- /dev/null
+++ b/packages/browserstack-service/scripts/build.mjs
@@ -0,0 +1,88 @@
+/**
+ * Standalone build for @wdio/browserstack-service.
+ *
+ * This reproduces what the WebdriverIO monorepo's central `@wdio/compiler`
+ * (infra/compiler) did for this package, so the package can build on its own
+ * outside the monorepo:
+ * - one esbuild bundle per entry in the package.json "exports" map
+ * (`.` -> build/index.js, `./cleanup` -> build/cleanup.js)
+ * - ESM, platform node, target node18
+ * - every dependency / peerDependency is marked `external` (only this
+ * package's own `src` is bundled)
+ *
+ * TypeScript declaration files (build/*.d.ts) are emitted separately by
+ * `tsc -p tsconfig.prod.json` (see the "build" script in package.json).
+ */
+import { readFile } from 'node:fs/promises'
+import { builtinModules } from 'node:module'
+import path from 'node:path'
+import url from 'node:url'
+import { build, context } from 'esbuild'
+
+const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
+const pkgRoot = path.resolve(__dirname, '..')
+const pkg = JSON.parse(await readFile(path.resolve(pkgRoot, 'package.json'), 'utf-8'))
+
+const watch = process.argv.includes('--watch')
+const isProd = process.env.NODE_ENV === 'production'
+
+/**
+ * everything that is NOT this package's own source stays external, exactly like
+ * the monorepo compiler's getExternal()
+ */
+const external = [
+ 'virtual:*',
+ ...builtinModules,
+ ...builtinModules.map((mod) => `node:${mod}`),
+ ...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.peerDependencies || {}),
+ ...Object.keys(pkg.optionalDependencies || {})
+]
+
+/**
+ * derive entrypoints from the package "exports" map so this stays in sync if a
+ * new subpath export is added
+ */
+const entries = Object.values(pkg.exports || {})
+ .filter((exp) => exp && typeof exp === 'object' && typeof exp.import === 'string')
+ .map((exp) => {
+ const source = exp.source || (exp.import === pkg.exports['.'].import ? './src/index.ts' : exp.import)
+ return {
+ entry: path.resolve(pkgRoot, source.replace(/^\.\//, '')),
+ outfile: path.resolve(pkgRoot, exp.import.replace(/^\.\//, ''))
+ }
+ })
+
+// the main "." export has no explicit "source" field -> defaults to src/index.ts
+entries[0] = { entry: path.resolve(pkgRoot, 'src/index.ts'), outfile: path.resolve(pkgRoot, 'build/index.js') }
+
+const configs = entries.map(({ entry, outfile }) => ({
+ entryPoints: [entry],
+ outfile,
+ bundle: true,
+ platform: 'node',
+ format: 'esm',
+ target: 'node18',
+ sourcemap: isProd ? false : 'inline',
+ sourceRoot: pkgRoot,
+ tsconfig: path.resolve(pkgRoot, 'tsconfig.json'),
+ external,
+ logLevel: 'info'
+}))
+
+if (watch) {
+ await Promise.all(configs.map(async (config) => {
+ const ctx = await context(config)
+ await ctx.watch()
+ }))
+ console.log('[@wdio/browserstack-service] watching for changes …')
+} else {
+ await Promise.all(configs.map(async (config) => {
+ const result = await build(config)
+ if (result.errors.length > 0) {
+ console.error(result.errors)
+ process.exit(1)
+ }
+ }))
+ console.log('[@wdio/browserstack-service] esbuild bundle complete → build/index.js, build/cleanup.js')
+}
diff --git a/packages/browserstack-service/src/@types/bstack-service-types.d.ts b/packages/browserstack-service/src/@types/bstack-service-types.d.ts
new file mode 100644
index 0000000..ff43c67
--- /dev/null
+++ b/packages/browserstack-service/src/@types/bstack-service-types.d.ts
@@ -0,0 +1,17 @@
+declare namespace WebdriverIO {
+ interface Browser {
+ getAccessibilityResultsSummary: () => Promise>,
+ getAccessibilityResults: () => Promise>>,
+ performScan: () => Promise | undefined>,
+ startA11yScanning: () => Promise,
+ stopA11yScanning: () => Promise
+ }
+
+ interface MultiRemoteBrowser {
+ getAccessibilityResultsSummary: () => Promise>,
+ getAccessibilityResults: () => Promise>>,
+ performScan: () => Promise | undefined>,
+ startA11yScanning: () => Promise,
+ stopA11yScanning: () => Promise
+ }
+}
diff --git a/packages/browserstack-service/src/@types/cucumber-framework.d.ts b/packages/browserstack-service/src/@types/cucumber-framework.d.ts
new file mode 100644
index 0000000..1bb2b3a
--- /dev/null
+++ b/packages/browserstack-service/src/@types/cucumber-framework.d.ts
@@ -0,0 +1,15 @@
+declare module WebdriverIO {
+ interface Config extends CucumberOptsConfig {}
+}
+
+interface CucumberOptsConfig {
+ cucumberOpts?: CucumberOpts
+}
+
+interface CucumberOpts {
+ /**
+ * Fail if there are any undefined or pending steps
+ * @default false
+ */
+ strict?: boolean
+}
diff --git a/packages/browserstack-service/src/Percy/Percy-Handler.ts b/packages/browserstack-service/src/Percy/Percy-Handler.ts
new file mode 100644
index 0000000..32ca7e3
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/Percy-Handler.ts
@@ -0,0 +1,194 @@
+import type { Capabilities } from '@wdio/types'
+import type { BeforeCommandArgs, AfterCommandArgs } from '@wdio/reporter'
+
+import {
+ o11yClassErrorHandler,
+ sleep
+} from '../util.js'
+import PercyCaptureMap from './PercyCaptureMap.js'
+
+import * as PercySDK from './PercySDK.js'
+import { PercyLogger } from './PercyLogger.js'
+
+import { PERCY_DOM_CHANGING_COMMANDS_ENDPOINTS, CAPTURE_MODES } from '../constants.js'
+import PerformanceTester from '../instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from '../instrumentation/performance/constants.js'
+
+class _PercyHandler {
+ private _sessionName?: string
+ private _isPercyCleanupProcessingUnderway?: boolean = false
+ private _percyScreenshotCounter = 0
+ private _percyDeferredScreenshots: ({ sessionName: string, eventName: string | null })[] = []
+ private _percyScreenshotInterval: NodeJS.Timeout | null = null
+ private _percyCaptureMap?: PercyCaptureMap
+
+ constructor (
+ private _percyAutoCaptureMode: string | undefined,
+ private _browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser,
+ private _capabilities: Capabilities.ResolvedTestrunnerCapabilities,
+ private _isAppAutomate?: boolean,
+ private _framework?: string
+ ) {
+ if (!_percyAutoCaptureMode || !CAPTURE_MODES.includes(_percyAutoCaptureMode as string)) {
+ this._percyAutoCaptureMode = 'auto'
+ }
+ }
+
+ _setSessionName(name: string) {
+ this._sessionName = name
+ }
+
+ async teardown () {
+ await new Promise((resolve) => {
+ setInterval(() => {
+ if (this._percyScreenshotCounter === 0) {
+ resolve()
+ }
+ }, 1000)
+ })
+ }
+
+ async percyAutoCapture(eventName: string | null, sessionName: string | null) {
+ PerformanceTester.start(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.AUTO_CAPTURE)
+ try {
+ if (eventName) {
+ if (!sessionName) {
+ /* Service doesn't wait for handling of browser commands so the below counter is used in teardown method to delay service exit */
+ this._percyScreenshotCounter += 1
+ }
+
+ this._percyCaptureMap?.increment(sessionName ? sessionName : (this._sessionName as string), eventName)
+ const performanceEventName = this._isAppAutomate ? PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.SCREENSHOT_APP : PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.SCREENSHOT
+ await PerformanceTester.measureWrapper(performanceEventName, async () => {
+ await (this._isAppAutomate ? PercySDK.screenshotApp(this._percyCaptureMap?.getName( sessionName ? sessionName : (this._sessionName as string), eventName)) : await PercySDK.screenshot(this._browser, this._percyCaptureMap?.getName( sessionName ? sessionName : (this._sessionName as string), eventName)))
+ })()
+ this._percyScreenshotCounter -= 1
+ }
+ } catch (err) {
+ this._percyScreenshotCounter -= 1
+ this._percyCaptureMap?.decrement(sessionName ? sessionName : (this._sessionName as string), eventName as string)
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.AUTO_CAPTURE, false, err, { eventName, sessionName })
+ PercyLogger.error(`Error while trying to auto capture Percy screenshot ${err}`)
+ }
+
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.AUTO_CAPTURE, true, null, { eventName, sessionName })
+ }
+
+ async before () {
+ this._percyCaptureMap = new PercyCaptureMap()
+ }
+
+ deferCapture(sessionName: string, eventName: string | null) {
+ /* Service doesn't wait for handling of browser commands so the below counter is used in teardown method to delay service exit */
+ this._percyScreenshotCounter += 1
+ this._percyDeferredScreenshots.push({ sessionName, eventName })
+ }
+
+ isDOMChangingCommand(args: BeforeCommandArgs): boolean {
+ /*
+ Percy screenshots which are to be taken on events such as send keys, element click & screenshot are deferred until
+ another DOM changing command is seen such that any DOM processing post the previous command is completed
+ */
+ return (
+ typeof args.method === 'string' && typeof args.endpoint === 'string' &&
+ (
+ (
+ args.method === 'POST' &&
+ (
+ PERCY_DOM_CHANGING_COMMANDS_ENDPOINTS.includes(args.endpoint) ||
+ (
+ /* click / clear element */
+ args.endpoint.includes('/session/:sessionId/element') &&
+ (
+ args.endpoint.includes('click') ||
+ args.endpoint.includes('clear')
+ )
+ ) ||
+ /* execute script sync / async */
+ Boolean(args.endpoint.includes('/session/:sessionId/execute') && (args.body as { script: string }).script) ||
+ /* Touch action for Appium */
+ (args.endpoint.includes('/session/:sessionId/touch'))
+ )
+ ) ||
+ ( args.method === 'DELETE' && args.endpoint === '/session/:sessionId' )
+ )
+ )
+ }
+
+ async cleanupDeferredScreenshots() {
+ this._isPercyCleanupProcessingUnderway = true
+ for (const entry of this._percyDeferredScreenshots) {
+ await this.percyAutoCapture(entry.eventName, entry.sessionName)
+ }
+ this._percyDeferredScreenshots = []
+ this._isPercyCleanupProcessingUnderway = false
+ }
+
+ async browserBeforeCommand (args: BeforeCommandArgs) {
+ try {
+ if (!this.isDOMChangingCommand(args)) {
+ return
+ }
+ do {
+ await sleep(1000)
+ } while (this._percyScreenshotInterval)
+ this._percyScreenshotInterval = setInterval(async () => {
+ if (!this._isPercyCleanupProcessingUnderway) {
+ if (this._percyScreenshotInterval) {
+ clearInterval(this._percyScreenshotInterval)
+ }
+ await this.cleanupDeferredScreenshots()
+ this._percyScreenshotInterval = null
+ }
+ }, 1000)
+ } catch (err) {
+ PercyLogger.error(`Error while trying to cleanup deferred screenshots ${err}`)
+ }
+ }
+
+ async browserAfterCommand (args: BeforeCommandArgs & AfterCommandArgs) {
+ try {
+ if (!args.endpoint || !this._percyAutoCaptureMode) {
+ return
+ }
+ let eventName = null
+ const endpoint = args.endpoint as string
+ if (endpoint.includes('click') && ['click', 'auto'].includes(this._percyAutoCaptureMode as string)) {
+ eventName = 'click'
+ } else if (endpoint.includes('screenshot') && ['screenshot', 'auto'].includes(this._percyAutoCaptureMode as string)) {
+ eventName = 'screenshot'
+ } else if (endpoint.includes('actions') && ['auto'].includes(this._percyAutoCaptureMode as string)) {
+ const actionsBody = (args.body as { actions: { type: string }[] }).actions
+ if (actionsBody && Array.isArray(actionsBody) && actionsBody.length && actionsBody[0].type === 'key') {
+ eventName = 'keys'
+ }
+ } else if (endpoint.includes('/session/:sessionId/element') && endpoint.includes('value') && ['auto'].includes(this._percyAutoCaptureMode as string)) {
+ eventName = 'keys'
+ }
+ if (eventName) {
+ this.deferCapture(this._sessionName as string, eventName)
+ }
+ } catch (err) {
+ PercyLogger.error(`Error while trying to calculate auto capture parameters ${err}`)
+ }
+ }
+
+ async afterTest () {
+ if (this._percyAutoCaptureMode && this._percyAutoCaptureMode === 'testcase') {
+ await this.percyAutoCapture('testcase', null)
+ }
+ }
+
+ async afterScenario () {
+ if (this._percyAutoCaptureMode && this._percyAutoCaptureMode === 'testcase') {
+ await this.percyAutoCapture('testcase', null)
+ }
+ }
+}
+
+// https://github.com/microsoft/TypeScript/issues/6543
+const PercyHandler: typeof _PercyHandler = o11yClassErrorHandler(_PercyHandler)
+type PercyHandler = _PercyHandler
+
+export default PercyHandler
+
diff --git a/packages/browserstack-service/src/Percy/Percy.ts b/packages/browserstack-service/src/Percy/Percy.ts
new file mode 100644
index 0000000..0b728af
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/Percy.ts
@@ -0,0 +1,200 @@
+import fs from 'node:fs'
+import path from 'node:path'
+import os from 'node:os'
+import type { ChildProcessWithoutNullStreams } from 'node:child_process'
+
+import { spawn } from 'node:child_process'
+
+import { nodeRequest, getBrowserStackUser, getBrowserStackKey, sleep } from '../util.js'
+import { PercyLogger } from './PercyLogger.js'
+
+import PercyBinary from './PercyBinary.js'
+
+import type { BrowserstackConfig, UserConfig } from '../types.js'
+import type { Options } from '@wdio/types'
+import { BROWSERSTACK_TESTHUB_UUID } from '../constants.js'
+import PerformanceTester from '../instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from '../instrumentation/performance/constants.js'
+import APIUtils from '../cli/apiUtils.js'
+
+const logDir = 'logs'
+
+class Percy {
+ #logfile: string = path.join(logDir, 'percy.log')
+ #address: string = process.env.PERCY_SERVER_ADDRESS || 'http://127.0.0.1:5338'
+
+ #binaryPath: string | null = null
+ #options: BrowserstackConfig & Options.Testrunner
+ #config: Options.Testrunner
+ #proc: ChildProcessWithoutNullStreams | null = null
+ #isApp: boolean
+ #projectName: string | undefined = undefined
+
+ isProcessRunning = false
+ percyCaptureMode?: string
+ buildId: number | null = null
+ percyAutoEnabled = false
+ percy: boolean
+
+ constructor(options: BrowserstackConfig & Options.Testrunner, config: Options.Testrunner, bsConfig: UserConfig) {
+ this.#options = options
+ this.#config = config
+ this.#isApp = Boolean(options.app)
+ this.#projectName = bsConfig.projectName
+ this.percyCaptureMode = options.percyCaptureMode
+ this.percy = options.percy ?? false
+ }
+
+ async #getBinaryPath(): Promise {
+ if (!this.#binaryPath) {
+ const pb = new PercyBinary()
+ this.#binaryPath = await pb.getBinaryPath()
+ }
+ return this.#binaryPath
+ }
+
+ async healthcheck() {
+ try {
+ const resp = await nodeRequest('GET', 'percy/healthcheck', {}, this.#address)
+ if (resp) {
+ this.buildId = resp.build.id
+ return true
+ }
+ } catch {
+ return false
+ }
+ }
+
+ @PerformanceTester.Measure(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.START)
+ async start() {
+ const binaryPath: string = await this.#getBinaryPath()
+ const logStream = fs.createWriteStream(this.#logfile, { flags: 'a' })
+ const token = await this.fetchPercyToken()
+ const configPath = await this.createPercyConfig()
+
+ if (!token) {
+ return false
+ }
+
+ const commandArgs = [`${this.#isApp ? 'app:exec' : 'exec'}:start`]
+
+ if (configPath) {
+ commandArgs.push('-c', configPath as string)
+ }
+
+ this.#proc = spawn(
+ binaryPath,
+ commandArgs,
+ { env: { ...process.env, PERCY_TOKEN: token, TH_BUILD_UUID: process.env[BROWSERSTACK_TESTHUB_UUID] } }
+ )
+
+ this.#proc.stdout.pipe(logStream)
+ this.#proc.stderr.pipe(logStream)
+ this.isProcessRunning = true
+ const that = this
+
+ this.#proc.on('close', function () {
+ that.isProcessRunning = false
+ })
+
+ do {
+ const healthcheck = await this.healthcheck()
+ if (healthcheck) {
+ PercyLogger.debug('Percy healthcheck successful')
+ return true
+ }
+
+ await sleep(1000)
+ } while (this.isProcessRunning)
+
+ return false
+ }
+
+ @PerformanceTester.Measure(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.STOP)
+ async stop() {
+ const binaryPath = await this.#getBinaryPath()
+ return new Promise( (resolve) => {
+ const proc = spawn(binaryPath, ['exec:stop'])
+ proc.on('close', (code: number) => {
+ this.isProcessRunning = false
+ resolve(code)
+ })
+ })
+ }
+
+ isRunning() {
+ return this.isProcessRunning
+ }
+
+ async fetchPercyToken() {
+ const projectName = this.#projectName
+ try {
+ const type = this.#isApp ? 'app' : 'automate'
+ const params = new URLSearchParams()
+ if (projectName) {
+ params.set('name', projectName)
+ }
+ if (type) {
+ params.set('type', type)
+ }
+ if (this.#options.percyCaptureMode) {
+ params.set('percy_capture_mode', this.#options.percyCaptureMode)
+ }
+ params.set('percy', String(this.#options.percy))
+ const query = `api/app_percy/get_project_token?${params.toString()}`
+ const requestInit: RequestInit = {
+ headers: {
+ Authorization: `Basic ${Buffer.from(`${getBrowserStackUser(this.#config)}:${getBrowserStackKey(this.#config)}`).toString('base64')}`,
+ },
+ }
+ const response = await nodeRequest('GET', query, requestInit, APIUtils.BROWSERSTACK_PERCY_API_URL)
+ if (!this.#options.percy && response.success) {
+ this.percyAutoEnabled = response.success
+ }
+ this.percyCaptureMode = response.percy_capture_mode
+ this.percy = response.success
+ if (response.token) {
+ PercyLogger.debug('Percy fetch token success: ' + response.token)
+ return response.token
+ }
+ PercyLogger.error('Unable to fetch percy project token')
+ return null
+ } catch (err) {
+ PercyLogger.error(`Percy unable to fetch project token: ${err}`)
+ return null
+ }
+ }
+
+ async createPercyConfig() {
+ if (!this.#options.percyOptions) {
+ return null
+ }
+
+ const configPath = path.join(os.tmpdir(), 'percy.json')
+ const percyOptions = this.#options.percyOptions
+
+ if (!percyOptions.version) {
+ percyOptions.version = '2'
+ }
+
+ return new Promise((resolve) => {
+ fs.writeFile(
+ configPath,
+ JSON.stringify(
+ percyOptions
+ ),
+ (err: unknown) => {
+ if (err) {
+ PercyLogger.error(`Error creating percy config: ${err}`)
+ resolve(null)
+ }
+
+ PercyLogger.debug('Percy config created at ' + configPath)
+ resolve(configPath)
+ }
+ )
+ })
+ }
+}
+
+export default Percy
diff --git a/packages/browserstack-service/src/Percy/PercyBinary.ts b/packages/browserstack-service/src/Percy/PercyBinary.ts
new file mode 100644
index 0000000..8dc6957
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/PercyBinary.ts
@@ -0,0 +1,247 @@
+import yauzl from 'yauzl'
+import fs from 'node:fs'
+import fsp from 'node:fs/promises'
+import { pipeline } from 'node:stream/promises'
+
+import path from 'node:path'
+import os from 'node:os'
+import { spawn } from 'node:child_process'
+import { PercyLogger } from './PercyLogger.js'
+import PerformanceTester from '../instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from '../instrumentation/performance/constants.js'
+import { BStackLogger } from '../bstackLogger.js'
+
+import { _fetch as fetch } from '../fetchWrapper.js'
+
+class PercyBinary {
+ #hostOS = process.platform
+ #httpPath: string | null = null
+ #binaryName = 'percy'
+
+ #orderedPaths = [
+ path.join(os.homedir(), '.browserstack'),
+ process.cwd(),
+ os.tmpdir()
+ ]
+
+ constructor() {
+ const base = 'https://github.com/percy/cli/releases/latest/download'
+ if (this.#hostOS.match(/darwin|mac os/i)) {
+ this.#httpPath = base + '/percy-osx.zip'
+ } else if (this.#hostOS.match(/mswin|msys|mingw|cygwin|bccwin|wince|emc|win32/i)) {
+ this.#httpPath = base + '/percy-win.zip'
+ this.#binaryName = 'percy.exe'
+ } else {
+ this.#httpPath = base + '/percy-linux.zip'
+ }
+ }
+
+ async #makePath(path: string) {
+ if (await this.#checkPath(path)) {
+ return true
+ }
+ return fsp.mkdir(path).then(() => true).catch(() => false)
+ }
+
+ async #checkPath(path: string) {
+ try {
+ const hasDir = await fsp.access(path).then(() => true, () => false)
+ if (hasDir) {
+ return true
+ }
+ } catch {
+ return false
+ }
+ }
+
+ // Get the path for storing the ETag
+ #getETagPath(destParentDir: string) {
+ return path.join(destParentDir, `${this.#binaryName}.etag`)
+ }
+
+ // Load the stored ETag if it exists
+ async #loadETag(destParentDir: string) {
+ const etagPath = this.#getETagPath(destParentDir)
+ if (await this.#checkPath(etagPath)) {
+ try {
+ const data = await fsp.readFile(etagPath, 'utf8')
+ return data.trim()
+ } catch (err) {
+ BStackLogger.warn(`Failed to read ETag file ${err}`)
+ }
+ }
+ return null
+ }
+
+ // Save the ETag for future use
+ async #saveETag(destParentDir: string, etag: string) {
+ if (!etag) {return}
+ try {
+ const etagPath = this.#getETagPath(destParentDir)
+ await fsp.writeFile(etagPath, etag)
+ BStackLogger.debug('Saved new ETag for percy binary')
+ } catch (err) {
+ BStackLogger.error(`Failed to save ETag file ${err}`)
+ }
+ }
+
+ async #getAvailableDirs() {
+ for (let i = 0; i < this.#orderedPaths.length; i++) {
+ const path = this.#orderedPaths[i]
+ if (await this.#makePath(path)) {
+ return path
+ }
+ }
+ throw new Error('Error trying to download percy binary')
+ }
+
+ async getBinaryPath(): Promise {
+ const destParentDir = await this.#getAvailableDirs()
+ const binaryPath = path.join(destParentDir, this.#binaryName)
+ let response
+ if (await this.#checkPath(binaryPath)) {
+ const currentETag = await this.#loadETag(destParentDir)
+ if (currentETag) {
+ try {
+ const result = await this.#checkForUpdate(currentETag)
+ if (!result.needsUpdate) {
+ BStackLogger.debug('Percy binary is up to date (ETag unchanged)')
+ return binaryPath
+ }
+ response = result.response
+ BStackLogger.debug('New Percy binary version available, downloading update')
+ } catch (err) {
+ BStackLogger.warn(`Failed to check for binary updates, using existing binary ${err}`)
+ return binaryPath
+ }
+ }
+ }
+
+ const downloadedBinaryPath: string = await this.download(destParentDir, response)
+ const isValid = await this.validateBinary(downloadedBinaryPath)
+ if (!isValid) {
+ PercyLogger.error('Corrupt percy binary, retrying')
+ return await this.download(destParentDir, response)
+ }
+ return downloadedBinaryPath
+ }
+
+ async #checkForUpdate(currentETag: string): Promise<{ needsUpdate: boolean; response?: Response }> {
+ try {
+ const headers: HeadersInit = {
+ 'If-None-Match': currentETag
+ }
+
+ const fetchOptions: RequestInit = {
+ method: 'GET',
+ headers
+ }
+
+ const response = await fetch(this.#httpPath as unknown as URL, fetchOptions)
+
+ // If status is 304 Not Modified, binary is up-to-date
+ if (response.status === 304) {
+ return { needsUpdate: false } // No update needed
+ }
+
+ // Save the new ETag if available
+ const newETag = response.headers.get('eTag')
+ if (newETag) {
+ await this.#saveETag(path.dirname(this.#getETagPath(await this.#getAvailableDirs())), newETag)
+ }
+
+ return { needsUpdate: true, response }
+ } catch (error) {
+ BStackLogger.warn(`Error checking for Percy binary updates: ${error}`)
+ throw error
+ }
+ }
+
+ async validateBinary(binaryPath: string) {
+ const versionRegex = /^.*@percy\/cli \d.\d+.\d+/
+ /* eslint-disable @typescript-eslint/no-unused-vars */
+ return new Promise((resolve, reject) => {
+ const proc = spawn(binaryPath, ['--version'])
+ proc.stdout.on('data', (data) => {
+ if (versionRegex.test(data)) {
+ resolve(true)
+ }
+ })
+
+ proc.on('close', () => {
+ resolve(false)
+ })
+ })
+ }
+
+ @PerformanceTester.Measure(PERFORMANCE_SDK_EVENTS.PERCY_EVENTS.DOWNLOAD)
+ async download(destParentDir: string, response?: Response): Promise {
+ if (!await this.#checkPath(destParentDir)){
+ await fsp.mkdir(destParentDir)
+ }
+ const binaryName = this.#binaryName
+ const zipFilePath = path.join(destParentDir, binaryName + '.zip')
+ const binaryPath = path.join(destParentDir, binaryName)
+ const downloadedFileStream = fs.createWriteStream(zipFilePath)
+
+ if (!response) {
+ response = await fetch(this.#httpPath as unknown as URL)
+ }
+ const newETag = response.headers.get('eTag')
+ if (newETag) {
+ await this.#saveETag(destParentDir, newETag)
+ }
+ // @ts-expect-error stream type
+ await pipeline(response.body as unknown as RequestInit, downloadedFileStream)
+
+ return new Promise((resolve, reject) => {
+ yauzl.open(zipFilePath, { lazyEntries: true }, function (err, zipfile) {
+ if (err) {
+ return reject(err)
+ }
+ zipfile.readEntry()
+ zipfile.on('entry', (entry) => {
+ if (/\/$/.test(entry.fileName)) {
+ // Directory file names end with '/'.
+ zipfile.readEntry()
+ } else {
+ // file entry
+ const writeStream = fs.createWriteStream(
+ path.join(destParentDir, entry.fileName)
+ )
+ zipfile.openReadStream(entry, function (zipErr, readStream) {
+ if (zipErr) {
+ reject(err)
+ }
+ readStream.on('end', function () {
+ writeStream.close()
+ zipfile.readEntry()
+ })
+ readStream.pipe(writeStream)
+ })
+
+ if (entry.fileName === binaryName) {
+ zipfile.close()
+ }
+ }
+ })
+
+ zipfile.on('error', (zipErr) => {
+ reject(zipErr)
+ })
+
+ zipfile.once('end', () => {
+ fs.chmod(binaryPath, '0755', function (zipErr: Error) {
+ if (zipErr) {
+ reject(zipErr)
+ }
+ resolve(binaryPath)
+ })
+ zipfile.close()
+ })
+ })
+ })
+ }
+}
+
+export default PercyBinary
diff --git a/packages/browserstack-service/src/Percy/PercyCaptureMap.ts b/packages/browserstack-service/src/Percy/PercyCaptureMap.ts
new file mode 100644
index 0000000..8e6671d
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/PercyCaptureMap.ts
@@ -0,0 +1,50 @@
+/*
+ * Maintains a counter for each driver to get consistent and
+ * unique screenshot names for percy
+ */
+
+interface Map {
+ [key: string]: Record
+}
+
+class PercyCaptureMap {
+ #map: Map = {}
+
+ increment(sessionName: string, eventName: string) {
+ if (!this.#map[sessionName]) {
+ this.#map[sessionName] = {}
+ }
+
+ if (!this.#map[sessionName][eventName]) {
+ this.#map[sessionName][eventName] = 0
+ }
+
+ this.#map[sessionName][eventName]++
+ }
+
+ decrement(sessionName: string, eventName: string) {
+ if (!this.#map[sessionName] || !this.#map[sessionName][eventName]) {
+ return
+ }
+
+ this.#map[sessionName][eventName]--
+ }
+
+ getName(sessionName: string, eventName: string) {
+ return `${sessionName}-${eventName}-${this.get(sessionName, eventName)}`
+ }
+
+ get(sessionName: string, eventName: string) {
+ if (!this.#map[sessionName]) {
+ return 0
+ }
+
+ if (!this.#map[sessionName][eventName]) {
+ return 0
+ }
+
+ return this.#map[sessionName][eventName] - 1
+ }
+}
+
+export default PercyCaptureMap
diff --git a/packages/browserstack-service/src/Percy/PercyHelper.ts b/packages/browserstack-service/src/Percy/PercyHelper.ts
new file mode 100644
index 0000000..384bb52
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/PercyHelper.ts
@@ -0,0 +1,80 @@
+// ======= Percy helper methods start =======
+
+import type { Capabilities } from '@wdio/types'
+import type { BrowserstackConfig, UserConfig } from '../types.js'
+
+import type { Options } from '@wdio/types'
+
+import { PercyLogger } from './PercyLogger.js'
+import Percy from './Percy.js'
+
+export const startPercy = async (options: BrowserstackConfig & Options.Testrunner, config: Options.Testrunner, bsConfig: UserConfig): Promise => {
+ PercyLogger.debug('Starting percy')
+ const percy = new Percy(options, config, bsConfig)
+ const response = await percy.start()
+ if (response) {
+ return percy
+ }
+ return undefined
+}
+
+export const stopPercy = async (percy: Percy) => {
+ PercyLogger.debug('Stopping percy')
+ return percy.stop()
+}
+
+export const getBestPlatformForPercySnapshot = (capabilities?: Capabilities.TestrunnerCapabilities) => {
+ try {
+ const percyBrowserPreference = { 'chrome': 0, 'firefox': 1, 'edge': 2, 'safari': 3 }
+
+ let bestPlatformCaps: WebdriverIO.Capabilities | undefined
+ let bestBrowser: string | undefined
+
+ if (Array.isArray(capabilities)) {
+ capabilities
+ .flatMap((c) => {
+ if ('alwaysMatch' in c) {
+ return c.alwaysMatch as WebdriverIO.Capabilities
+ }
+
+ if (Object.values(c).length > 0 && Object.values(c).every(c => typeof c === 'object' && c.capabilities)) {
+ return Object.values(c).map((o) => o.capabilities) as WebdriverIO.Capabilities[]
+ }
+ return c as WebdriverIO.Capabilities
+ }).forEach((capability: WebdriverIO.Capabilities) => {
+ let currBrowserName = capability.browserName
+ if (capability['bstack:options']) {
+ currBrowserName = capability['bstack:options'].browserName || currBrowserName
+ }
+ // @ts-expect-error
+ if (!bestBrowser || !bestPlatformCaps || (bestPlatformCaps.deviceName || bestPlatformCaps['bstack:options']?.deviceName)) {
+ bestBrowser = currBrowserName
+ bestPlatformCaps = capability
+ } else if (currBrowserName && percyBrowserPreference[currBrowserName.toLowerCase() as keyof typeof percyBrowserPreference] < percyBrowserPreference[bestBrowser.toLowerCase() as keyof typeof percyBrowserPreference]) {
+ bestBrowser = currBrowserName
+ bestPlatformCaps = capability
+ }
+ })
+ return bestPlatformCaps
+ } else if (typeof capabilities === 'object') {
+ Object.entries(capabilities as Capabilities.RequestedMultiremoteCapabilities).forEach(([, caps]) => {
+ let currBrowserName = (caps.capabilities as WebdriverIO.Capabilities).browserName
+ if ((caps.capabilities as WebdriverIO.Capabilities)['bstack:options']) {
+ currBrowserName = (caps.capabilities as WebdriverIO.Capabilities)['bstack:options']?.browserName || currBrowserName
+ }
+ // @ts-expect-error
+ if (!bestBrowser || !bestPlatformCaps || (bestPlatformCaps.deviceName || bestPlatformCaps['bstack:options']?.deviceName)) {
+ bestBrowser = currBrowserName
+ bestPlatformCaps = (caps.capabilities as WebdriverIO.Capabilities)
+ } else if (currBrowserName && percyBrowserPreference[currBrowserName.toLowerCase() as keyof typeof percyBrowserPreference] < percyBrowserPreference[bestBrowser.toLowerCase() as keyof typeof percyBrowserPreference]) {
+ bestBrowser = currBrowserName
+ bestPlatformCaps = (caps.capabilities as WebdriverIO.Capabilities)
+ }
+ })
+ return bestPlatformCaps
+ }
+ } catch (err) {
+ PercyLogger.error(`Error while trying to determine best platform for Percy snapshot ${err}`)
+ return null
+ }
+}
diff --git a/packages/browserstack-service/src/Percy/PercyLogger.ts b/packages/browserstack-service/src/Percy/PercyLogger.ts
new file mode 100644
index 0000000..0435512
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/PercyLogger.ts
@@ -0,0 +1,78 @@
+import path from 'node:path'
+import fs from 'node:fs'
+import chalk from 'chalk'
+
+import logger from '@wdio/logger'
+
+import { PERCY_LOGS_FILE } from '../constants.js'
+import { COLORS } from '../util.js'
+
+const log = logger('@wdio/browserstack-service')
+
+export class PercyLogger {
+ public static logFilePath = path.join(process.cwd(), PERCY_LOGS_FILE)
+ private static logFolderPath = path.join(process.cwd(), 'logs')
+ private static logFileStream: fs.WriteStream | null
+
+ static logToFile(logMessage: string, logLevel: string) {
+ try {
+ if (!this.logFileStream) {
+ if (!fs.existsSync(this.logFolderPath)){
+ fs.mkdirSync(this.logFolderPath)
+ }
+ this.logFileStream = fs.createWriteStream(this.logFilePath, { flags: 'a' })
+ }
+ if (this.logFileStream && this.logFileStream.writable) {
+ this.logFileStream.write(this.formatLog(logMessage, logLevel))
+ }
+ } catch (error) {
+ log.debug(`Failed to log to file. Error ${error}`)
+ }
+ }
+
+ private static formatLog(logMessage: string, level: string) {
+ return `${chalk.gray(new Date().toISOString())} ${chalk[COLORS[level]](level.toUpperCase())} ${chalk.whiteBright('@wdio/browserstack-service')} ${logMessage}\n`
+ }
+
+ public static info(message: string) {
+ this.logToFile(message, 'info')
+ log.info(message)
+ }
+
+ public static error(message: string) {
+ this.logToFile(message, 'error')
+ log.error(message)
+ }
+
+ public static debug(message: string, param?: unknown) {
+ this.logToFile(message, 'debug')
+ if (param) {
+ log.debug(message, param)
+ } else {
+ log.debug(message)
+ }
+ }
+
+ public static warn(message: string) {
+ this.logToFile(message, 'warn')
+ log.warn(message)
+ }
+
+ public static trace(message: string) {
+ this.logToFile(message, 'trace')
+ log.trace(message)
+ }
+
+ public static clearLogger() {
+ if (this.logFileStream) {
+ this.logFileStream.end()
+ }
+ this.logFileStream = null
+ }
+
+ public static clearLogFile() {
+ if (fs.existsSync(this.logFilePath)) {
+ fs.truncateSync(this.logFilePath)
+ }
+ }
+}
diff --git a/packages/browserstack-service/src/Percy/PercySDK.ts b/packages/browserstack-service/src/Percy/PercySDK.ts
new file mode 100644
index 0000000..9f91013
--- /dev/null
+++ b/packages/browserstack-service/src/Percy/PercySDK.ts
@@ -0,0 +1,97 @@
+import InsightsHandler from '../insights-handler.js'
+import TestReporter from '../reporter.js'
+import { PercyLogger } from './PercyLogger.js'
+import { isUndefined } from '../util.js'
+import { createRequire } from 'node:module'
+
+const require = createRequire(import.meta.url)
+
+const tryRequire = function (pkg: string, fallback: unknown) {
+ try {
+ const mod = require(pkg)
+ if (mod && typeof mod === 'object' && 'default' in mod) {
+ return (mod as { default: unknown }).default
+ }
+ return mod
+ } catch {
+ return fallback
+ }
+}
+
+const percySnapshot = tryRequire('@percy/selenium-webdriver', null)
+
+const percyAppScreenshot = tryRequire('@percy/appium-app', {})
+
+/* eslint-disable @typescript-eslint/no-unused-vars */
+let snapshotHandler = (...args: unknown[]) => {
+ PercyLogger.error('Unsupported driver for percy')
+}
+if (percySnapshot) {
+ snapshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, snapshotName: string, options?: { [key: string]: unknown }) => {
+ if (process.env.PERCY_SNAPSHOT === 'true') {
+ let { name, uuid } = InsightsHandler.currentTest
+ if (isUndefined(name)) {
+ ({ name, uuid } = TestReporter.currentTest)
+ }
+ options ||= {}
+ options = {
+ ...options,
+ testCase: name || ''
+ }
+ return percySnapshot(browser, snapshotName, options)
+ }
+ }
+}
+export const snapshot = snapshotHandler
+
+/*
+This is a helper method which appends some internal fields
+to the options object being sent to Percy methods
+*/
+const screenshotHelper = (type: string, driverOrName: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, nameOrOptions?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
+ let { name, uuid } = InsightsHandler.currentTest
+ if (isUndefined(name)) {
+ ({ name, uuid } = TestReporter.currentTest)
+ }
+ if (!driverOrName || typeof driverOrName === 'string') {
+ nameOrOptions ||= {}
+ if (typeof nameOrOptions === 'object') {
+ nameOrOptions = {
+ ...nameOrOptions,
+ testCase: name || ''
+ }
+ }
+ } else {
+ options ||= {}
+ options = {
+ ...options,
+ testCase: name || ''
+ }
+ }
+ if (type === 'app') {
+ return percyAppScreenshot(driverOrName, nameOrOptions, options)
+ }
+ return percySnapshot.percyScreenshot(driverOrName, nameOrOptions, options)
+}
+
+/* eslint-disable @typescript-eslint/no-unused-vars */
+let screenshotHandler = async (...args: unknown[]) => {
+ PercyLogger.error('Unsupported driver for percy')
+}
+if (percySnapshot && percySnapshot.percyScreenshot) {
+ screenshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, screenshotName?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
+ return screenshotHelper('web', browser, screenshotName, options)
+ }
+}
+export const screenshot = screenshotHandler
+
+/* eslint-disable @typescript-eslint/no-unused-vars */
+let screenshotAppHandler = async (...args: unknown[]) => {
+ PercyLogger.error('Unsupported driver for percy')
+}
+if (percyAppScreenshot) {
+ screenshotAppHandler = (driverOrName: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, nameOrOptions?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
+ return screenshotHelper('app', driverOrName, nameOrOptions, options)
+ }
+}
+export const screenshotApp = screenshotAppHandler
\ No newline at end of file
diff --git a/packages/browserstack-service/src/accessibility-handler.ts b/packages/browserstack-service/src/accessibility-handler.ts
new file mode 100644
index 0000000..76ae832
--- /dev/null
+++ b/packages/browserstack-service/src/accessibility-handler.ts
@@ -0,0 +1,525 @@
+///
+import util from 'node:util'
+
+import type { Capabilities, Frameworks, Options } from '@wdio/types'
+
+import type { BrowserstackConfig, BrowserstackOptions } from './types.js'
+
+import type { ITestCaseHookParameter } from './cucumber-types.js'
+
+import Listener from './testOps/listener.js'
+
+// Define better types for accessibility
+interface PlatformA11yMeta {
+ browser_name?: string
+ browser_version?: string
+ device?: string
+ platform?: string
+ [key: string]: unknown
+}
+
+interface AccessibilityOptions {
+ includeIssueType?: string[]
+ excludeIssueType?: string[]
+ [key: string]: unknown
+}
+
+interface TestMetadata {
+ [testId: string]: {
+ scanTestForAccessibility?: boolean
+ accessibilityScanStarted?: boolean
+ [key: string]: unknown
+ }
+}
+
+interface A11yScanSessionMap {
+ [sessionId: string]: boolean
+}
+
+interface CommandInfo {
+ name: string
+ class?: string
+ [key: string]: unknown
+}
+
+interface TestExtensionData {
+ thTestRunUuid?: string
+ thBuildUuid?: string
+ thJwtToken?: string
+ [key: string]: unknown
+}
+
+import {
+ getA11yResultsSummary,
+ getAppA11yResultsSummary,
+ getA11yResults,
+ performA11yScan,
+ getUniqueIdentifier,
+ getUniqueIdentifierForCucumber,
+ isAccessibilityAutomationSession,
+ isAppAccessibilityAutomationSession,
+ isBrowserstackSession,
+ o11yClassErrorHandler,
+ shouldScanTestForAccessibility,
+ validateCapsWithA11y,
+ shouldAddServiceVersion,
+ validateCapsWithNonBstackA11y,
+ isTrue,
+ validateCapsWithAppA11y,
+ getAppA11yResults,
+ executeAccessibilityScript,
+ isFalse
+} from './util.js'
+import accessibilityScripts from './scripts/accessibility-scripts.js'
+import PerformanceTester from './instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from './instrumentation/performance/constants.js'
+
+import { BStackLogger } from './bstackLogger.js'
+
+class _AccessibilityHandler {
+ private _platformA11yMeta: PlatformA11yMeta
+ private _caps: Capabilities.ResolvedTestrunnerCapabilities
+ private _suiteFile?: string
+ private _accessibility?: boolean
+ private _turboscale?: boolean
+ private _options: BrowserstackConfig & BrowserstackOptions
+ private _config: Options.Testrunner
+ private _accessibilityOptions?: AccessibilityOptions
+ private _autoScanning: boolean = true
+ private _testIdentifier: string | null = null
+ private _testMetadata: TestMetadata = {}
+ private static _a11yScanSessionMap: A11yScanSessionMap = {}
+ private _sessionId: string | null = null
+ private listener = Listener.getInstance()
+
+ constructor (
+ private _browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser,
+ _capabilities: Capabilities.ResolvedTestrunnerCapabilities,
+ _options : BrowserstackConfig & BrowserstackOptions,
+ private isAppAutomate: boolean,
+ _config : Options.Testrunner,
+ private _framework?: string,
+ _accessibilityAutomation?: boolean | string,
+ _turboscale?: boolean | string,
+ _accessibilityOpts?: AccessibilityOptions
+ ) {
+ const caps = (this._browser as WebdriverIO.Browser).capabilities as WebdriverIO.Capabilities
+
+ this._platformA11yMeta = {
+ browser_name: caps?.browserName,
+ // @ts-expect-error invalid caps property
+ browser_version: caps?.browserVersion || (caps as WebdriverIO.Capabilities)?.version || 'latest',
+ platform_name: caps?.platformName,
+ platform_version: this._getCapabilityValue(caps, 'appium:platformVersion', 'platformVersion'),
+ os_name: this._getCapabilityValue(_capabilities, 'os', 'os'),
+ os_version: this._getCapabilityValue(_capabilities, 'osVersion', 'os_version')
+ }
+
+ this._caps = _capabilities
+ this._accessibility = isTrue(_accessibilityAutomation)
+ this._accessibilityOptions = _accessibilityOpts
+ this._autoScanning = !isFalse(this._accessibilityOptions?.autoScanning)
+ this._options = _options
+ this._config= _config
+ this._turboscale = isTrue(_turboscale)
+ }
+
+ setSuiteFile(filename: string) {
+ this._suiteFile = filename
+ }
+
+ _getCapabilityValue(caps: Capabilities.ResolvedTestrunnerCapabilities, capType: string, legacyCapType: string) {
+ if (caps) {
+ if (capType === 'accessibility') {
+ if ((caps as WebdriverIO.Capabilities)['bstack:options'] && (isTrue((caps as WebdriverIO.Capabilities)['bstack:options']?.accessibility))) {
+ return (caps as WebdriverIO.Capabilities)['bstack:options']?.accessibility
+ } else if (isTrue((caps as WebdriverIO.Capabilities)['browserstack.accessibility'])) {
+ return (caps as WebdriverIO.Capabilities)['browserstack.accessibility']
+ }
+ } else if (capType === 'deviceName') {
+ if ((caps as WebdriverIO.Capabilities)['bstack:options'] && (caps as WebdriverIO.Capabilities)['bstack:options']?.deviceName) {
+ return (caps as WebdriverIO.Capabilities)['bstack:options']?.deviceName
+ } else if ((caps as WebdriverIO.Capabilities)['bstack:options'] && (caps as WebdriverIO.Capabilities)['bstack:options']?.device) {
+ return (caps as WebdriverIO.Capabilities)['bstack:options']?.device
+ } else if ((caps as WebdriverIO.Capabilities)['appium:deviceName']) {
+ return (caps as WebdriverIO.Capabilities)['appium:deviceName']
+ }
+ } else if (capType === 'goog:chromeOptions' && (caps as WebdriverIO.Capabilities)['goog:chromeOptions']) {
+ return (caps as WebdriverIO.Capabilities)['goog:chromeOptions']
+ } else {
+ const bstackOptions = (caps as WebdriverIO.Capabilities)['bstack:options']
+ if ( bstackOptions && bstackOptions?.[capType as keyof Capabilities.BrowserStackCapabilities]) {
+ return bstackOptions?.[capType as keyof Capabilities.BrowserStackCapabilities]
+ } else if ((caps as WebdriverIO.Capabilities)[legacyCapType as keyof WebdriverIO.Capabilities]) {
+ return (caps as WebdriverIO.Capabilities)[legacyCapType as keyof WebdriverIO.Capabilities]
+ }
+ }
+ }
+ }
+
+ async before(sessionId: string) {
+ PerformanceTester.start(PERFORMANCE_SDK_EVENTS.CONFIG_EVENTS.ACCESSIBILITY)
+
+ this._sessionId = sessionId
+ this._accessibility = isTrue(this._getCapabilityValue(this._caps, 'accessibility', 'browserstack.accessibility'))
+
+ //checks for running ALLY on non-bstack infra
+ if (
+ isAccessibilityAutomationSession(this._accessibility) &&
+ (
+ this._turboscale ||
+ !shouldAddServiceVersion(this._config, this._options.testObservability)
+ ) &&
+ validateCapsWithNonBstackA11y(
+ this._platformA11yMeta.browser_name as string,
+ this._platformA11yMeta?.browser_version as string
+ )
+ ){
+ this._accessibility = true
+ } else {
+ if (isAccessibilityAutomationSession(this._accessibility) && !this.isAppAutomate) {
+ const deviceName = this._getCapabilityValue(this._caps, 'deviceName', 'device')
+ const chromeOptions = this._getCapabilityValue(this._caps, 'goog:chromeOptions', '') as Capabilities.ChromeOptions
+
+ this._accessibility = validateCapsWithA11y(deviceName as string, this._platformA11yMeta as unknown as Record, chromeOptions)
+ }
+ if (isAppAccessibilityAutomationSession(this._accessibility, this.isAppAutomate)) {
+ this._accessibility = validateCapsWithAppA11y(this._platformA11yMeta)
+ }
+ }
+
+ // Safely add accessibility methods to browser instance with proper typing
+ const browserWithA11y = this._browser as WebdriverIO.Browser & {
+ getAccessibilityResultsSummary: () => Promise>,
+ getAccessibilityResults: () => Promise>>,
+ performScan: () => Promise | undefined>,
+ startA11yScanning: () => Promise,
+ stopA11yScanning: () => Promise
+ }
+
+ browserWithA11y.getAccessibilityResultsSummary = async () => {
+ if (isAppAccessibilityAutomationSession(this._accessibility, this.isAppAutomate)) {
+ return await getAppA11yResultsSummary(this.isAppAutomate, (this._browser as WebdriverIO.Browser), isBrowserstackSession(this._browser), this._accessibility, this._sessionId)
+ }
+ return await getA11yResultsSummary(this.isAppAutomate, (this._browser as WebdriverIO.Browser), isBrowserstackSession(this._browser), this._accessibility)
+ }
+
+ browserWithA11y.getAccessibilityResults = async () => {
+ if (isAppAccessibilityAutomationSession(this._accessibility, this.isAppAutomate)) {
+ return await getAppA11yResults(this.isAppAutomate, (this._browser as WebdriverIO.Browser), isBrowserstackSession(this._browser), this._accessibility, this._sessionId)
+ }
+ return await getA11yResults(this.isAppAutomate, (this._browser as WebdriverIO.Browser), isBrowserstackSession(this._browser), this._accessibility)
+ }
+
+ browserWithA11y.performScan = async () => {
+ const results = await performA11yScan(this.isAppAutomate, (this._browser as WebdriverIO.Browser), isBrowserstackSession(this._browser), this._accessibility)
+ if (results) {
+ this._testMetadata[this._testIdentifier as string] = {
+ scanTestForAccessibility : true,
+ accessibilityScanStarted : true
+ }
+ }
+ await this._setAnnotation('Accessibility scanning was triggered manually')
+ return results
+ }
+
+ browserWithA11y.startA11yScanning = async () => {
+ if (this._testIdentifier === null){
+ BStackLogger.warn('Accessibility scanning cannot be started from outside the test')
+ return
+ }
+ AccessibilityHandler._a11yScanSessionMap[sessionId] = true
+ this._testMetadata[this._testIdentifier as string] = {
+ scanTestForAccessibility : true,
+ accessibilityScanStarted : true
+ }
+ await this._setAnnotation('Accessibility scanning has started')
+ }
+
+ browserWithA11y.stopA11yScanning = async () => {
+ if (this._testIdentifier === null){
+ BStackLogger.warn('Accessibility scanning cannot be stopped from outside the test')
+ return
+ }
+ AccessibilityHandler._a11yScanSessionMap[sessionId] = false
+ await this._setAnnotation('Accessibility scanning has stopped')
+ }
+
+ if (!this._accessibility) {
+ return
+ }
+ if (!('overwriteCommand' in this._browser && Array.isArray(accessibilityScripts.commandsToWrap))) {
+ return
+ }
+
+ accessibilityScripts.commandsToWrap
+ .filter((command) => command.name && command.class)
+ .forEach((command) => {
+ const browser = this._browser as WebdriverIO.Browser
+ try {
+ // element commands aren't on browser; use orig when present, otherwise rely on overwriteCommand's origFunction
+ const orig = browser[command.name as keyof WebdriverIO.Browser]
+ const prevImpl = orig ? orig.bind(browser) : undefined
+ // @ts-expect-error fix type
+ browser.overwriteCommand(command.name, this.commandWrapper.bind(this, command, prevImpl), command.class === 'Element')
+ } catch (error) {
+ BStackLogger.debug(`Exception in overwrite command ${command.name} - ${error}`)
+ }
+ })
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.CONFIG_EVENTS.ACCESSIBILITY)
+
+ }
+
+ async beforeTest (suiteTitle: string | undefined, test: Frameworks.Test) {
+ try {
+ if (
+ this._framework !== 'mocha' ||
+ !this.shouldRunTestHooks(this._browser, this._accessibility)
+ ) {
+ /* This is to be used when test events are sent */
+ Listener.setTestRunAccessibilityVar(false)
+ return
+ }
+
+ // @ts-expect-error fix type
+ const shouldScanTest = this._autoScanning && shouldScanTestForAccessibility(suiteTitle, test.title, this._accessibilityOptions)
+ const testIdentifier = this.getIdentifier(test)
+ this._testIdentifier = testIdentifier
+
+ if (this._sessionId) {
+ /* For case with multiple tests under one browser, before hook of 2nd test should change this map value */
+ AccessibilityHandler._a11yScanSessionMap[this._sessionId] = shouldScanTest
+ }
+
+ /* This is to be used when test events are sent */
+ Listener.setTestRunAccessibilityVar(this._accessibility && shouldScanTest)
+
+ this._testMetadata[testIdentifier] = {
+ scanTestForAccessibility : shouldScanTest,
+ accessibilityScanStarted : true
+ }
+
+ this._testMetadata[testIdentifier].accessibilityScanStarted = shouldScanTest
+
+ if (shouldScanTest) {
+ BStackLogger.info('Automate test case execution has started.')
+ }
+ } catch (error) {
+ BStackLogger.error(`Exception in starting accessibility automation scan for this test case ${error}`)
+ }
+ }
+
+ async afterTest (suiteTitle: string | undefined, test: Frameworks.Test) {
+ BStackLogger.debug('Accessibility after test hook. Before sending test stop event')
+ if (
+ this._framework !== 'mocha' ||
+ !this.shouldRunTestHooks(this._browser, this._accessibility)
+ ) {
+ return
+ }
+
+ try {
+ const testIdentifier = this.getIdentifier(test)
+ const accessibilityScanStarted = this._testMetadata[testIdentifier]?.accessibilityScanStarted
+ const shouldScanTestForAccessibility = this._testMetadata[testIdentifier]?.scanTestForAccessibility
+
+ if (!accessibilityScanStarted) {
+ return
+ }
+
+ if (shouldScanTestForAccessibility) {
+ BStackLogger.info('Automate test case execution has ended. Processing for accessibility testing is underway. ')
+
+ const dataForExtension = {
+ 'thTestRunUuid': process.env.TEST_ANALYTICS_ID,
+ 'thBuildUuid': process.env.BROWSERSTACK_TESTHUB_UUID,
+ 'thJwtToken': process.env.BROWSERSTACK_TESTHUB_JWT
+ }
+
+ await this.sendTestStopEvent((this._browser as WebdriverIO.Browser), dataForExtension)
+
+ BStackLogger.info('Accessibility testing for this test case has ended.')
+ }
+ } catch (error) {
+ BStackLogger.error(`Accessibility results could not be processed for the test case ${test.title}. Error : ${error}`)
+ }
+ }
+
+ /**
+ * Cucumber Only
+ */
+ async beforeScenario (world: ITestCaseHookParameter) {
+ const pickleData = world.pickle
+ const gherkinDocument = world.gherkinDocument
+ const featureData = gherkinDocument.feature
+ const uniqueId = getUniqueIdentifierForCucumber(world)
+ this._testIdentifier = uniqueId
+ if (!this.shouldRunTestHooks(this._browser, this._accessibility)) {
+ /* This is to be used when test events are sent */
+ Listener.setTestRunAccessibilityVar(false)
+ return
+ }
+
+ try {
+ // @ts-expect-error fix type
+ const shouldScanScenario = this._autoScanning && shouldScanTestForAccessibility(featureData?.name, pickleData.name, this._accessibilityOptions, world, true)
+ this._testMetadata[uniqueId] = {
+ scanTestForAccessibility : shouldScanScenario,
+ accessibilityScanStarted : true
+ }
+
+ this._testMetadata[uniqueId].accessibilityScanStarted = shouldScanScenario
+ if (this._sessionId) {
+ /* For case with multiple tests under one browser, before hook of 2nd test should change this map value */
+ AccessibilityHandler._a11yScanSessionMap[this._sessionId] = shouldScanScenario
+ }
+
+ /* This is to be used when test events are sent */
+ Listener.setTestRunAccessibilityVar(this._accessibility && shouldScanScenario)
+
+ if (shouldScanScenario) {
+ BStackLogger.info('Automate test case execution has started.')
+ }
+ } catch (error) {
+ BStackLogger.error(`Exception in starting accessibility automation scan for this test case ${error}`)
+ }
+ }
+
+ async afterScenario (world: ITestCaseHookParameter) {
+ BStackLogger.debug('Accessibility after scenario hook. Before sending test stop event')
+ if (!this.shouldRunTestHooks(this._browser, this._accessibility)) {
+ return
+ }
+
+ const pickleData = world.pickle
+ try {
+ const uniqueId = getUniqueIdentifierForCucumber(world)
+ const accessibilityScanStarted = this._testMetadata[uniqueId]?.accessibilityScanStarted
+ const shouldScanTestForAccessibility = this._testMetadata[uniqueId]?.scanTestForAccessibility
+
+ if (!accessibilityScanStarted) {
+ return
+ }
+
+ if (shouldScanTestForAccessibility) {
+ BStackLogger.info('Automate test case execution has ended. Processing for accessibility testing is underway. ')
+
+ const dataForExtension = {
+ 'thTestRunUuid': process.env.TEST_ANALYTICS_ID,
+ 'thBuildUuid': process.env.BROWSERSTACK_TESTHUB_UUID,
+ 'thJwtToken': process.env.BROWSERSTACK_TESTHUB_JWT
+ }
+
+ await this.sendTestStopEvent(( this._browser as WebdriverIO.Browser), dataForExtension)
+
+ BStackLogger.info('Accessibility testing for this test case has ended.')
+ }
+ } catch (error) {
+ BStackLogger.error(`Accessibility results could not be processed for the test case ${pickleData.name}. Error : ${error}`)
+ }
+ }
+
+ /*
+ * private methods
+ */
+
+ private async commandWrapper (command: CommandInfo, prevImpl: Function, origFunction: Function, ...args: unknown[]) {
+ if (
+ this._sessionId && AccessibilityHandler._a11yScanSessionMap[this._sessionId] &&
+ (
+ !command.name.includes('execute') ||
+ !AccessibilityHandler.shouldPatchExecuteScript(args.length ? args[0] as string : null)
+ )
+ ) {
+ BStackLogger.debug(`Performing scan for ${command.class} ${command.name}`)
+ await performA11yScan(this.isAppAutomate, this._browser, true, true, command.name)
+ }
+ const impl = prevImpl || origFunction
+ return impl(...args)
+ }
+
+ private async sendTestStopEvent(browser: WebdriverIO.Browser, dataForExtension: TestExtensionData) {
+ BStackLogger.debug('Performing scan before saving results')
+ if (AccessibilityHandler._a11yScanSessionMap[this._sessionId as string]) {
+ await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.PERFORM_SCAN, async () => {
+ await performA11yScan(this.isAppAutomate, browser, true, true)
+ }, { command: 'afterTest' })()
+ }
+
+ if (isAppAccessibilityAutomationSession(this._accessibility, this.isAppAutomate)) {
+ return
+ }
+
+ await PerformanceTester.measureWrapper(PERFORMANCE_SDK_EVENTS.A11Y_EVENTS.SAVE_RESULTS, async () => {
+ if (accessibilityScripts.saveTestResults) {
+ const results: unknown = await executeAccessibilityScript(browser, accessibilityScripts.saveTestResults, dataForExtension)
+ BStackLogger.debug(util.format(results as string))
+ } else {
+ BStackLogger.error('saveTestResults script is null or undefined')
+ }
+ })()
+
+ }
+
+ private getIdentifier (test: Frameworks.Test | ITestCaseHookParameter) {
+ if ('pickle' in test) {
+ return getUniqueIdentifierForCucumber(test)
+ }
+ return getUniqueIdentifier(test, this._framework)
+ }
+
+ private shouldRunTestHooks(browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | null, isAccessibility?: boolean | string) {
+ if (!browser) {
+ return false
+ }
+ return isAccessibilityAutomationSession(isAccessibility)
+ }
+
+ private async checkIfPageOpened(browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, testIdentifier: string, shouldScanTest?: boolean) {
+ let pageOpen = false
+ this._testMetadata[testIdentifier] = {
+ scanTestForAccessibility : shouldScanTest,
+ accessibilityScanStarted : true
+ }
+
+ try {
+ const currentURL = await (browser as WebdriverIO.Browser).getUrl()
+ const url = new URL(currentURL)
+ pageOpen = url?.protocol === 'http:' || url?.protocol === 'https:'
+ } catch {
+ pageOpen = false
+ }
+
+ return pageOpen
+ }
+
+ private static shouldPatchExecuteScript(script: string | null): boolean {
+ if (!script || typeof script !== 'string') {
+ return true
+ }
+
+ return (
+ script.toLowerCase().indexOf('browserstack_executor') !== -1 ||
+ script.toLowerCase().indexOf('browserstack_accessibility_automation_script') !== -1
+ )
+ }
+
+ private async _setAnnotation(message: string) {
+ if (this._accessibility && isBrowserstackSession(this._browser)) {
+ await (this._browser as WebdriverIO.Browser).executeScript(`browserstack_executor: ${JSON.stringify({
+ action: 'annotate',
+ arguments: {
+ data: message,
+ level: 'info'
+ }
+ })}`, [])
+ }
+ }
+}
+
+// https://github.com/microsoft/TypeScript/issues/6543
+const AccessibilityHandler: typeof _AccessibilityHandler = o11yClassErrorHandler(_AccessibilityHandler)
+type AccessibilityHandler = _AccessibilityHandler
+
+export default AccessibilityHandler
+
diff --git a/packages/browserstack-service/src/ai-handler.ts b/packages/browserstack-service/src/ai-handler.ts
new file mode 100644
index 0000000..2664ed9
--- /dev/null
+++ b/packages/browserstack-service/src/ai-handler.ts
@@ -0,0 +1,239 @@
+import path from 'node:path'
+import fs from 'node:fs'
+import url from 'node:url'
+import aiSDK from '@browserstack/ai-sdk-node'
+import { BStackLogger } from './bstackLogger.js'
+import { TCG_URL, TCG_INFO, SUPPORTED_BROWSERS_FOR_AI, BSTACK_SERVICE_VERSION, BSTACK_TCG_AUTH_RESULT } from './constants.js'
+import { handleHealingInstrumentation } from './instrumentation/funnelInstrumentation.js'
+
+import type { Capabilities } from '@wdio/types'
+import type BrowserStackConfig from './config.js'
+import type { Options } from '@wdio/types'
+import type { BrowserstackHealing } from '@browserstack/ai-sdk-node'
+import { getBrowserStackUserAndKey, isBrowserstackInfra } from './util.js'
+import type { BrowserstackOptions } from './types.js'
+import PerformanceTester from './instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from './instrumentation/performance/constants.js'
+
+class AiHandler {
+ authResult: BrowserstackHealing.InitSuccessResponse | BrowserstackHealing.InitErrorResponse
+ wdioBstackVersion: string
+ constructor() {
+ this.authResult = JSON.parse(process.env[BSTACK_TCG_AUTH_RESULT] || '{}')
+ this.wdioBstackVersion = BSTACK_SERVICE_VERSION
+ }
+
+ async authenticateUser(user: string, key: string) {
+ return await aiSDK.BrowserstackHealing.init(key, user, TCG_URL, this.wdioBstackVersion)
+ }
+
+ updateCaps(
+ authResult: BrowserstackHealing.InitSuccessResponse | BrowserstackHealing.InitErrorResponse,
+ options: BrowserstackOptions,
+ caps: Array | Capabilities.ResolvedTestrunnerCapabilities
+ ) {
+ const installExtCondition = authResult.isAuthenticated === true && (authResult.defaultLogDataEnabled === true || options.selfHeal === true)
+ if (installExtCondition){
+ if (Array.isArray(caps)) {
+ const newCaps= aiSDK.BrowserstackHealing.initializeCapabilities(caps[0])
+ caps[0] = newCaps
+ } else if (typeof caps === 'object') {
+ caps = aiSDK.BrowserstackHealing.initializeCapabilities(caps)
+ }
+ } else if (options.selfHeal === true) {
+ const healingWarnMessage = (authResult as aiSDK.BrowserstackHealing.InitErrorResponse).message
+ BStackLogger.warn(`Healing Auth failed. Disabling healing for this session. Reason: ${healingWarnMessage}`)
+ }
+
+ return caps
+ }
+
+ async setToken(sessionId: string, sessionToken: string){
+ await aiSDK.BrowserstackHealing.setToken(sessionId, sessionToken, TCG_URL)
+ }
+
+ async installFirefoxExtension(browser: WebdriverIO.Browser){
+ const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
+ const extensionPath = path.resolve(__dirname, aiSDK.BrowserstackHealing.getFirefoxAddonPath())
+ const extFile = fs.readFileSync(extensionPath)
+ await browser.installAddOn(extFile.toString('base64'), true)
+ }
+
+ async handleHealing(orginalFunc: (arg0: string, arg1: string) => { error?: string }, using: string, value: string, browser: WebdriverIO.Browser, options: BrowserstackOptions){
+ const sessionId = browser.sessionId
+
+ // a utility function to escape single and double quotes
+ const escapeString = (str: string) => str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t')
+
+ const tcgDetails = escapeString(JSON.stringify({
+ region: TCG_INFO.tcgRegion,
+ tcgUrls: {
+ [TCG_INFO.tcgRegion]: {
+ endpoint: TCG_INFO.tcgUrl.split('://')[1]
+ }
+ }
+ }))
+
+ const locatorType = escapeString(using)
+ const locatorValue = escapeString(value)
+
+ this.authResult = this.authResult as BrowserstackHealing.InitSuccessResponse
+
+ try {
+ const result = await orginalFunc(using, value)
+ if (!result.error) {
+ const script = await aiSDK.BrowserstackHealing.logData(locatorType, locatorValue, undefined, undefined, this.authResult.groupId, sessionId, undefined, tcgDetails)
+ if (script) {
+ await browser.execute(script)
+ }
+ return result
+ }
+ if (options.selfHeal === true && this.authResult.isHealingEnabled) {
+ BStackLogger.info('findElement failed, trying to heal')
+ PerformanceTester.start(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_STEP)
+ const script = await aiSDK.BrowserstackHealing.healFailure(locatorType, locatorValue, undefined, undefined, this.authResult.userId, this.authResult.groupId, sessionId, undefined, undefined, this.authResult.isGroupAIEnabled, tcgDetails)
+ if (script) {
+ await browser.execute(script)
+ PerformanceTester.start(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_GET_RESULT)
+ const tcgData = await aiSDK.BrowserstackHealing.pollResult(TCG_URL, sessionId, this.authResult.sessionToken)
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_GET_RESULT)
+ if (tcgData && tcgData.selector && tcgData.value){
+ const healedResult = await orginalFunc(tcgData.selector, tcgData.value)
+ BStackLogger.info('Healing worked, element found: ' + tcgData.selector + ': ' + tcgData.value)
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_STEP)
+ return healedResult.error ? result : healedResult
+ }
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_STEP, false, 'No healed result found')
+ } else {
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_STEP, false, 'No healing script generated')
+ }
+ }
+ } catch (err) {
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.AI_EVENTS.SELF_HEAL_STEP, false, String(err))
+ if (options.selfHeal === true) {
+ BStackLogger.warn('Something went wrong while healing. Disabling healing for this command')
+ } else {
+ BStackLogger.warn('Error in findElement: ' + err + 'using: ' + using + 'value: ' + value)
+ }
+ }
+ return await orginalFunc(using, value)
+ }
+
+ addMultiRemoteCaps (
+ authResult: BrowserstackHealing.InitSuccessResponse | BrowserstackHealing.InitErrorResponse,
+ config: Options.Testrunner,
+ browserStackConfig: BrowserStackConfig,
+ options: BrowserstackOptions,
+ caps: Capabilities.RequestedMultiremoteCapabilities,
+ browser: string
+ ) {
+ if ( caps[browser].capabilities &&
+ !(isBrowserstackInfra(caps[browser])) &&
+ SUPPORTED_BROWSERS_FOR_AI.includes((caps[browser]?.capabilities as WebdriverIO.Capabilities)?.browserName?.toLowerCase() || 'unknown browser')
+ ) {
+ const innerConfig = getBrowserStackUserAndKey(config, options)
+ if (innerConfig?.user && innerConfig.key) {
+ // @ts-expect-error fix type
+ handleHealingInstrumentation(authResult, browserStackConfig, options.selfHeal)
+ caps[browser].capabilities = this.updateCaps(authResult, options, caps[browser].capabilities as WebdriverIO.Capabilities) as WebdriverIO.Capabilities
+ }
+ }
+ }
+
+ handleMultiRemoteSetup(
+ authResult: BrowserstackHealing.InitSuccessResponse | BrowserstackHealing.InitErrorResponse,
+ config: Options.Testrunner,
+ browserStackConfig: BrowserStackConfig,
+ options: BrowserstackOptions,
+ caps: Capabilities.RequestedMultiremoteCapabilities,
+ ) {
+ const browserNames = Object.keys(caps)
+ for (let i = 0; i < browserNames.length; i++) {
+ const browser = browserNames[i]
+ this.addMultiRemoteCaps(authResult, config, browserStackConfig, options, caps, browser)
+ }
+ }
+
+ async setup(
+ config: Options.Testrunner,
+ browserStackConfig: BrowserStackConfig,
+ options: BrowserstackOptions,
+ caps: WebdriverIO.Capabilities,
+ isMultiremote: boolean
+ ) {
+ try {
+ const innerConfig = getBrowserStackUserAndKey(config, options)
+ if (innerConfig?.user && innerConfig.key) {
+ const authResult = await this.authenticateUser(innerConfig.user, innerConfig.key)
+ process.env[BSTACK_TCG_AUTH_RESULT] = JSON.stringify(authResult)
+ if (!isMultiremote && SUPPORTED_BROWSERS_FOR_AI.includes(caps.browserName?.toLowerCase() || 'unknown browser')) {
+
+ // @ts-expect-error fix type
+ handleHealingInstrumentation(authResult, browserStackConfig, options.selfHeal)
+ this.updateCaps(authResult, options, caps)
+
+ } else if (isMultiremote) {
+ this.handleMultiRemoteSetup(authResult, config, browserStackConfig, options, caps as unknown as Capabilities.RequestedMultiremoteCapabilities)
+ }
+ }
+
+ } catch (err) {
+ if (options.selfHeal === true) {
+ BStackLogger.warn(`Error while initiliazing Browserstack healing Extension ${err}`)
+ }
+ }
+
+ return caps
+ }
+
+ async handleSelfHeal(options: BrowserstackOptions, browser: WebdriverIO.Browser) {
+
+ if (SUPPORTED_BROWSERS_FOR_AI.includes((browser.capabilities as Capabilities.BrowserStackCapabilities)?.browserName?.toLowerCase() as string)) {
+ const authInfo = this.authResult as BrowserstackHealing.InitSuccessResponse
+
+ if (Object.keys(authInfo).length === 0 && options.selfHeal === true) {
+ BStackLogger.debug('TCG Auth result is empty')
+ return
+ }
+
+ const { isAuthenticated, sessionToken, defaultLogDataEnabled } = authInfo
+
+ if (isAuthenticated && (defaultLogDataEnabled === true || options.selfHeal === true)) {
+ await this.setToken(browser.sessionId, sessionToken)
+
+ if ((browser.capabilities as Capabilities.BrowserStackCapabilities).browserName === 'firefox') {
+ await this.installFirefoxExtension(browser)
+ }
+
+ // @ts-expect-error fix type
+ browser.overwriteCommand('findElement', async (orginalFunc: unknown, using: string, value: string) => {
+ // @ts-expect-error fix type
+ return await this.handleHealing(orginalFunc, using, value, browser, options)
+ })
+ }
+ }
+ }
+
+ async selfHeal(options: BrowserstackOptions, caps: Capabilities.ResolvedTestrunnerCapabilities, browser: WebdriverIO.Browser) {
+ try {
+
+ const multiRemoteBrowsers = Object.keys(caps).filter(e => Object.keys(browser).includes(e))
+ if (multiRemoteBrowsers.length > 0) {
+ for (let i = 0; i < multiRemoteBrowsers.length; i++) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const remoteBrowser = (browser as any)[multiRemoteBrowsers[i]]
+ await this.handleSelfHeal(options, remoteBrowser)
+ }
+ } else {
+ await this.handleSelfHeal(options, browser)
+ }
+
+ } catch (err) {
+ if (options.selfHeal === true) {
+ BStackLogger.warn(`Error while setting up self-healing: ${err}. Disabling healing for this session.`)
+ }
+ }
+ }
+}
+
+export default new AiHandler()
diff --git a/packages/browserstack-service/src/bstackLogger.ts b/packages/browserstack-service/src/bstackLogger.ts
new file mode 100644
index 0000000..b397fd8
--- /dev/null
+++ b/packages/browserstack-service/src/bstackLogger.ts
@@ -0,0 +1,94 @@
+import path from 'node:path'
+import fs from 'node:fs'
+import chalk from 'chalk'
+
+import logger from '@wdio/logger'
+
+import { LOGS_FILE } from './constants.js'
+import { COLORS } from './util.js'
+
+const log = logger('@wdio/browserstack-service')
+
+export class BStackLogger {
+ public static logFilePath = path.join(process.cwd(), LOGS_FILE)
+ public static logFolderPath = path.join(process.cwd(), 'logs')
+ private static logFileStream: fs.WriteStream | null
+
+ private static redactCredentials(logMessage: string): string {
+ return logMessage
+ .replace(/(["']?(?:username|userName|accesskey|accessKey|user|key)["']?\s*[:=]\s*["']?)([^"'\s,}]+)/gi, '$1')
+ .replace(/([?&](?:username|userName|access_key|accesskey|accessKey|user|key)=)([^\s]+)/gi, '$1')
+ }
+
+ static logToFile(logMessage: string, logLevel: string) {
+ try {
+ const redactedMessage = this.redactCredentials(logMessage)
+ if (!this.logFileStream) {
+ this.ensureLogsFolder()
+ this.logFileStream = fs.createWriteStream(this.logFilePath, { flags: 'a' })
+ }
+ if (this.logFileStream && this.logFileStream.writable) {
+ this.logFileStream.write(this.formatLog(redactedMessage, logLevel))
+ }
+ } catch (error) {
+ log.debug(`Failed to log to file. Error ${error}`)
+ }
+ }
+
+ private static formatLog(logMessage: string, level: string) {
+ return `${chalk.gray(new Date().toISOString())} ${chalk[COLORS[level]](level.toUpperCase())} ${chalk.whiteBright('@wdio/browserstack-service')} ${logMessage}\n`
+ }
+
+ public static info(message: string) {
+ const redactedMessage = this.redactCredentials(message)
+ this.logToFile(redactedMessage, 'info')
+ log.info(redactedMessage)
+ }
+
+ public static error(message: string) {
+ const redactedMessage = this.redactCredentials(message)
+ this.logToFile(redactedMessage, 'error')
+ log.error(redactedMessage)
+ }
+
+ public static debug(message: string, param?: unknown) {
+ const redactedMessage = this.redactCredentials(message)
+ this.logToFile(redactedMessage, 'debug')
+ if (param) {
+ log.debug(redactedMessage, param)
+ } else {
+ log.debug(redactedMessage)
+ }
+ }
+
+ public static warn(message: string) {
+ const redactedMessage = this.redactCredentials(message)
+ this.logToFile(redactedMessage, 'warn')
+ log.warn(redactedMessage)
+ }
+
+ public static trace(message: string) {
+ const redactedMessage = this.redactCredentials(message)
+ this.logToFile(redactedMessage, 'trace')
+ log.trace(redactedMessage)
+ }
+
+ public static clearLogger() {
+ if (this.logFileStream) {
+ this.logFileStream.end()
+ }
+ this.logFileStream = null
+ }
+
+ public static clearLogFile() {
+ if (fs.existsSync(this.logFilePath)) {
+ fs.truncateSync(this.logFilePath)
+ }
+ }
+
+ public static ensureLogsFolder() {
+ if (!fs.existsSync(this.logFolderPath)){
+ fs.mkdirSync(this.logFolderPath)
+ }
+ }
+}
diff --git a/packages/browserstack-service/src/cleanup.ts b/packages/browserstack-service/src/cleanup.ts
new file mode 100644
index 0000000..3f48bfc
--- /dev/null
+++ b/packages/browserstack-service/src/cleanup.ts
@@ -0,0 +1,108 @@
+import { getErrorString, stopBuildUpstream } from './util.js'
+import { BStackLogger } from './bstackLogger.js'
+import fs from 'node:fs'
+import util from 'node:util'
+import { fireFunnelRequest } from './instrumentation/funnelInstrumentation.js'
+import { BROWSERSTACK_TESTHUB_UUID, BROWSERSTACK_TESTHUB_JWT, BROWSERSTACK_OBSERVABILITY } from './constants.js'
+import type { FunnelData } from './types.js'
+import PerformanceTester from './instrumentation/performance/performance-tester.js'
+
+export default class BStackCleanup {
+ static async startCleanup() {
+ try {
+ // Get funnel data object from saved file
+ const funnelDataCleanup = process.argv.includes('--funnelData')
+ let funnelData: FunnelData | null = null
+ if (funnelDataCleanup) {
+ const index = process.argv.indexOf('--funnelData')
+ const filePath = process.argv[index + 1]
+ funnelData = BStackCleanup.getFunnelDataFromFile(filePath)
+ }
+
+ if (process.argv.includes('--observability') && funnelData) {
+ await this.executeObservabilityCleanup(funnelData)
+ }
+
+ if (funnelDataCleanup && funnelData) {
+ await this.sendFunnelData(funnelData)
+ }
+ } catch (err) {
+ const error = err as string
+ BStackLogger.error(error)
+ }
+
+ try {
+ if (process.argv.includes('--performanceData')) {
+ await PerformanceTester.uploadEventsData()
+ }
+ } catch (er) {
+ BStackLogger.debug(`Error in sending events data ${util.format(er)}`)
+ }
+ }
+ static async executeObservabilityCleanup(funnelData: FunnelData) {
+ if (!process.env[BROWSERSTACK_TESTHUB_JWT]) {
+ return
+ }
+ BStackLogger.debug('Executing Test Reporting and Analytics cleanup')
+ try {
+ const result = await stopBuildUpstream()
+ if ((process.env[BROWSERSTACK_OBSERVABILITY]) && process.env[BROWSERSTACK_TESTHUB_UUID]) {
+ BStackLogger.info(`\nVisit https://automation.browserstack.com/builds/${process.env[BROWSERSTACK_TESTHUB_UUID]} to view build report, insights, and many more debugging information all at one place!\n`)
+ }
+ const status = (result && result.status) || 'failed'
+ const message = (result && result.message)
+ this.updateO11yStopData(funnelData, status, status === 'failed' ? message : undefined)
+ } catch (e: unknown) {
+ BStackLogger.error('Error in stopping Test Reporting and Analytics build: ' + e)
+ this.updateO11yStopData(funnelData, 'failed', e)
+ }
+ }
+
+ static updateO11yStopData(funnelData: FunnelData, status: string, error: unknown = undefined) {
+ const toData = funnelData?.event_properties?.productUsage?.testObservability
+ // Return if no Test Reporting and Analytics data in funnel data
+ if (!toData) {
+ return
+ }
+ let existingStopData = toData.events.buildEvents.finished
+ existingStopData = existingStopData || {}
+
+ existingStopData = {
+ ...existingStopData,
+ status,
+ error: getErrorString(error),
+ stoppedFrom: 'exitHook'
+ }
+ toData.events.buildEvents.finished = existingStopData
+ }
+
+ static async sendFunnelData(funnelData: FunnelData) {
+ try {
+ await fireFunnelRequest(funnelData)
+ BStackLogger.debug('Funnel data sent successfully from cleanup')
+ } catch (e: unknown) {
+ BStackLogger.error('Error in sending funnel data: ' + e)
+ }
+ }
+
+ static getFunnelDataFromFile(filePath: string) {
+ if (!filePath) {
+ return null
+ }
+
+ const content = fs.readFileSync(filePath, 'utf8')
+
+ const data = JSON.parse(content)
+ this.removeFunnelDataFile(filePath)
+ return data
+ }
+
+ static removeFunnelDataFile(filePath?: string) {
+ if (!filePath) {
+ return
+ }
+ fs.rmSync(filePath, { force: true })
+ }
+}
+
+void BStackCleanup.startCleanup()
diff --git a/packages/browserstack-service/src/cli/apiUtils.ts b/packages/browserstack-service/src/cli/apiUtils.ts
new file mode 100644
index 0000000..9eabcae
--- /dev/null
+++ b/packages/browserstack-service/src/cli/apiUtils.ts
@@ -0,0 +1,25 @@
+export default class APIUtils {
+ static FUNNEL_INSTRUMENTATION_URL = 'https://api.browserstack.com/sdk/v1/event'
+ static BROWSERSTACK_AUTOMATE_API_URL = 'https://api.browserstack.com'
+ static BROWSERSTACK_AA_API_URL = 'https://api.browserstack.com'
+ static BROWSERSTACK_PERCY_API_URL = 'https://api.browserstack.com'
+ static BROWSERSTACK_AUTOMATE_API_CLOUD_URL = 'https://api-cloud.browserstack.com'
+ static BROWSERSTACK_AA_API_CLOUD_URL = 'https://api-cloud.browserstack.com'
+ static APP_ALLY_ENDPOINT = 'https://app-accessibility.browserstack.com/automate'
+ static DATA_ENDPOINT = 'https://collector-observability.browserstack.com'
+ static UPLOAD_LOGS_ADDRESS = 'https://upload-observability.browserstack.com'
+ static EDS_URL = 'https://eds.browserstack.com'
+
+ static updateURLSForGRR(apis: GRRUrls) {
+ this.FUNNEL_INSTRUMENTATION_URL = `${apis.automate.api}/sdk/v1/event`
+ this.BROWSERSTACK_AUTOMATE_API_URL = apis.automate.api
+ this.BROWSERSTACK_AA_API_URL = apis.appAutomate.api
+ this.BROWSERSTACK_PERCY_API_URL = apis.percy.api
+ this.BROWSERSTACK_AUTOMATE_API_CLOUD_URL = apis.automate.upload
+ this.BROWSERSTACK_AA_API_CLOUD_URL = apis.appAutomate.upload
+ this.APP_ALLY_ENDPOINT = `${apis.appAccessibility.api}/automate`
+ this.DATA_ENDPOINT = apis.observability.api
+ this.UPLOAD_LOGS_ADDRESS = apis.observability.upload
+ this.EDS_URL = apis.edsInstrumentation.api
+ }
+}
diff --git a/packages/browserstack-service/src/cli/cliLogger.ts b/packages/browserstack-service/src/cli/cliLogger.ts
new file mode 100644
index 0000000..0941c2c
--- /dev/null
+++ b/packages/browserstack-service/src/cli/cliLogger.ts
@@ -0,0 +1,82 @@
+import path from 'node:path'
+import fs from 'node:fs'
+import chalk from 'chalk'
+
+import logger from '@wdio/logger'
+
+import { LOGS_FILE } from '../constants.js'
+import { COLORS } from '../util.js'
+
+const log = logger('@wdio/browserstack-service/cli')
+
+export class BStackLogger {
+ public static logFilePath = path.join(process.cwd(), LOGS_FILE)
+ public static logFolderPath = path.join(process.cwd(), 'logs')
+ private static logFileStream: fs.WriteStream | null
+
+ static logToFile(logMessage: string, logLevel: string) {
+ try {
+ if (!this.logFileStream) {
+ this.ensureLogsFolder()
+ this.logFileStream = fs.createWriteStream(this.logFilePath, { flags: 'a' })
+ }
+ if (this.logFileStream && this.logFileStream.writable) {
+ this.logFileStream.write(this.formatLog(logMessage, logLevel))
+ }
+ } catch (error) {
+ log.debug(`Failed to log to file. Error ${error}`)
+ }
+ }
+
+ private static formatLog(logMessage: string, level: string) {
+ return `${chalk.gray(new Date().toISOString())} ${chalk[COLORS[level]](level.toUpperCase())} ${chalk.whiteBright('@wdio/browserstack-service')} ${logMessage}\n`
+ }
+
+ public static info(message: string) {
+ this.logToFile(message, 'info')
+ log.info(message)
+ }
+
+ public static error(message: string) {
+ this.logToFile(message, 'error')
+ log.error(message)
+ }
+
+ public static debug(message: string, param?: unknown) {
+ this.logToFile(message, 'debug')
+ if (param) {
+ log.debug(message, param)
+ } else {
+ log.debug(message)
+ }
+ }
+
+ public static warn(message: string) {
+ this.logToFile(message, 'warn')
+ log.warn(message)
+ }
+
+ public static trace(message: string) {
+ this.logToFile(message, 'trace')
+ log.trace(message)
+ }
+
+ public static clearLogger() {
+ if (this.logFileStream) {
+ this.logFileStream.end()
+ }
+ this.logFileStream = null
+ }
+
+ public static clearLogFile() {
+ if (fs.existsSync(this.logFilePath)) {
+ fs.truncateSync(this.logFilePath)
+ }
+ }
+
+ public static ensureLogsFolder() {
+ if (!fs.existsSync(this.logFolderPath)){
+ fs.mkdirSync(this.logFolderPath)
+ }
+ }
+}
diff --git a/packages/browserstack-service/src/cli/cliUtils.ts b/packages/browserstack-service/src/cli/cliUtils.ts
new file mode 100644
index 0000000..f11bf1b
--- /dev/null
+++ b/packages/browserstack-service/src/cli/cliUtils.ts
@@ -0,0 +1,984 @@
+import fs from 'node:fs'
+import fsp from 'node:fs/promises'
+import { platform, arch, homedir } from 'node:os'
+import path from 'node:path'
+import util, { promisify } from 'node:util'
+import { exec } from 'node:child_process'
+import { Readable } from 'node:stream'
+import type { ZipFile, Options as yauzlOptions } from 'yauzl'
+import yauzl from 'yauzl'
+import { threadId } from 'node:worker_threads'
+
+import { _fetch as fetch } from '../fetchWrapper.js'
+
+import {
+ isNullOrEmpty,
+ nestedKeyValue,
+ createDir,
+ isWritable,
+ setReadWriteAccess,
+ isTrue,
+ getBrowserStackUser,
+ getBrowserStackKey,
+ isFalse,
+ isTurboScale,
+ shouldAddServiceVersion,
+} from '../util.js'
+import PerformanceTester from '../instrumentation/performance/performance-tester.js'
+import { EVENTS as PerformanceEvents } from '../instrumentation/performance/constants.js'
+import { BStackLogger as logger } from './cliLogger.js'
+import { UPDATED_CLI_ENDPOINT, BSTACK_SERVICE_VERSION, BINARY_BUSY_ERROR_CODES } from '../constants.js'
+import type { Options, Capabilities } from '@wdio/types'
+import type {
+ BrowserstackConfig,
+ BrowserstackOptions,
+ TestManagementOptions,
+ TestObservabilityOptions,
+} from '../types.js'
+import { TestFrameworkConstants } from './frameworks/constants/testFrameworkConstants.js'
+import APIUtils from './apiUtils.js'
+
+const CLI_LOCK_TIMEOUT_MS = 5 * 60 * 1000
+const CLI_LOCK_POLL_MS = 1000
+const CLI_DOWNLOAD_TIMEOUT_MS = 5 * 60 * 1000
+const CLI_DOWNLOAD_TMP_PREFIX = 'downloaded_file_'
+const CLI_DOWNLOAD_TMP_SUFFIX = '.zip'
+
+export class CLIUtils {
+ static automationFrameworkDetail = {}
+ static testFrameworkDetail = {}
+ static CLISupportedFrameworks = ['mocha']
+
+ static isDevelopmentEnv() {
+ return process.env.BROWSERSTACK_CLI_ENV === 'development'
+ }
+
+ static getCLIParamsForDevEnv(): Record {
+ return {
+ id: process.env.BROWSERSTACK_CLI_ENV || '',
+ listen: `unix:/tmp/sdk-platform-${process.env.BROWSERSTACK_CLI_ENV}.sock`,
+ }
+ }
+
+ /**
+ * Build config object for binary session request
+ * @returns {string}
+ * @throws {Error}
+ */
+ static getBinConfig(
+ config: Options.Testrunner,
+ capabilities:
+ | Capabilities.RequestedStandaloneCapabilities
+ | Capabilities.RequestedStandaloneCapabilities[],
+ options: BrowserstackConfig & BrowserstackOptions,
+ buildTag?: string,
+ ) {
+ const modifiedOpts: Record = { ...options }
+ if (modifiedOpts.opts) {
+ modifiedOpts.browserStackLocalOptions = modifiedOpts.opts
+ delete modifiedOpts.opts
+ }
+ delete modifiedOpts.testManagementOptions
+
+ modifiedOpts.testContextOptions = {
+ skipSessionName: isFalse(modifiedOpts.setSessionName),
+ skipSessionStatus: isFalse(modifiedOpts.setSessionStatus),
+ sessionNameOmitTestTitle: modifiedOpts.sessionNameOmitTestTitle || false,
+ sessionNamePrependTopLevelSuiteTitle:
+ modifiedOpts.sessionNamePrependTopLevelSuiteTitle || false,
+ sessionNameFormat: modifiedOpts.sessionNameFormat || '',
+ }
+
+ const commonBstackOptions = (() => {
+ if (
+ capabilities &&
+ !Array.isArray(capabilities) &&
+ typeof capabilities === 'object' &&
+ 'bstack:options' in (capabilities as Record)
+ ) {
+ // Cast after guard to satisfy TypeScript
+ return (
+ (
+ capabilities as {
+ ['bstack:options']?: Record;
+ }
+ )['bstack:options'] || {}
+ )
+ }
+ return {}
+ })()
+
+ const isNonBstackA11y =
+ isTurboScale(options) ||
+ !shouldAddServiceVersion(
+ config as Options.Testrunner,
+ options.testObservability,
+ )
+ const observabilityOptions: TestObservabilityOptions =
+ options.testObservabilityOptions || {}
+ const testManagementOptions: TestManagementOptions =
+ options.testManagementOptions || {}
+ const testPlanId = typeof testManagementOptions.testPlanId === 'string'
+ ? testManagementOptions.testPlanId.trim()
+ : ''
+ const binconfig: Record = {
+ userName: observabilityOptions.user || config.user,
+ accessKey: observabilityOptions.key || config.key,
+ platforms: [],
+ isNonBstackA11yWDIO: isNonBstackA11y,
+ ...modifiedOpts,
+ ...commonBstackOptions,
+ }
+
+ binconfig.buildName = observabilityOptions.buildName || binconfig.buildName
+ binconfig.projectName = observabilityOptions.projectName || binconfig.projectName
+ binconfig.buildTag = this.getObservabilityBuildTags(observabilityOptions, buildTag) || []
+ if (testPlanId.length > 0) {
+ binconfig.testManagementOptions = {
+ testPlanId,
+ }
+ }
+
+ const caps = Array.isArray(capabilities) ? capabilities : [capabilities]
+ for (const cap of caps) {
+ const platform: Record = {}
+ const capability = cap as Record
+
+ Object.keys(capability)
+ .filter((key) => key !== 'bstack:options')
+ .forEach((key) => {
+ platform[key] = capability[key]
+ })
+
+ if (capability['bstack:options']) {
+ Object.keys(
+ capability['bstack:options'] as Record,
+ ).forEach((key) => {
+ platform[key] = (
+ capability['bstack:options'] as Record<
+ string,
+ unknown
+ >
+ )[key]
+ })
+ }
+ (binconfig.platforms as Array).push(platform)
+ }
+ return JSON.stringify(binconfig)
+ }
+
+ static getSdkVersion() {
+ return BSTACK_SERVICE_VERSION
+ }
+
+ static getSdkLanguage() {
+ return 'ECMAScript'
+ }
+
+ static async setupCliPath(
+ config: Options.Testrunner,
+ ): Promise {
+ logger.debug('Configuring Cli path.')
+ const developmentBinaryPath = process.env.SDK_CLI_BIN_PATH || null
+ if (!isNullOrEmpty(developmentBinaryPath)) {
+ logger.debug(`Development Cli Path: ${developmentBinaryPath}`)
+ return developmentBinaryPath
+ }
+
+ try {
+ const cliDir = this.getCliDir()
+ if (isNullOrEmpty(cliDir)) {
+ throw new Error('No writable directory available for the CLI')
+ }
+ const existingCliPath = this.getExistingCliPath(cliDir)
+ const finalBinaryPath = await this.checkAndUpdateCli(
+ existingCliPath,
+ cliDir,
+ config,
+ )
+ logger.debug(`Resolved binary path: ${finalBinaryPath}`)
+ return finalBinaryPath
+ } catch (err) {
+ logger.debug(
+ `Error in setting up cli path directory, Exception: ${util.format(err)}`,
+ )
+ }
+ return null
+ }
+
+ static async checkAndUpdateCli(
+ existingCliPath: string,
+ cliDir: string,
+ config: Options.Testrunner,
+ ): Promise {
+ // Skip CLI update in worker processes - only launcher should update
+ // Workers are identified by having BROWSERSTACK_TESTHUB_JWT set (build already started)
+ if (process.env.BROWSERSTACK_TESTHUB_JWT) {
+ logger.debug(
+ `Worker process detected, skipping CLI update. Using existing: ${existingCliPath}`,
+ )
+ if (existingCliPath && fs.existsSync(existingCliPath)) {
+ return existingCliPath
+ }
+ logger.warn(
+ 'Worker process has no existing CLI binary, attempting download as fallback.',
+ )
+ }
+
+ PerformanceTester.start(PerformanceEvents.SDK_CLI_CHECK_UPDATE)
+ logger.info(`Current CLI Path Found: ${existingCliPath}`)
+ const queryParams: Record = {
+ sdk_version: CLIUtils.getSdkVersion(),
+ os: platform(),
+ os_arch: arch(),
+ cli_version: '0',
+ sdk_language: this.getSdkLanguage(),
+ }
+ if (!isNullOrEmpty(existingCliPath)) {
+ // If binary is busy (being executed by another process), skip version check
+ // and API call entirely — use existing binary as-is
+ if (this.isBinaryBusy(existingCliPath)) {
+ logger.warn(`Existing binary is currently in use, skipping update: ${existingCliPath}`)
+ PerformanceTester.end(PerformanceEvents.SDK_CLI_CHECK_UPDATE)
+ return existingCliPath
+ }
+ const version = await this.runShellCommand(
+ `${existingCliPath} version`,
+ )
+ if (version.toLowerCase().includes('text file busy')) {
+ logger.warn(`Binary busy during version check, skipping update: ${existingCliPath}`)
+ PerformanceTester.end(PerformanceEvents.SDK_CLI_CHECK_UPDATE)
+ return existingCliPath
+ }
+ queryParams.cli_version = version
+ }
+ const response = await this.requestToUpdateCLI(queryParams, config)
+ if (nestedKeyValue(response, ['updated_cli_version'])) {
+ logger.debug(
+ `Need to update binary, current binary version: ${queryParams.cli_version}`,
+ )
+
+ const browserStackBinaryUrl =
+ process.env.BROWSERSTACK_BINARY_URL || null
+ if (!isNullOrEmpty(browserStackBinaryUrl)) {
+ logger.debug(
+ `Using BROWSERSTACK_BINARY_URL: ${browserStackBinaryUrl}`,
+ )
+ response.url = browserStackBinaryUrl
+ }
+
+ const finalBinaryPath = await this.downloadLatestBinary(
+ nestedKeyValue(response, ['url']),
+ cliDir,
+ )
+ PerformanceTester.end(PerformanceEvents.SDK_CLI_CHECK_UPDATE)
+ return finalBinaryPath
+ }
+ PerformanceTester.end(PerformanceEvents.SDK_CLI_CHECK_UPDATE)
+ return existingCliPath
+ }
+
+ static getCliDir() {
+ const writableDir = this.getWritableDir()
+ try {
+ if (isNullOrEmpty(writableDir)) {
+ throw new Error('No writable directory available for the CLI')
+ }
+ const cliDirPath = path.join(writableDir!, 'cli')
+ if (!fs.existsSync(cliDirPath)) {
+ createDir(cliDirPath)
+ }
+ return cliDirPath
+ } catch (err) {
+ logger.error(
+ `Error in getting writable directory, writableDir=${util.format(err)}`,
+ )
+ return ''
+ }
+ }
+
+ static getWritableDir() {
+ const writableDirOptions = [
+ process.env.BROWSERSTACK_FILES_DIR,
+ path.join(homedir(), '.browserstack'),
+ path.join('tmp', '.browserstack'),
+ ]
+
+ for (const path of writableDirOptions) {
+ if (isNullOrEmpty(path)) {
+ continue
+ }
+ try {
+ if (fs.existsSync(path!)) {
+ logger.debug(`File ${path} already exist`)
+ if (!isWritable(path!)) {
+ logger.debug(`Giving write permission to ${path}`)
+ const success = setReadWriteAccess(path!)
+ if (!isTrue(success)) {
+ logger.warn(
+ `Unable to provide write permission to ${path}`,
+ )
+ }
+ }
+ } else {
+ logger.debug(`File does not exist: ${path}`)
+ createDir(path!)
+ logger.debug(`Giving write permission to ${path}`)
+ const success = setReadWriteAccess(path!)
+ if (!isTrue(success)) {
+ logger.warn(
+ `Unable to provide write permission to ${path}`,
+ )
+ }
+ }
+ return path
+ } catch (err) {
+ logger.error(
+ `Unable to get writable directory, exception ${util.format(err)}`,
+ )
+ }
+ }
+ return null
+ }
+
+ static getExistingCliPath(cliDir: string) {
+ try {
+ // Check if the path exists and is a directory
+ if (!fs.existsSync(cliDir) || !fs.statSync(cliDir).isDirectory()) {
+ return ''
+ }
+
+ // List all files in the directory that start with "binary-"
+ const allBinaries = fs
+ .readdirSync(cliDir)
+ .map((file: string) => path.join(cliDir, file))
+ .filter(
+ (filePath: string) =>
+ fs.statSync(filePath).isFile() &&
+ path.basename(filePath).startsWith('binary-'),
+ )
+
+ if (allBinaries.length > 0) {
+ // Get the latest binary by comparing the last modified time
+ const latestBinary = allBinaries
+ .map((filePath: string) => ({
+ filePath,
+ mtime: fs.statSync(filePath).mtime,
+ }))
+ .reduce(
+ (
+ latest: { filePath: string; mtime: Date } | null,
+ current: { filePath: string; mtime: Date },
+ ) => {
+ if (!latest || !latest.mtime) {
+ return current
+ }
+
+ if (current.mtime > latest.mtime) {
+ return current
+ }
+
+ return latest
+ },
+ null,
+ )
+ return latestBinary ? latestBinary.filePath : ''
+ }
+
+ return '' // No binary present
+ } catch (err) {
+ logger.error(`Error while reading CLI path: ${util.format(err)}`)
+ return ''
+ }
+ }
+
+ static isBinaryBusy(binaryPath: string): boolean {
+ if (isNullOrEmpty(binaryPath)) {return false}
+ if (platform() === 'darwin') {return false}
+ if (!fs.existsSync(binaryPath)) {return false}
+
+ try {
+ const fd = fs.openSync(binaryPath, 'r+')
+ fs.closeSync(fd)
+ return false
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (err: any) {
+ if (BINARY_BUSY_ERROR_CODES.includes(err.code)) {
+ logger.debug(`Binary is busy: ${binaryPath}`)
+ return true
+ }
+ logger.debug(`Error checking if binary is busy: ${err.message}`)
+ return false
+ }
+ }
+
+ static requestToUpdateCLI = async (
+ queryParams: Record,
+ config: Options.Testrunner,
+ ) => {
+ const params = new URLSearchParams(queryParams)
+ const requestInit: RequestInit = {
+ method: 'GET',
+ headers: {
+ Authorization: `Basic ${Buffer.from(`${getBrowserStackUser(config)}:${getBrowserStackKey(config)}`).toString('base64')}`,
+ },
+ }
+ const response = await fetch(
+ `${APIUtils.BROWSERSTACK_AUTOMATE_API_URL}/${UPDATED_CLI_ENDPOINT}?${params.toString()}`,
+ requestInit,
+ )
+ const jsonResponse = await response.json()
+ logger.debug(`response ${JSON.stringify(jsonResponse)}`)
+ return jsonResponse
+ }
+
+ static runShellCommand(
+ cmdCommand: string,
+ workingDir = '',
+ ): Promise {
+ return new Promise((resolve) => {
+ const process = exec(
+ cmdCommand,
+ { cwd: workingDir, timeout: 5000 },
+ (error: Error, stdout: string, stderr: string) => {
+ if (error) {
+ resolve(stderr.trim() || 'SHELL_EXECUTE_ERROR')
+ } else {
+ resolve(stdout.trim())
+ }
+ },
+ )
+
+ // Ensure the process is killed if it exceeds the timeout
+ process.on('error', () => {
+ resolve('SHELL_EXECUTE_ERROR')
+ })
+ })
+ }
+
+ static downloadLatestBinary = async (
+ binDownloadUrl: string,
+ cliDir: string,
+ ): Promise => {
+ const lockPath = path.join(cliDir, 'download.lock')
+
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
+
+ const parseLockFile = () => {
+ try {
+ const content = fs.readFileSync(lockPath, 'utf8').trim()
+ const [pidLine, timestampLine] = content.split('\n')
+ const pid = Number.parseInt(pidLine, 10)
+ const timestamp = Number.parseInt(timestampLine, 10)
+ if (!Number.isFinite(pid) || !Number.isFinite(timestamp)) {
+ return null
+ }
+ return { pid, timestamp }
+ } catch {
+ return null
+ }
+ }
+
+ const isProcessRunning = (pid: number) => {
+ try {
+ process.kill(pid, 0)
+ return true
+ } catch {
+ return false
+ }
+ }
+
+ const acquireLock = async (
+ timeoutMs = CLI_LOCK_TIMEOUT_MS,
+ pollMs = CLI_LOCK_POLL_MS,
+ ): Promise<(() => void) | { alreadyExists: string }> => {
+ const start = Date.now()
+ while (true) {
+ try {
+ const fd = fs.openSync(lockPath, 'wx')
+ try {
+ fs.writeFileSync(fd, `${process.pid}\n${Date.now()}\n`)
+ } catch {
+ // intentionally ignore write errors; the open fd still holds
+ // the exclusive lock and will be closed in cleanup
+ }
+ return () => {
+ try {
+ fs.closeSync(fd)
+ } catch {
+ // ignore cleanup errors
+ }
+ try {
+ fs.unlinkSync(lockPath)
+ } catch {
+ // ignore cleanup errors
+ }
+ }
+ } catch (e: unknown) {
+ const error = e as { code?: string }
+ if (error.code === 'EEXIST') {
+ const lockMeta = parseLockFile()
+ if (lockMeta) {
+ const lockAge = Date.now() - lockMeta.timestamp
+ const running = isProcessRunning(lockMeta.pid)
+ if (!running || lockAge > timeoutMs) {
+ logger.warn(
+ `Stale CLI download lock detected (pid=${lockMeta.pid}, age=${lockAge}ms). Removing lock.`,
+ )
+ try {
+ fs.unlinkSync(lockPath)
+ } catch {
+ // ignore cleanup errors
+ }
+ continue
+ }
+ }
+ // Check if existing binary appeared while waiting
+ const existingBinary =
+ CLIUtils.getExistingCliPath(cliDir)
+ if (
+ existingBinary &&
+ fs.existsSync(existingBinary) &&
+ fs.statSync(existingBinary).size > 0
+ ) {
+ logger.debug(
+ `Binary appeared while waiting for lock: ${existingBinary}`,
+ )
+ return { alreadyExists: existingBinary }
+ }
+ if (Date.now() - start > timeoutMs) {
+ throw new Error(
+ `Timeout waiting for lock: ${lockPath}`,
+ )
+ }
+ await sleep(pollMs)
+ continue
+ }
+ throw e
+ }
+ }
+ }
+
+ const cleanupTemporaryDownloads = (maxAgeMs = CLI_LOCK_TIMEOUT_MS) => {
+ try {
+ const now = Date.now()
+ // Match both download zips (downloaded_file_*.zip) and orphan extract
+ // temp files (.tmp.) left by crashed peer workers.
+ const tmpExtractRe = /\.tmp\.\d+$/
+ for (const entry of fs.readdirSync(cliDir)) {
+ const isDownloadZip =
+ entry.startsWith(CLI_DOWNLOAD_TMP_PREFIX) &&
+ entry.endsWith(CLI_DOWNLOAD_TMP_SUFFIX)
+ const isExtractTmp = tmpExtractRe.test(entry)
+ if (!isDownloadZip && !isExtractTmp) {
+ continue
+ }
+ const filePath = path.join(cliDir, entry)
+ let stats: fs.Stats
+ try {
+ stats = fs.statSync(filePath)
+ } catch {
+ continue
+ }
+ if (now - stats.mtimeMs < maxAgeMs) {
+ continue
+ }
+ try {
+ fs.unlinkSync(filePath)
+ } catch (err) {
+ logger.debug(
+ `Failed to delete temp CLI file ${filePath}: ${util.format(err)}`,
+ )
+ }
+ }
+ } catch (err) {
+ logger.debug(
+ `Failed to scan temp CLI files in ${cliDir}: ${util.format(err)}`,
+ )
+ }
+ }
+
+ PerformanceTester.start(PerformanceEvents.SDK_CLI_DOWNLOAD)
+ logger.debug(`Downloading SDK binary from: ${binDownloadUrl}`)
+
+ let downloadEnded = false
+ const endDownload = (success = true, errMsg?: string) => {
+ if (downloadEnded) {
+ return
+ }
+ downloadEnded = true
+ if (success) {
+ PerformanceTester.end(PerformanceEvents.SDK_CLI_DOWNLOAD)
+ return
+ }
+ PerformanceTester.end(
+ PerformanceEvents.SDK_CLI_DOWNLOAD,
+ false,
+ errMsg,
+ )
+ }
+
+ let releaseLock: (() => void) | undefined
+ try {
+ const lockResult = await acquireLock()
+
+ // Check if binary already exists (another process downloaded it)
+ if (typeof lockResult !== 'function') {
+ endDownload()
+ return lockResult.alreadyExists
+ }
+
+ releaseLock = lockResult
+
+ // Re-check after acquiring lock
+ const existingBinary = CLIUtils.getExistingCliPath(cliDir)
+ if (
+ existingBinary &&
+ fs.existsSync(existingBinary) &&
+ fs.statSync(existingBinary).size > 0
+ ) {
+ logger.debug(
+ `Binary already exists after acquiring lock: ${existingBinary}`,
+ )
+ endDownload()
+ releaseLock()
+ return existingBinary
+ }
+
+ cleanupTemporaryDownloads()
+
+ const zipFilePath = path.join(
+ cliDir,
+ `${CLI_DOWNLOAD_TMP_PREFIX}${process.pid}_${Date.now()}${CLI_DOWNLOAD_TMP_SUFFIX}`,
+ )
+ const downloadedFileStream = fs.createWriteStream(zipFilePath)
+
+ return new Promise((resolve, reject) => {
+ const processDownload = async () => {
+ const abortController = new AbortController()
+ const timeout = setTimeout(
+ () => abortController.abort(),
+ CLI_DOWNLOAD_TIMEOUT_MS,
+ )
+ let response: Response
+ try {
+ response = await fetch(binDownloadUrl, {
+ signal: abortController.signal,
+ })
+ } finally {
+ clearTimeout(timeout)
+ }
+ if (!response.body) {
+ throw new Error('No response body received')
+ }
+
+ downloadedFileStream.on('error', function (err: Error) {
+ logger.error(
+ `Got Error while downloading cli binary file: ${err}`,
+ )
+ endDownload(false, util.format(err))
+ releaseLock?.()
+ reject(err)
+ })
+
+ try {
+ const arrayBuffer = await response.arrayBuffer()
+ const nodeStream = Readable.from([
+ new Uint8Array(arrayBuffer),
+ ])
+
+ nodeStream.pipe(downloadedFileStream)
+
+ // Set up the downloadFileStream handler before pipeline
+ CLIUtils.downloadFileStream(
+ downloadedFileStream,
+ zipFilePath,
+ cliDir,
+ (result: string) => {
+ endDownload()
+ releaseLock?.()
+ resolve(result)
+ },
+ (err?: Error) => {
+ endDownload(false, util.format(err))
+ releaseLock?.()
+ reject(err)
+ },
+ )
+ } catch (err) {
+ logger.error(
+ `Got Error in cli binary downloading request ${util.format(err)}`,
+ )
+ endDownload(false, util.format(err))
+ releaseLock?.()
+ reject(err as Error)
+ }
+ }
+
+ processDownload()
+ })
+ } catch (err) {
+ releaseLock?.()
+ endDownload(false, util.format(err))
+ logger.debug(
+ `Failed to download binary, Exception: ${util.format(err)}`,
+ )
+ return null
+ }
+ }
+
+ static downloadFileStream(
+ downloadedFileStream: fs.WriteStream,
+ zipFilePath: string,
+ cliDir: string,
+ resolve: (path: string) => void,
+ reject: (reason?: Error) => void,
+ ) {
+ downloadedFileStream.on('close', async function () {
+ const yauzlOpenPromise = promisify(yauzl.open) as (
+ path: string,
+ options: yauzlOptions,
+ ) => Promise
+ try {
+ const zipfile = await yauzlOpenPromise(zipFilePath, {
+ lazyEntries: true,
+ })
+ let resolvedBinaryPath: string | null = null
+
+ zipfile.readEntry()
+ zipfile.on('entry', async (entry) => {
+ if (/\/$/.test(entry.fileName)) {
+ zipfile.readEntry()
+ return
+ }
+
+ // Zip-slip guard: reject entries whose resolved path escapes cliDir
+ // (BROWSERSTACK_BINARY_URL lets users supply arbitrary zips).
+ const candidatePath = path.join(cliDir, entry.fileName)
+ const resolvedCandidate = path.resolve(candidatePath)
+ const resolvedDir = path.resolve(cliDir) + path.sep
+ if (!resolvedCandidate.startsWith(resolvedDir)) {
+ zipfile.close()
+ reject(new Error(`Zip-slip detected: entry "${entry.fileName}" resolves outside ${cliDir}`))
+ return
+ }
+
+ const isBinaryEntry = path.basename(entry.fileName).startsWith('binary-')
+
+ if (!isBinaryEntry) {
+ const directStream = fs.createWriteStream(candidatePath)
+ directStream.on('error', (writeErr) => {
+ zipfile.close()
+ reject(writeErr as Error)
+ })
+ const openReadStreamPromise = promisify(
+ zipfile.openReadStream,
+ ).bind(zipfile)
+ try {
+ const readStream = await openReadStreamPromise(entry)
+ readStream.on('end', function () {
+ directStream.end()
+ directStream.on('close', () => zipfile.readEntry())
+ })
+ readStream.pipe(directStream)
+ } catch (zipErr) {
+ zipfile.close()
+ reject(zipErr as Error)
+ }
+ return
+ }
+
+ // Binary entry: extract to PID-scoped temp file, chmod, atomic rename inline.
+ // Prevents ETXTBSY/EBUSY: the file being executed is never the file being written.
+ const finalPath = candidatePath
+ const tempPath = path.join(cliDir, `${entry.fileName}.tmp.${process.pid}`)
+
+ const writeStream = fs.createWriteStream(tempPath)
+
+ let writeStreamErrored = false
+ writeStream.on('error', (writeErr) => {
+ writeStreamErrored = true
+ fsp.unlink(tempPath).catch(() => {})
+ zipfile.close()
+ reject(writeErr as Error)
+ })
+
+ // 'close' fires after the fd is closed; safe for fsp.rename on Windows (where 'finish' may fire before fd release).
+ // autoClose=true also makes 'close' fire after 'error' — bail out if the error path already rejected.
+ writeStream.on('close', async () => {
+ if (writeStreamErrored) { return }
+ try {
+ await fsp.chmod(tempPath, '0755')
+ try {
+ await fsp.rename(tempPath, finalPath)
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (renameErr: any) {
+ // Narrow fallback to cross-device (EXDEV) only
+ if (renameErr.code !== 'EXDEV') {
+ throw renameErr
+ }
+ logger.warn(`Atomic rename failed (cross-device), falling back to copy: ${renameErr.message}`)
+ await fsp.copyFile(tempPath, finalPath)
+ await fsp.unlink(tempPath).catch(() => {})
+ }
+ if (!resolvedBinaryPath) {
+ resolvedBinaryPath = finalPath
+ }
+ zipfile.readEntry()
+ } catch (err) {
+ await fsp.unlink(tempPath).catch(() => {})
+ zipfile.close()
+ reject(err as Error)
+ }
+ })
+
+ const openReadStreamPromise = promisify(
+ zipfile.openReadStream,
+ ).bind(zipfile)
+ try {
+ const readStream = await openReadStreamPromise(entry)
+ readStream.on('end', function () {
+ writeStream.end()
+ })
+ readStream.pipe(writeStream)
+ } catch (zipErr) {
+ fsp.unlink(tempPath).catch(() => {})
+ zipfile.close()
+ reject(zipErr as Error)
+ }
+ })
+
+ zipfile.on('error', (zipErr) => {
+ reject(zipErr as Error)
+ })
+
+ zipfile.once('end', () => {
+ fsp.unlink(zipFilePath).catch(() => {
+ logger.warn(`Failed to delete zip file: ${zipFilePath}`)
+ })
+
+ if (!resolvedBinaryPath) {
+ zipfile.close()
+ reject(new Error('No binary-* entry found in zip; cannot complete CLI binary extraction'))
+ return
+ }
+ zipfile.close()
+ resolve(resolvedBinaryPath)
+ })
+ } catch (err) {
+ reject(err as Error)
+ }
+ })
+ }
+
+ static getTestFrameworkDetail() {
+ if (process.env.BROWSERSTACK_TEST_FRAMEWORK_DETAIL) {
+ return JSON.parse(process.env.BROWSERSTACK_TEST_FRAMEWORK_DETAIL)
+ }
+ return this.testFrameworkDetail
+ }
+
+ static getAutomationFrameworkDetail() {
+ if (process.env.BROWSERSTACK_AUTOMATION_FRAMEWORK_DETAIL) {
+ return JSON.parse(
+ process.env.BROWSERSTACK_AUTOMATION_FRAMEWORK_DETAIL,
+ )
+ }
+ return this.automationFrameworkDetail
+ }
+
+ static setFrameworkDetail(
+ testFramework: string,
+ automationFramework: string,
+ ) {
+ if (!testFramework || !automationFramework) {
+ logger.debug(
+ `Test or Automation framework not provided testFramework=${testFramework}, automationFramework=${automationFramework}`,
+ )
+ }
+
+ this.testFrameworkDetail = {
+ name: testFramework,
+ version: { [testFramework]: CLIUtils.getSdkVersion() },
+ }
+
+ this.automationFrameworkDetail = {
+ name: automationFramework,
+ version: { [automationFramework]: CLIUtils.getSdkVersion() },
+ }
+
+ process.env.BROWSERSTACK_AUTOMATION_FRAMEWORK_DETAIL = JSON.stringify(
+ this.automationFrameworkDetail,
+ )
+ process.env.BROWSERSTACK_TEST_FRAMEWORK_DETAIL = JSON.stringify(
+ this.testFrameworkDetail,
+ )
+ }
+
+ /**
+ * Get the current instance name using thread id and processId
+ * @returns {string}
+ */
+ static getCurrentInstanceName() {
+ return `${process.pid}:${threadId}`
+ }
+
+ /**
+ * Generate a unique client worker identifier combining thread ID and process ID.
+ * This identifier is used to track worker-specific events and performance metrics
+ * across distributed test execution. Format matches the Python SDK implementation
+ * for consistency across SDKs.
+ *
+ * Format: "threadId-processId"
+ *
+ * @param context - Optional execution context with threadId and processId
+ * @returns Worker ID string in format "threadId-processId"
+ * @example
+ * const workerId = CLIUtils.getClientWorkerId() // Returns "1-12345"
+ * const workerId = CLIUtils.getClientWorkerId({ threadId: 123, processId: 456 }) // Returns "123-456"
+ */
+ static getClientWorkerId(context?: { threadId?: string | number; processId?: string | number }): string {
+ const workerThreadId = context?.threadId?.toString() || threadId.toString()
+ const workerProcessId = context?.processId?.toString() || process.pid.toString()
+ return `${workerThreadId}-${workerProcessId}`
+ }
+
+ /**
+ *
+ * @param {TestFrameworkState | AutomationFrameworkState} frameworkState
+ * @param {HookState} hookState
+ * @returns {string}
+ */
+ static getHookRegistryKey(frameworkState: State, hookState: State) {
+ return `${frameworkState}:${hookState}`
+ }
+
+ static matchHookRegex(hookState: string) {
+ const pattern = new RegExp(TestFrameworkConstants.HOOK_REGEX)
+
+ return pattern.test(hookState)
+ }
+
+ static getObservabilityBuildTags(
+ observabilityOptions: TestObservabilityOptions,
+ bstackBuildTag?: string,
+ ) {
+ if (process.env.TEST_OBSERVABILITY_BUILD_TAG) {
+ return process.env.TEST_OBSERVABILITY_BUILD_TAG.split(',')
+ }
+ if (observabilityOptions.buildTag) {
+ return observabilityOptions.buildTag
+ }
+ if (bstackBuildTag) {
+ return [bstackBuildTag]
+ }
+ return []
+ }
+
+ static checkCLISupportedFrameworks(framework: string | undefined) {
+ if (framework === undefined) {
+ return false
+ }
+ return this.CLISupportedFrameworks.includes(framework)
+ }
+}
diff --git a/packages/browserstack-service/src/cli/eventDispatcher.ts b/packages/browserstack-service/src/cli/eventDispatcher.ts
new file mode 100644
index 0000000..6fb2def
--- /dev/null
+++ b/packages/browserstack-service/src/cli/eventDispatcher.ts
@@ -0,0 +1,56 @@
+/**
+ * EventDispatcher - Singleton class for event handling
+ */
+class EventDispatcher {
+
+ static #instance: EventDispatcher|null = null
+ observers: Record
+
+ constructor() {
+ this.observers = {}
+ }
+
+ /**
+ * Get the EventDispatcher singleton instance
+ * @returns {EventDispatcher} The singleton instance
+ */
+ static getInstance() {
+ if (!EventDispatcher.#instance) {
+ EventDispatcher.#instance = new EventDispatcher()
+ }
+ return EventDispatcher.#instance
+ }
+
+ /**
+ * Add event observer
+ * @param {string} event - Event name
+ * @param {Function} callback - Callback function
+ */
+ registerObserver(hookRegistryKey: string, callback: Function) {
+ if (!this.observers[hookRegistryKey]) {
+ this.observers[hookRegistryKey] = []
+ }
+
+ this.observers[hookRegistryKey].push(callback)
+ }
+
+ /**
+ * Notify registered observers on an event
+ * @param {string} event - Event name
+ * @param {*} data - Event data
+ */
+ async notifyObserver(event: string, args: unknown) {
+ if (this.observers[event]) {
+ for (const callback of this.observers[event]) {
+ await callback(args)
+ }
+ return
+ }
+ }
+}
+
+// Create the singleton instance
+export const eventDispatcher = EventDispatcher.getInstance()
+
+// Object.freeze to prevent modification of the instance
+Object.freeze(eventDispatcher)
diff --git a/packages/browserstack-service/src/cli/frameworks/automationFramework.ts b/packages/browserstack-service/src/cli/frameworks/automationFramework.ts
new file mode 100644
index 0000000..319853b
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/automationFramework.ts
@@ -0,0 +1,148 @@
+import { BStackLogger as logger } from '../cliLogger.js'
+import { eventDispatcher } from '../eventDispatcher.js'
+import { CLIUtils } from '../cliUtils.js'
+import TrackedInstance from '../instances/trackedInstance.js'
+import type AutomationFrameworkInstance from '../instances/automationFrameworkInstance.js'
+import type TrackedContext from '../instances/trackedContext.js'
+import { AutomationFrameworkConstants } from './constants/automationFrameworkConstants.js'
+
+/**
+ * AutomationFramework - Automation Framework abstract class
+ */
+export default class AutomationFramework {
+ #automationFrameworkName: string
+ #automationFrameworkVersion: string
+
+ static instances = new Map()
+ static KEY_AUTOMATION_SESSIONS = 'automation_sessions'
+ static KEY_NON_BROWSERSTACK_AUTOMATION_SESSIONS = 'non_browserstack_automation_sessions'
+
+ /**
+ * Constructor for the AutomationFramework
+ * @param {string} automationFrameworkName - Name of the automation framework
+ * @param {string} automationFrameworkVersion - Version of the automation framework
+ */
+ constructor(automationFrameworkName: string, automationFrameworkVersion: string) {
+ this.#automationFrameworkName = automationFrameworkName
+ this.#automationFrameworkVersion = automationFrameworkVersion
+ }
+
+ /**
+ * Get the automation framework name
+ * @returns {string} The name of the automation framework
+ */
+ getAutomationFrameworkName() {
+ return this.#automationFrameworkName
+ }
+
+ /**
+ * Get the automation framework version
+ * @returns {string} The version of the automation framework
+ */
+ getAutomationFrameworkVersion() {
+ return this.#automationFrameworkVersion
+ }
+
+ /**
+ * Track an event
+ * @param {Object}
+ * @param {Object}
+ * @param {Object}
+ * @returns {void}
+ */
+ async trackEvent(automationFrameworkState: State, hookState: State, args: unknown = {}) {
+ logger.info(`trackEvent: automationFrameworkState=${automationFrameworkState} hookState=${hookState} args=${args}`)
+ }
+
+ /**
+ *
+ * @param {*} instance
+ * @param {*} automationFrameworkState
+ * @param {*} hookState
+ * @param {*} args
+ */
+ async runHooks(instance: AutomationFrameworkInstance, automationFrameworkState: State, hookState: State, args: unknown = {}) {
+ logger.info(`runHooks: automationFrameworkState=${automationFrameworkState} hookState=${hookState}`)
+
+ const hookRegistryKey = CLIUtils.getHookRegistryKey(automationFrameworkState, hookState)
+ await eventDispatcher.notifyObserver(hookRegistryKey, args)
+ }
+
+ /**
+ * Register an observer
+ * @returns {void}
+ */
+ static registerObserver(automationFrameworkState: State, hookState: State, callback: Function) {
+ eventDispatcher.registerObserver(CLIUtils.getHookRegistryKey(automationFrameworkState, hookState), callback)
+ }
+
+ /**
+ * Set the tracked instance
+ * @param {TrackedInstance} context - The context
+ * @param {TrackedInstance} instance - The instance
+ * @returns {void}
+ */
+ static setTrackedInstance(context: TrackedContext, instance: AutomationFrameworkInstance) {
+ logger.debug(`setTrackedInstance: ${context.getId()}`)
+ AutomationFramework.instances.set(context.getId(), instance)
+ }
+
+ /**
+ * Get the tracked instance
+ * @returns {TrackedInstance} The tracked instance
+ */
+ static getTrackedInstance() {
+ logger.debug(`getTrackedInstance: ${CLIUtils.getCurrentInstanceName()}`)
+ const context = TrackedInstance.createContext(CLIUtils.getCurrentInstanceName())
+ return AutomationFramework.instances.get(context.getId())
+ }
+
+ /**
+ * Set the state
+ * @param {TrackedInstance} instance - The instance
+ * @param {string} key - The key
+ * @param {*} value - The value
+ * @returns
+ */
+ static setState(instance: AutomationFrameworkInstance, key: string, value: unknown) {
+ instance.getAllData().set(key, value)
+ }
+
+ /**
+ * Get the state
+ * @param {TrackedInstance} instance - The instance
+ * @param {string} key - The key
+ * @returns {*} The state
+ */
+ static getState(instance: AutomationFrameworkInstance, key: string) {
+ return instance.getAllData().get(key)
+ }
+
+ static isAutomationSession(instance: AutomationFrameworkInstance): boolean {
+ return AutomationFramework.getState(instance, AutomationFrameworkConstants.KEY_IS_BROWSERSTACK_HUB)
+ }
+
+ /**
+ * Set the driver for the automation framework instance
+ * @param {AutomationFrameworkInstance} instance - The automation framework instance
+ * @param {*} driver - The driver object
+ */
+ static setDriver(instance: AutomationFrameworkInstance, driver: unknown): void {
+ if (this.isAutomationSession(instance)) {
+ AutomationFramework.setState(instance, AutomationFramework.KEY_AUTOMATION_SESSIONS, driver)
+ } else {
+ AutomationFramework.setState(instance, AutomationFramework.KEY_NON_BROWSERSTACK_AUTOMATION_SESSIONS, driver)
+ }
+ }
+
+ /**
+ * Get the driver from the automation framework instance
+ * @param {AutomationFrameworkInstance} instance - The automation framework instance
+ * @returns {*} The driver object or null
+ */
+ static getDriver(instance: AutomationFrameworkInstance): unknown {
+ let driver: unknown = null
+ driver = this.isAutomationSession(instance) ? AutomationFramework.getState(instance, AutomationFramework.KEY_AUTOMATION_SESSIONS) || null : AutomationFramework.getState(instance, AutomationFramework.KEY_NON_BROWSERSTACK_AUTOMATION_SESSIONS) || null
+ return driver
+ }
+}
diff --git a/packages/browserstack-service/src/cli/frameworks/constants/automationFrameworkConstants.ts b/packages/browserstack-service/src/cli/frameworks/constants/automationFrameworkConstants.ts
new file mode 100644
index 0000000..b0e65e0
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/constants/automationFrameworkConstants.ts
@@ -0,0 +1,17 @@
+export const AutomationFrameworkConstants = {
+ ENV_BROWSERSTACK_PLATFORM_INDEX: 'BROWSERSTACK_PLATFORM_INDEX',
+ KEY_HUB_URL: 'hub_url',
+ KEY_FRAMEWORK_SESSION_ID: 'framework_session_id',
+ KEY_INPUT_CAPABILITIES: 'input_capabilities',
+ KEY_CAPABILITIES: 'capabilities',
+ KEY_IS_BROWSERSTACK_HUB: 'is_browserstack_hub',
+ KEY_STARTED_AT: 'started_at',
+ KEY_ENDED_AT: 'ended_at',
+ KEY_PLATFORM_INDEX: 'platform_index',
+ COMMAND_NEW_SESSION: 'newsession',
+ COMMAND_GET: 'get',
+ COMMAND_SCREENSHOT: 'screenshot',
+ COMMAND_W3C_EXECUTE_SCRIPT: 'w3cexecutescript',
+ COMMAND_W3C_EXECUTE_SCRIPT_ASYNC: 'w3cexecutescriptasync',
+ COMMAND_QUIT: 'quit'
+}
diff --git a/packages/browserstack-service/src/cli/frameworks/constants/testFrameworkConstants.ts b/packages/browserstack-service/src/cli/frameworks/constants/testFrameworkConstants.ts
new file mode 100644
index 0000000..e321352
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/constants/testFrameworkConstants.ts
@@ -0,0 +1,42 @@
+export const TestFrameworkConstants = {
+ KEY_TEST_UUID: 'test_uuid',
+ KEY_TEST_ID : 'test_id',
+ KEY_TEST_NAME : 'test_name',
+ KEY_TEST_FILE_PATH : 'test_file_path',
+ KEY_TEST_TAGS : 'test_tags',
+ KEY_TEST_RESULT : 'test_result',
+ KEY_TEST_RESULT_AT : 'test_result_at',
+ KEY_TEST_STARTED_AT : 'test_started_at',
+ KEY_TEST_ENDED_AT : 'test_ended_at',
+ KEY_TEST_LOCATION : 'test_location',
+ KEY_TEST_SCOPE : 'test_scope',
+ KEY_TEST_SCOPES : 'test_scopes',
+ KEY_TEST_FRAMEWORK_NAME : 'test_framework_name',
+ KEY_TEST_FRAMEWORK_VERSION : 'test_framework_version',
+ KEY_TEST_CODE : 'test_code',
+ KEY_TEST_RERUN_NAME : 'test_rerun_name',
+ KEY_PLATFORM_INDEX : 'platform_index',
+ KEY_TEST_FAILURE : 'test_failure',
+ KEY_TEST_FAILURE_TYPE : 'test_failure_type',
+ KEY_TEST_FAILURE_REASON : 'test_failure_reason',
+ KEY_TEST_LOGS : 'test_logs',
+ KEY_TEST_META : 'test_meta',
+ KEY_TEST_DEFERRED : 'test_deferred',
+ KEY_SESSION_NAME : 'test_session_name',
+ KEY_AUTOMATE_SESSION_NAME : 'automate_session_name',
+ KEY_AUTOMATE_SESSION_STATUS: 'automate_session_status',
+ KEY_AUTOMATE_SESSION_REASON: 'automate_session_reason',
+ KEY_EVENT_STARTED_AT : 'event_started_at',
+ KEY_EVENT_ENDED_AT : 'event_ended_at',
+ KEY_HOOK_ID : 'hook_id',
+ KEY_HOOK_RESULT : 'hook_result',
+ KEY_HOOK_LOGS : 'hook_logs',
+ KEY_HOOK_NAME : 'hook_name',
+ KEY_HOOKS_STARTED: 'test_hooks_started',
+ KEY_HOOKS_FINISHED: 'test_hooks_finished',
+ DEFAULT_TEST_RESULT : 'pending',
+ DEFAULT_HOOK_RESULT : 'pending',
+ KIND_SCREENSHOT : 'TEST_SCREENSHOT',
+ KIND_LOG : 'TEST_LOG',
+ HOOK_REGEX : '^(BEFORE_|AFTER_)',
+}
diff --git a/packages/browserstack-service/src/cli/frameworks/testFramework.ts b/packages/browserstack-service/src/cli/frameworks/testFramework.ts
new file mode 100644
index 0000000..f291505
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/testFramework.ts
@@ -0,0 +1,144 @@
+import { CLIUtils } from '../cliUtils.js'
+import { eventDispatcher } from '../eventDispatcher.js'
+import { BStackLogger as logger } from '../cliLogger.js'
+import type TrackedContext from '../instances/trackedContext.js'
+import TrackedInstance from '../instances/trackedInstance.js'
+import type TestFrameworkInstance from '../instances/testFrameworkInstance.js'
+
+export default class TestFramework {
+ static instances = new Map()
+ testFrameworks: Array = []
+ testFrameworkVersions: Record = {}
+ binSessionId: string|null = null
+
+ /**
+ * Constructor for the TestFramework
+ * @param {Array} testFrameworks - List of Test frameworks
+ * @param {Map} testFrameworkVersions - Name of the Test frameworks
+ * @param {string} binSessionId - BinSessionId
+ */
+ constructor(testFrameworks: Array, testFrameworkVersions: Record, binSessionId: string) {
+ this.testFrameworks = testFrameworks
+ this.testFrameworkVersions = testFrameworkVersions
+ this.binSessionId = binSessionId
+ }
+
+ /**
+ * get all instances
+ * @return {Map} - return all instances Map
+ */
+ getInstances() {
+ return TestFramework.instances
+ }
+
+ /**
+ * set testFrameworkInstance
+ * @param {TrackedContext} context
+ * @param {TestFrameworkInstance} instance
+ */
+ setInstance(context: TrackedContext, instance: TestFrameworkInstance) {
+ TestFramework.instances.set(context.getId, instance)
+ }
+
+ /**
+ * Find instance and track any state for the test framework
+ * @returns instance
+ */
+ static getTrackedInstance() {
+ const ctx = TrackedInstance.createContext(CLIUtils.getCurrentInstanceName())
+ return TestFramework.instances.get(ctx.getId())
+ }
+
+ /**
+ * Set tracked instance
+ * @returns {string} The name of the test framework
+ */
+ static setTrackedInstance(context: TrackedContext, instance: TestFrameworkInstance) {
+ TestFramework.instances.set(context.getId(), instance)
+ }
+
+ /**
+ * get all test framework versions
+ * @returns {Map} - return all versions of framework available.
+ */
+ getTestFrameworksVersions() {
+ return this.testFrameworkVersions
+ }
+
+ /**
+ * get all test frameworks
+ * @returns {Array} - return all test frameworks
+ */
+ getTestFrameworks() {
+ return this.testFrameworks
+ }
+
+ /**
+ * Track an event
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {HookState} hookState
+ * @param {*} args
+ * @returns {void}
+ */
+ trackEvent(testFrameworkState: State, hookState: State, args: unknown = {}) {
+ logger.info(`trackEvent: testFrameworkState=${testFrameworkState}; hookState=${hookState}; args=${args}`)
+ }
+
+ /**
+ * run test hooks
+ * @param {TestFrameworkInstance} instance
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {HookState} hookState
+ * @param {*} args
+ */
+ async runHooks(instance: TestFrameworkInstance, testFrameworkState: State, hookState: State, args: unknown = {}) {
+ logger.info(`runHooks: instance=${instance} automationFrameworkState=${testFrameworkState} hookState=${hookState}`)
+
+ const hookRegistryKey = CLIUtils.getHookRegistryKey(testFrameworkState, hookState)
+ await eventDispatcher.notifyObserver(hookRegistryKey, args)
+ }
+
+ /**
+ * Register an observer
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {HookState} hookState
+ * @param {*} callback
+ * @returns {void}
+ */
+ static registerObserver(testFrameworkState: State, hookState: State, callback: Function) {
+ eventDispatcher.registerObserver(CLIUtils.getHookRegistryKey(testFrameworkState, hookState), callback)
+ }
+
+ /**
+ * Resolve instance for the test framework
+ * @param {TestFrameworkInstance} testFrameworkInstance
+ * @param {string} key
+ * @returns {TestFrameworkInstance}
+ */
+ static getState(instance: TestFrameworkInstance, key: string) {
+ return instance.getAllData().get(key)
+ }
+
+ static hasState(instance: TestFrameworkInstance, key: string) {
+ return instance.hasData(key)
+ }
+
+ /**
+ * Set the state
+ * @param {TrackedInstance} instance - The instance
+ * @param {string} key - The key
+ * @param {*} value - The value
+ * @returns
+ */
+ static setState(instance: TrackedInstance, key: string, value: unknown) {
+ instance.getAllData().set(key, value)
+ }
+
+ updateInstanceState(instance: TestFrameworkInstance, testFrameworkState: State, hookState: State) {
+ instance.setLastTestState(instance.getCurrentTestState())
+ instance.setLastHookState(instance.getCurrentHookState())
+ instance.setCurrentTestState(testFrameworkState)
+ instance.setCurrentHookState(hookState)
+ }
+
+}
diff --git a/packages/browserstack-service/src/cli/frameworks/wdioAutomationFramework.ts b/packages/browserstack-service/src/cli/frameworks/wdioAutomationFramework.ts
new file mode 100644
index 0000000..7901f5f
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/wdioAutomationFramework.ts
@@ -0,0 +1,82 @@
+import AutomationFramework from './automationFramework.js'
+import { AutomationFrameworkState } from '../states/automationFrameworkState.js'
+import { CLIUtils } from '../cliUtils.js'
+import TrackedInstance from '../instances/trackedInstance.js'
+import AutomationFrameworkInstance from '../instances/automationFrameworkInstance.js'
+import { BStackLogger as logger } from '../cliLogger.js'
+
+/**
+ * WebdriverIO Framework class
+ */
+export default class WdioAutomationFramework extends AutomationFramework {
+
+ constructor(automationFrameworkName: string, automationFrameworkVersion: string) {
+ super(automationFrameworkName, automationFrameworkVersion)
+ }
+
+ /**
+ * Find instance and track any state for the automation framework
+ * @param {*} automationFrameworkState
+ * @param {*} hookState
+ * @param {*} args
+ */
+ async trackEvent(automationFrameworkState: State, hookState: State, args: Record = {}) {
+ logger.info(`trackEvent: automationFrameworkState=${automationFrameworkState} hookState=${hookState}`)
+ await super.trackEvent(automationFrameworkState, hookState, args)
+
+ const instance = this.resolveInstance(automationFrameworkState, hookState, args)
+ if (instance === null) {
+ logger.error(`trackEvent: instance not found for automationFrameworkState=${automationFrameworkState} hookState=${hookState}`)
+ return
+ }
+ args.instance = instance
+ await this.runHooks(instance, automationFrameworkState, hookState, args)
+ }
+
+ /**
+ * Resolve instance for the automation framework
+ * @param {*} automationFrameworkState
+ * @param {*} hookState
+ * @param {*} args
+ * @returns instance
+ */
+ resolveInstance(automationFrameworkState: State, hookState: State, args: Record = {}) {
+ let instance = null
+ logger.info(`resolveInstance: resolving instance for automationFrameworkState=${automationFrameworkState} hookState=${hookState}`)
+ if (automationFrameworkState === AutomationFrameworkState.CREATE || automationFrameworkState === AutomationFrameworkState.NONE) {
+ this.trackWebdriverIOInstance(automationFrameworkState, args)
+ }
+
+ instance = AutomationFramework.getTrackedInstance()
+ return instance
+ }
+
+ /**
+ * Create instance for WebdriverIO
+ * @returns {void}
+ */
+ trackWebdriverIOInstance(automationFrameworkState: State, args: Record = {}) {
+ if (
+ // !args.browser &&
+ AutomationFramework.getTrackedInstance()
+ ) {
+ logger.info('trackWebdriverIOInstance: instance already exists')
+ return
+ }
+
+ const target = CLIUtils.getCurrentInstanceName()
+ const trackedContext = TrackedInstance.createContext(target)
+ let instance = null
+ logger.info(`trackWebdriverIOInstance: created instance for target=${target}, state=${automationFrameworkState}, args=${args}`)
+
+ instance = new AutomationFrameworkInstance(
+ trackedContext,
+ this.getAutomationFrameworkName(),
+ this.getAutomationFrameworkVersion(),
+ automationFrameworkState
+ )
+
+ AutomationFramework.setTrackedInstance(trackedContext, instance)
+ logger.info(`trackWebdriverIOInstance: saved instance contextId=${trackedContext.getId()} target=${target}`)
+ }
+}
diff --git a/packages/browserstack-service/src/cli/frameworks/wdioMochaTestFramework.ts b/packages/browserstack-service/src/cli/frameworks/wdioMochaTestFramework.ts
new file mode 100644
index 0000000..70de2a4
--- /dev/null
+++ b/packages/browserstack-service/src/cli/frameworks/wdioMochaTestFramework.ts
@@ -0,0 +1,376 @@
+import { v4 as uuidv4 } from 'uuid'
+import path from 'node:path'
+
+import TestFramework from './testFramework.js'
+import { TestFrameworkState } from '../states/testFrameworkState.js'
+import { HookState } from '../states/hookState.js'
+import TestFrameworkInstance from '../instances/testFrameworkInstance.js'
+import { CLIUtils } from '../cliUtils.js'
+import TrackedInstance from '../instances/trackedInstance.js'
+import { TestFrameworkConstants } from './constants/testFrameworkConstants.js'
+import { BStackLogger as logger } from '../cliLogger.js'
+import type { Frameworks } from '@wdio/types'
+import { getGitMetaData, getMochaTestHierarchy, getUniqueIdentifier, isUndefined, removeAnsiColors } from '../../util.js'
+import { TEST_ANALYTICS_ID } from '../../constants.js'
+
+export default class WdioMochaTestFramework extends TestFramework {
+ static KEY_HOOK_LAST_STARTED = 'test_hook_last_started'
+ static KEY_HOOK_LAST_FINISHED = 'test_hook_last_finished'
+
+ /**
+ * Constructor for the TestFramework
+ * @param {Array} testFrameworks - List of Test frameworks
+ * @param {Map} testFrameworkVersions - Name of the Test frameworks
+ * @param {string} binSessionId - BinSessionId
+ */
+ constructor(testFrameworks: string[], testFrameworkVersions: Record, binSessionId: string) {
+ super(testFrameworks, testFrameworkVersions, binSessionId)
+ }
+
+ /**
+ * Find instance and track any state for the test framework
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {HookState} hookState
+ * @param {*} args
+ */
+ async trackEvent(testFrameworkState: State, hookState: State, args: Record = {}) {
+ logger.info(`trackEvent: testFrameworkState=${testFrameworkState} hookState=${hookState}`)
+ await super.trackEvent(testFrameworkState, hookState, args)
+
+ const instance = this.resolveInstance(testFrameworkState, hookState, args)
+ if (instance === null) {
+ logger.error(`trackEvent: instance not found for testFrameworkState=${testFrameworkState} hookState=${hookState}`)
+ return
+ }
+
+ try {
+ if (CLIUtils.matchHookRegex(testFrameworkState.toString()) && hookState === HookState.PRE) {
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_HOOK_ID]: uuidv4(),
+ })
+ }
+
+ if (!TestFramework.getState(instance, TestFrameworkConstants.KEY_TEST_ID) && hookState === HookState.PRE && testFrameworkState === TestFrameworkState.TEST) {
+ const test = args.test as Frameworks.Test
+ const testData = await this.getTestData(instance, test)
+ logger.info(`trackEvent: instanceData=${JSON.stringify(Object.fromEntries(instance.getAllData()))}`)
+ instance.updateMultipleEntries(testData)
+ }
+
+ if (testFrameworkState === TestFrameworkState.TEST) {
+ if (hookState === HookState.PRE) {
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_TEST_STARTED_AT]: new Date().toISOString(),
+ })
+ } else if (hookState === HookState.POST) {
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_TEST_ENDED_AT]: new Date().toISOString(),
+ })
+ }
+ } else if (testFrameworkState === TestFrameworkState.LOG) {
+ const logEntry = args.logEntry as Record
+ logEntry.uuid = TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOK_ID)
+ this.loadLogEntries(instance, testFrameworkState, hookState, logEntry)
+ } else if (testFrameworkState === TestFrameworkState.LOG_REPORT && hookState === HookState.POST) {
+ logger.info('trackEvent: load test results')
+ this.loadTestResult(instance, args)
+ }
+
+ await this.trackHookEvents(instance, testFrameworkState, hookState, args)
+ logger.debug(`trackEvent: tracked instance data=${JSON.stringify(Object.fromEntries(instance.getAllData()))}`)
+ } catch (error) {
+ logger.error(`trackEvent: Error in tracking events: ${error} hookState=${hookState} testFrameworkState=${testFrameworkState}`)
+ }
+ args.instance = instance
+ await this.runHooks(instance, testFrameworkState, hookState, args)
+ }
+
+ /**
+ * Resolve instance for the test framework
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {HookState} hookState
+ * @param {*} args
+ * @returns {TestFrameworkInstance}
+ */
+ resolveInstance(testFrameworkState: State, hookState: State, args: Record = {}): TestFrameworkInstance|null {
+ let instance = null
+ logger.info(`resolveInstance: resolving instance for testFrameworkState=${testFrameworkState} hookState=${hookState}`)
+ if (testFrameworkState === TestFrameworkState.INIT_TEST || testFrameworkState === TestFrameworkState.NONE) {
+ this.trackWdioMochaInstance(testFrameworkState, args)
+ }
+
+ instance = TestFramework.getTrackedInstance()
+ this.updateInstanceState(instance, testFrameworkState, hookState)
+
+ return instance
+ }
+
+ /**
+ * Track WebdriverIO instance
+ * @param {TestFrameworkState} testFrameworkState
+ * @param {*} args
+ */
+ trackWdioMochaInstance(testFrameworkState: State, args: Record) {
+ const target = CLIUtils.getCurrentInstanceName()
+ const trackedContext = TrackedInstance.createContext(target)
+ let instance = null
+ logger.info(`trackWdioMochaInstance: created instance for target=${target}, state=${testFrameworkState}, args=${args}`)
+
+ instance = new TestFrameworkInstance(
+ trackedContext,
+ this.getTestFrameworks(),
+ this.getTestFrameworksVersions(),
+ testFrameworkState,
+ HookState.NONE
+ )
+
+ const frameworkName = this.getTestFrameworks()[0]
+
+ const instanceEntries = {
+ [TestFrameworkConstants.KEY_TEST_FRAMEWORK_NAME]: frameworkName,
+ [TestFrameworkConstants.KEY_TEST_FRAMEWORK_VERSION]: this.getTestFrameworksVersions()[frameworkName],
+ [TestFrameworkConstants.KEY_TEST_LOGS]: [],
+ [TestFrameworkConstants.KEY_HOOKS_FINISHED]: new Map(),
+ [TestFrameworkConstants.KEY_HOOKS_STARTED]: new Map(),
+ [TestFrameworkConstants.KEY_TEST_UUID]: uuidv4(),
+ [TestFrameworkConstants.KEY_TEST_RESULT]: TestFrameworkConstants.DEFAULT_TEST_RESULT,
+ // TODO[CLI]: Add customRerunParam
+ // [TestFrameworkConstants.KEY_TEST_RERUN_NAME]:
+ }
+
+ // Setting test uuid in env variable for A11y and App a11y scans
+ process.env[TEST_ANALYTICS_ID] = instanceEntries[TestFrameworkConstants.KEY_TEST_UUID] as string
+
+ instance.updateMultipleEntries(instanceEntries)
+
+ TestFramework.setTrackedInstance(trackedContext, instance)
+ logger.info(`trackWdioMochaInstance: saved instance contextId=${trackedContext.getId()} target=${target}`)
+ }
+
+ async getTestData(instance: TestFrameworkInstance, test: Frameworks.Test) {
+ const framework = TestFramework.getState(instance, TestFrameworkConstants.KEY_TEST_FRAMEWORK_NAME)
+ const fullTitle = getUniqueIdentifier(test, framework)
+ const gitConfig = await getGitMetaData()
+ const filename = test.file // || this._suiteFile
+
+ const testData: Record = {
+ [TestFrameworkConstants.KEY_TEST_ID]: getUniqueIdentifier(test, framework),
+ [TestFrameworkConstants.KEY_TEST_NAME]: test.title || test.description,
+ [TestFrameworkConstants.KEY_TEST_CODE]: test.body || '',
+ [TestFrameworkConstants.KEY_TEST_FILE_PATH]: (gitConfig?.root && filename) ? path.relative(gitConfig.root, filename) : undefined,
+ [TestFrameworkConstants.KEY_TEST_LOCATION]: filename ? path.relative(process.cwd(), filename) : undefined,
+ [TestFrameworkConstants.KEY_TEST_SCOPE]: fullTitle,
+ [TestFrameworkConstants.KEY_TEST_SCOPES]: getMochaTestHierarchy(test),
+ }
+
+ return testData
+ }
+
+ loadTestResult(instance: TestFrameworkInstance, args: Record) {
+ const results = args.result as Frameworks.TestResult
+ const { error, passed, skipped } = results
+ let result = 'passed'
+ let failure: Array|null = null
+ let failureReason: string|null = null
+ let failureType: string|null = null
+ if (!passed) {
+ if (skipped) {
+ result = 'skipped'
+ } else {
+ result = (error && error.message && error.message.includes('sync skip; aborting execution')) ? 'ignore' : 'failed'
+ }
+ if (error && result !== 'skipped') {
+ failure = [{ backtrace: [removeAnsiColors(error.message), removeAnsiColors(error.stack || '')] }] // add all errors here
+ failureReason = removeAnsiColors(error.message)
+ failureType = isUndefined(error.message) ? null : error.message.toString().match(/AssertionError/) ? 'AssertionError' : 'UnhandledError' //verify if this is working
+ }
+ }
+
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_TEST_RESULT]: result,
+ [TestFrameworkConstants.KEY_TEST_FAILURE]: failure,
+ [TestFrameworkConstants.KEY_TEST_FAILURE_REASON]: failureReason,
+ [TestFrameworkConstants.KEY_TEST_FAILURE_TYPE]: failureType,
+ })
+ }
+
+ /**
+ * Load log entries into the test framework instance.
+ * @param instance TestFrameworkInstance
+ * @param testFrameworkState TestFrameworkState
+ * @param hookState HookState
+ * @param args Additional arguments (level, message, etc.)
+ */
+ loadLogEntries(instance: TestFrameworkInstance, testFrameworkState: State, hookState: State, logEntry: Record) {
+ const logRecord: Record = {}
+ const { level, message, timestamp } = logEntry
+
+ if (CLIUtils.matchHookRegex(instance.getCurrentTestState().toString())) {
+ logRecord[TestFrameworkConstants.KEY_HOOK_ID] = TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOK_ID)
+ }
+ logRecord.kind = TestFrameworkConstants.KIND_LOG
+ logRecord.message = Buffer.from(message as string)
+ logRecord.level = level
+ logRecord.timestamp = timestamp
+
+ // Attach to the suitable hook
+ const lastActiveHook = WdioMochaTestFramework.lastActiveHook(instance, WdioMochaTestFramework.KEY_HOOK_LAST_STARTED)
+ if (lastActiveHook) {
+ const hookLogs = lastActiveHook[TestFrameworkConstants.KEY_HOOK_LOGS] as unknown[]
+ hookLogs.push(logRecord)
+ logger.debug(`hooks after update logs ${TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOKS_STARTED)} ${TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOKS_FINISHED)}`)
+ return
+ }
+
+ // Attach to the test instance
+ const entries = TestFramework.getState(instance, TestFrameworkConstants.KEY_TEST_LOGS) as unknown[]
+ entries.push(logRecord)
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_TEST_LOGS]: entries,
+ })
+ }
+
+ /**
+ * Get the last active hook for the given instance and hook key.
+ * @param instance TestFrameworkInstance
+ * @param lastHookKey string
+ * @returns Record | null
+ */
+ static lastActiveHook(instance: TestFrameworkInstance, lastHookKey: string): Record | null {
+ const hookStore = lastHookKey === WdioMochaTestFramework.KEY_HOOK_LAST_FINISHED
+ ? TestFrameworkConstants.KEY_HOOKS_FINISHED
+ : TestFrameworkConstants.KEY_HOOKS_STARTED
+
+ const lastActive = TestFramework.getState(instance, lastHookKey) as string | null
+ let hooksMap: Record | null = null
+
+ if (lastActive) {
+ hooksMap = TestFramework.getState(instance, hookStore) as Record | null
+ }
+
+ if (hooksMap && lastActive && hooksMap[lastActive]) {
+ const lastHooks = hooksMap[lastActive] as unknown[]
+ if (lastHooks.length > 0) {
+ return lastHooks[lastHooks.length - 1] as Record
+ }
+ }
+ return null
+ }
+
+ /**
+ * Clear logs for a specific hook.
+ * @param instance TestFrameworkInstance
+ * @param lastHookKey string
+ */
+ static clearHookLogs(instance: TestFrameworkInstance, lastHookKey: string) {
+ const hook = this.lastActiveHook(instance, lastHookKey)
+ if (hook) {
+ hook[TestFrameworkConstants.KEY_HOOK_LOGS] = []
+ }
+ }
+
+ /**
+ * Clear all logs for the given instance, test framework state, and hook state.
+ * @param instance TestFrameworkInstance
+ * @param testFrameworkState TestFrameworkState
+ * @param hookState HookState
+ */
+ static clearLogs(instance: TestFrameworkInstance, testFrameworkState: State, hookState: State) {
+ const lastHookKey = hookState === HookState.PRE
+ ? WdioMochaTestFramework.KEY_HOOK_LAST_STARTED
+ : WdioMochaTestFramework.KEY_HOOK_LAST_FINISHED
+
+ WdioMochaTestFramework.clearHookLogs(instance, lastHookKey)
+
+ instance.updateMultipleEntries({
+ [TestFrameworkConstants.KEY_TEST_LOGS]: [],
+ })
+ }
+
+ /**
+ * Get all log entries for the given instance, test framework state, and hook state.
+ * @param instance TestFrameworkInstance
+ * @param testFrameworkState TestFrameworkState
+ * @param hookState HookState
+ * @returns unknown[]
+ */
+ static getLogEntries(instance: TestFrameworkInstance, testFrameworkState: State, hookState: State): unknown[] {
+ const lastHookKey = hookState === HookState.PRE
+ ? WdioMochaTestFramework.KEY_HOOK_LAST_STARTED
+ : WdioMochaTestFramework.KEY_HOOK_LAST_FINISHED
+
+ const hook = WdioMochaTestFramework.lastActiveHook(instance, lastHookKey)
+ const entries = hook ? (hook[TestFrameworkConstants.KEY_HOOK_LOGS] as unknown[]) : []
+ const testEntries = TestFramework.getState(instance, TestFrameworkConstants.KEY_TEST_LOGS) as unknown[]
+
+ return [...entries, ...testEntries]
+ }
+
+ /**
+ * Track hook events for the test framework.
+ * @param instance TestFrameworkInstance
+ * @param testFrameworkState TestFrameworkState
+ * @param hookState HookState
+ * @param args Additional arguments (e.g., test result, test method)
+ */
+ async trackHookEvents(
+ instance: TestFrameworkInstance,
+ testFrameworkState: State,
+ hookState: State,
+ args: Record
+ ) {
+ const testResult = args.result as Frameworks.TestResult
+ const test = args.test as Frameworks.Test
+ const key = testFrameworkState.toString()
+
+ const hooksStarted = TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOKS_STARTED) as Map
+ if (!hooksStarted.has(key)) {
+ hooksStarted.set(key, [])
+ }
+
+ const hooksFinished = TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOKS_FINISHED) as Map
+ if (!hooksFinished.has(key)) {
+ hooksFinished.set(key, [])
+ }
+
+ const updates: Record = {
+ [TestFrameworkConstants.KEY_HOOKS_STARTED]: hooksStarted,
+ [TestFrameworkConstants.KEY_HOOKS_FINISHED]: hooksFinished,
+ }
+
+ if (hookState === HookState.PRE) {
+ const gitConfig = await getGitMetaData()
+ const filename = test.file
+ const hook: Record = {
+ key,
+ [TestFrameworkConstants.KEY_HOOK_ID]: TestFramework.getState(instance, TestFrameworkConstants.KEY_HOOK_ID) || '',
+ [TestFrameworkConstants.KEY_HOOK_RESULT]: TestFrameworkConstants.DEFAULT_HOOK_RESULT,
+ [TestFrameworkConstants.KEY_EVENT_STARTED_AT]: new Date().toISOString(),
+ [TestFrameworkConstants.KEY_HOOK_LOGS]: [],
+ [TestFrameworkConstants.KEY_HOOK_NAME]: test.title || test.description,
+ [TestFrameworkConstants.KEY_TEST_FILE_PATH]: (gitConfig?.root && filename) ? path.relative(gitConfig.root, filename) : undefined,
+ [TestFrameworkConstants.KEY_TEST_LOCATION]: filename ? path.relative(process.cwd(), filename) : undefined,
+ }
+ hooksStarted.get(key)?.push(hook)
+ updates[WdioMochaTestFramework.KEY_HOOK_LAST_STARTED] = key
+ logger.info(`Hook Started in PRE key = ${key} & hook = ${JSON.stringify(hook)}`)
+ } else if (hookState === HookState.POST) {
+ const hooksList = hooksStarted.get(key) || []
+ logger.info(`Hook List in Post ${JSON.stringify(hooksList)}`)
+
+ if (hooksList.length > 0) {
+ const hook = hooksList.pop() as Record
+ const result = testResult.status
+ if (result !== TestFrameworkConstants.DEFAULT_HOOK_RESULT) {
+ hook[TestFrameworkConstants.KEY_HOOK_RESULT] = result
+ }
+ hook[TestFrameworkConstants.KEY_EVENT_ENDED_AT] = new Date().toISOString()
+ hooksFinished.get(key)?.push(hook)
+ updates[WdioMochaTestFramework.KEY_HOOK_LAST_FINISHED] = key
+ }
+ }
+
+ instance.updateMultipleEntries(updates)
+ logger.info(`trackHookEvents: hook state=${key}.${hookState}, hooks started=${JSON.stringify(hooksStarted)}, hooks finished=${JSON.stringify(hooksFinished)}`)
+ }
+}
diff --git a/packages/browserstack-service/src/cli/grpcClient.ts b/packages/browserstack-service/src/cli/grpcClient.ts
new file mode 100644
index 0000000..ab3f5db
--- /dev/null
+++ b/packages/browserstack-service/src/cli/grpcClient.ts
@@ -0,0 +1,616 @@
+import path from 'node:path'
+import util, { promisify } from 'node:util'
+
+import { CLIUtils } from './cliUtils.js'
+import {
+ SDKClient,
+ grpcCredentials,
+ grpcChannel,
+ StartBinSessionRequestConstructor,
+ StopBinSessionRequestConstructor,
+ ConnectBinSessionRequestConstructor,
+ TestFrameworkEventRequestConstructor,
+ TestSessionEventRequestConstructor,
+ ExecutionContextConstructor,
+ LogCreatedEventRequestConstructor,
+ // eslint-disable-next-line camelcase
+ LogCreatedEventRequest_LogEntryConstructor,
+ AutomationSessionConstructor,
+ DriverInitRequestConstructor,
+ FetchDriverExecuteParamsEventRequestConstructor
+} from '@browserstack/wdio-browserstack-service'
+
+// Type imports
+import type {
+ StartBinSessionRequest,
+ ConnectBinSessionRequest,
+ TestFrameworkEventRequest,
+ TestSessionEventRequest,
+ LogCreatedEventRequest,
+ LogCreatedEventRequest_LogEntry as LogEntry,
+ DriverInitRequest,
+ FetchDriverExecuteParamsEventRequest,
+ ConnectBinSessionResponse,
+ StartBinSessionResponse,
+ TestFrameworkEventResponse,
+ TestSessionEventResponse,
+ LogCreatedEventResponse,
+ DriverInitResponse,
+ FetchDriverExecuteParamsEventResponse,
+ TestOrchestrationRequest,
+ TestOrchestrationResponse
+} from '@browserstack/wdio-browserstack-service'
+
+import PerformanceTester from '../instrumentation/performance/performance-tester.js'
+import * as PERFORMANCE_SDK_EVENTS from '../instrumentation/performance/constants.js'
+import { BStackLogger } from './cliLogger.js'
+
+const GRPC_MESSAGE_LIMIT = 20 * 1024 * 1024 // 20 MB in bytes
+
+/**
+ * GrpcClient - Singleton class for managing gRPC client connections
+ *
+ * This class uses the singleton pattern to ensure only one gRPC client instance exists
+ * throughout the application lifecycle.
+ */
+export class GrpcClient {
+ static #instance: GrpcClient | null = null
+
+ binSessionId: string | undefined
+ listenAddress: string | undefined
+ channel: grpcChannel | null = null
+ client: SDKClient | null = null
+ logger = BStackLogger
+
+ constructor() { }
+
+ /**
+ * Get the singleton instance of GrpcClient
+ * @returns {GrpcClient} The singleton instance
+ */
+ static getInstance() {
+ if (!GrpcClient.#instance) {
+ GrpcClient.#instance = new GrpcClient()
+ }
+ return GrpcClient.#instance
+ }
+
+ /**
+ * Helper method to get client worker ID from execution context or current context.
+ * This provides a consistent way to extract worker identification across all gRPC calls.
+ *
+ * @param executionContext - Optional execution context with threadId and processId
+ * @returns Worker ID string in format "threadId-processId"
+ */
+ private getClientWorkerIdFromContext(executionContext?: { threadId?: string; processId?: string }): string {
+ return CLIUtils.getClientWorkerId(executionContext)
+ }
+
+ /**
+ * Initialize the gRPC client connection
+ * @param {string} host The gRPC server host
+ * @param {number} port The gRPC server port
+ */
+ init(params: Record) {
+ const { id, listen } = params
+ if (!id || !listen) {
+ throw new Error(`Unable to find listen addr or bin session id binSessionId: ${id} listenAddr: ${listen}`)
+ }
+
+ this.binSessionId = id
+ this.listenAddress = listen
+ process.env.BROWSERSTACK_CLI_BIN_SESSION_ID = this.binSessionId
+ process.env.BROWSERSTACK_CLI_BIN_LISTEN_ADDR = this.listenAddress
+ this.connect()
+ this.logger.info(`Initialized gRPC client with bin session id: ${this.binSessionId} and listen address: ${this.listenAddress}`)
+ }
+
+ /**
+ * Connect to the gRPC server
+ * @returns {void}
+ */
+ connect() {
+ let listenAddress = this.listenAddress
+
+ if (!listenAddress) {
+ listenAddress = process.env.BROWSERSTACK_CLI_BIN_LISTEN_ADDR
+ }
+
+ if (!this.binSessionId) {
+ this.binSessionId = this.binSessionId || process.env.BROWSERSTACK_CLI_BIN_SESSION_ID
+ }
+
+ if (!listenAddress) {
+ throw new Error('Unable to determine gRPC server listen address')
+ }
+
+ const channelOptions = {
+ 'grpc.keepalive_time_ms': 10000,
+ 'grpc.max_send_message_length': GRPC_MESSAGE_LIMIT,
+ 'grpc.max_receive_message_length': GRPC_MESSAGE_LIMIT,
+ }
+
+ // Create a channel
+ this.channel = new grpcChannel(
+ listenAddress,
+ grpcCredentials.createInsecure(),
+ channelOptions
+ )
+
+ // Create a client using the channel
+ this.client = new SDKClient(
+ listenAddress,
+ grpcCredentials.createInsecure(),
+ channelOptions
+ )
+
+ this.logger.info(`Connected to gRPC server at ${listenAddress}`)
+ }
+
+ async startBinSession(wdioConfig: string) {
+ PerformanceTester.start(PERFORMANCE_SDK_EVENTS.EVENTS.SDK_START_BIN_SESSION)
+ this.logger.debug('startBinSession: Calling startBinSession')
+
+ try {
+ if (!this.client) {
+ this.logger.info('No gRPC client not initialized.')
+ }
+
+ const packageVersion = CLIUtils.getSdkVersion()
+ const automationFrameworkDetail = CLIUtils.getAutomationFrameworkDetail()
+ const testFrameworkDetail = CLIUtils.getTestFrameworkDetail()
+ const frameworkVersions = {
+ ...automationFrameworkDetail.version,
+ ...testFrameworkDetail.version
+ }
+
+ // Create StartBinSessionRequest
+ const clientWorkerId = CLIUtils.getClientWorkerId()
+ const request = StartBinSessionRequestConstructor.create({
+ binSessionId: this.binSessionId,
+ sdkLanguage: CLIUtils.getSdkLanguage(),
+ sdkVersion: packageVersion,
+ pathProject: process.cwd(),
+ pathConfig: path.resolve(process.cwd(), 'browserstack.yml'),
+ cliArgs: process.argv.slice(2),
+ frameworks: [automationFrameworkDetail.name, testFrameworkDetail.name],
+ frameworkVersions,
+ language: CLIUtils.getSdkLanguage(),
+ testFramework: testFrameworkDetail.name,
+ wdioConfig: wdioConfig,
+ })
+ // Add clientWorkerId and platformIndex to request (proto fields 500 & 501)
+ ;(request as unknown as Record).clientWorkerId = clientWorkerId
+ ;(request as unknown as Record).platformIndex = '0' // Default platform index for main process
+ this.logger.debug(`StartBinSession with clientWorkerId: ${clientWorkerId}, platformIndex: 0`)
+
+ const startBinSessionPromise = promisify(this.client!.startBinSession).bind(this.client!) as (arg0: StartBinSessionRequest) => Promise
+ try {
+ const response = await startBinSessionPromise(request)
+ this.logger.info('StartBinSession successful')
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.EVENTS.SDK_START_BIN_SESSION)
+ return response
+ } catch (error: unknown) {
+ this.logger.error(`StartBinSession error: ${util.format(error)}`)
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.EVENTS.SDK_START_BIN_SESSION, false, util.format(error))
+ throw error
+ }
+ } catch (error) {
+ this.logger.error(`Error in startBinSession: ${util.format(error)}`)
+ PerformanceTester.end(PERFORMANCE_SDK_EVENTS.EVENTS.SDK_START_BIN_SESSION, false, util.format(error))
+ throw error
+ }
+ }
+
+ /**
+ * Connect to the bin session
+ * @returns {Promise