diff --git a/.gitattributes b/.gitattributes index 4308634e..7c05968e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,5 @@ .gitattributes export-ignore .gitignore export-ignore .npmignore export-ignore -.styleci.yml export-ignore CHANGELOG.md export-ignore RELEASE.md export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 38ca9f83..795082de 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,3 +1,44 @@ # Contribution Guide The Laravel contributing guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). + +# Installation + +This monorepo contains three packages: + +- [laravel-echo](https://www.npmjs.com/package/laravel-echo) +- [@laravel/echo-react](https://www.npmjs.com/package/@laravel/echo-react) +- [@laravel/echo-vue](https://www.npmjs.com/package/@laravel/echo-vue) + +[pnpm](https://pnpm.io/) is used to manage dependencies, the repo is set up as a workspace. Each package lives under `packages/*` + +From the root directory, install dependencies for all packages: + +```bash +pnpm i +``` + +## Running Tests + +Tests are written with [Vitest](https://vitest.dev/). + +To run all tests, from the root directory: + +```bash +pnpm -r run test +``` + +To run tests for an individual package: + +```bash +cd packages/react +pnpm run test +``` + +## Publishing + +This section is really for the benefit of the core maintainers. From the root directory: + +```bash +./release +``` diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yml b/.github/ISSUE_TEMPLATE/1_Bug_report.yml index 7b897a63..5a2f99d6 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yml @@ -51,5 +51,3 @@ body: description: Provide detailed steps to reproduce your issue. If necessary, please provide a GitHub repository to demonstrate your issue using `laravel new bug-report --github="--public"`. validations: required: true - - diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 692ffcb1..9166f5b5 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,10 +2,10 @@ blank_issues_enabled: false contact_links: - name: Feature request url: https://github.com/laravel/echo/pulls - about: 'For ideas or feature requests, send in a pull request' + about: "For ideas or feature requests, send in a pull request" - name: Support Questions & Other url: https://laravel.com/docs/contributions#support-questions - about: 'This repository is only for reporting bugs. If you have a question or need help using the library, click:' + about: "This repository is only for reporting bugs. If you have a question or need help using the library, click:" - name: Documentation issue url: https://github.com/laravel/docs about: For documentation issues, open a pull request at the laravel/docs repository diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fd2a3dca..047b6724 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,12 +13,12 @@ name: codeql on: push: - branches: [ master ] + branches: [master] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [master] schedule: - - cron: '44 23 * * 1' + - cron: "44 23 * * 1" jobs: analyze: @@ -28,40 +28,40 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'javascript' ] + language: ["javascript"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml new file mode 100644 index 00000000..8be6152f --- /dev/null +++ b/.github/workflows/coding-standards.yml @@ -0,0 +1,32 @@ +name: fix code styling + +on: + push: + branches: + - master + - "*.x" + pull_request: + +jobs: + format: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Install dependencies + run: pnpm install + + - name: Format code + run: pnpm run format + + - name: Commit linted files + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Fix code styling" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f3cc0614..34e66023 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,27 +4,32 @@ on: push: branches: - master - - '*.x' + - "*.x" pull_request: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: tests: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + - name: Install dependencies - run: npm install + run: pnpm install + + - name: Build + run: pnpm build - name: ESLint - run: npm run lint + run: pnpm run lint - name: Execute tests - run: npm test - - - name: Run build - run: npm run build + run: pnpm test diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index c23fc26f..00000000 --- a/.styleci.yml +++ /dev/null @@ -1,5 +0,0 @@ -php: - preset: laravel -js: true -css: true -ts: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b321cc..82ab886d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,10 @@ ## [v2.0.2](https://github.com/laravel/echo/compare/v2.0.0...v2.0.2) - 2025-02-18 -* [2.x] Fix TS errors with `skipLibCheck: false` by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/416 +- [2.x] Fix TS errors with `skipLibCheck: false` by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/416 ## v2.0.0 - 2025-02-11 -* Fix TypeScript Error in `isConstructor` by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/412 -* [2.0] Major package upgrades, better TypeScript support, smaller build by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/413 -* [2.x] move tslib to dev deps by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/414 +- Fix TypeScript Error in `isConstructor` by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/412 +- [2.0] Major package upgrades, better TypeScript support, smaller build by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/413 +- [2.x] move tslib to dev deps by [@SanderMuller](https://github.com/SanderMuller) in https://github.com/laravel/echo/pull/414 diff --git a/jest.config.cjs b/jest.config.cjs deleted file mode 100644 index f2461437..00000000 --- a/jest.config.cjs +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - isolatedModules: true - } - ], - }, - extensionsToTreatAsEsm: [".ts"], - testEnvironment: "node", -}; diff --git a/package.json b/package.json index 7a63b3a0..d381878c 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,5 @@ { - "name": "laravel-echo", - "version": "2.0.2", "description": "Laravel Echo library for beautiful Pusher and Socket.IO integration", - "keywords": [ - "laravel", - "pusher", - "ably" - ], "homepage": "https://github.com/laravel/echo", "repository": { "type": "git", @@ -16,67 +9,12 @@ "author": { "name": "Taylor Otwell" }, - "type": "module", - "main": "dist/echo.common.js", - "module": "dist/echo.js", - "types": "dist/echo.d.ts", "scripts": { - "build": "npm run compile && npm run declarations", - "compile": "rollup -c", - "declarations": "tsc --emitDeclarationOnly", - "lint": "eslint --config eslint.config.mjs", - "prepublish": "npm run build", - "release": "npm run test && standard-version && git push --follow-tags && npm publish", - "test": "jest" - }, - "devDependencies": { - "@babel/core": "^7.26.7", - "@babel/plugin-proposal-decorators": "^7.25.9", - "@babel/plugin-proposal-function-sent": "^7.25.9", - "@babel/plugin-proposal-throw-expressions": "^7.25.9", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-assign": "^7.25.9", - "@babel/preset-env": "^7.26.7", - "@rollup/plugin-babel": "^6.0.0", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-typescript": "^12.1.2", - "@types/jest": "^29.5", - "@types/node": "^20.0.0", - "@typescript-eslint/eslint-plugin": "^8.21.0", - "@typescript-eslint/parser": "^8.21.0", - "eslint": "^9.0.0", - "jest": "^29.7.0", - "pusher-js": "^8.0", - "rollup": "^3.0.0", - "socket.io-client": "^4.0", - "standard-version": "^9.3.2", - "ts-jest": "^29.2.5", - "tslib": "^2.8.1", - "typescript": "^5.7.0" - }, - "peerDependencies": { - "socket.io-client": "*", - "pusher-js": "*" - }, - "typesVersions": { - "*": { - "socket.io-client": [], - "pusher-js": [] - } - }, - "engines": { - "node": ">=20" - }, - "exports": { - ".": { - "import": "./dist/echo.js", - "require": "./dist/echo.common.js", - "types": "./dist/echo.d.ts" - }, - "./iife": "./dist/echo.iife.js" - }, - "overrides": { - "glob": "^9.0.0" + "test": "pnpm -r --if-present run test", + "build": "pnpm -r --if-present run build", + "lint": "pnpm -r --if-present run lint", + "format": "pnpm -r --if-present run format", + "compile": "pnpm -r --if-present run compile", + "declarations": "pnpm -r --if-present run declarations" } } diff --git a/eslint.config.mjs b/packages/laravel-echo/eslint.config.mjs similarity index 87% rename from eslint.config.mjs rename to packages/laravel-echo/eslint.config.mjs index c7cacc54..d58a9664 100644 --- a/eslint.config.mjs +++ b/packages/laravel-echo/eslint.config.mjs @@ -1,12 +1,10 @@ -import tsParser from "@typescript-eslint/parser"; import tsPlugin from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; const config = [ { - files: [ - "typings/**/*.ts", - "src/**/*.ts" - ], + ignores: ["dist/**/*"], + files: ["src/**/*.ts"], languageOptions: { parser: tsParser, // Use the imported parser object parserOptions: { @@ -31,7 +29,10 @@ const config = [ "@typescript-eslint/no-unsafe-function-type": "off", "@typescript-eslint/no-unsafe-member-access": "warn", "@typescript-eslint/no-unsafe-return": "warn", - "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], + "@typescript-eslint/no-unused-vars": [ + "warn", + { argsIgnorePattern: "^_" }, + ], "no-console": "warn", "prefer-const": "off", }, diff --git a/packages/laravel-echo/package.json b/packages/laravel-echo/package.json new file mode 100644 index 00000000..4b341e4e --- /dev/null +++ b/packages/laravel-echo/package.json @@ -0,0 +1,77 @@ +{ + "name": "laravel-echo", + "version": "2.0.2", + "description": "Laravel Echo library for beautiful Pusher and Socket.IO integration", + "keywords": [ + "laravel", + "pusher", + "ably" + ], + "homepage": "https://github.com/laravel/echo/tree/2.x/packages/laravel-echo", + "repository": { + "type": "git", + "url": "https://github.com/laravel/echo" + }, + "license": "MIT", + "author": { + "name": "Taylor Otwell" + }, + "type": "module", + "main": "dist/echo.common.js", + "module": "dist/echo.js", + "types": "dist/echo.d.ts", + "scripts": { + "build": "vite build && FORMAT=iife vite build", + "lint": "eslint --config eslint.config.mjs \"src/**/*.ts\"", + "prepublish": "pnpm run build", + "release": "pnpm run test && git push --follow-tags && pnpm publish", + "test": "vitest", + "format": "prettier --write ." + }, + "devDependencies": { + "@babel/core": "^7.26.7", + "@babel/plugin-proposal-decorators": "^7.25.9", + "@babel/plugin-proposal-function-sent": "^7.25.9", + "@babel/plugin-proposal-throw-expressions": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-assign": "^7.25.9", + "@babel/preset-env": "^7.26.7", + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^8.21.0", + "@typescript-eslint/parser": "^8.21.0", + "eslint": "^9.0.0", + "prettier": "^3.5.3", + "pusher-js": "^8.0", + "socket.io-client": "^4.0", + "tslib": "^2.8.1", + "typescript": "^5.7.0", + "vite": "^5.0.0", + "vite-plugin-dts": "^3.0.0", + "vitest": "^3.1.2" + }, + "peerDependencies": { + "pusher-js": "*", + "socket.io-client": "*" + }, + "typesVersions": { + "*": { + "socket.io-client": [], + "pusher-js": [] + } + }, + "engines": { + "node": ">=20" + }, + "exports": { + ".": { + "import": "./dist/echo.js", + "require": "./dist/echo.common.js", + "types": "./dist/echo.d.ts" + }, + "./iife": "./dist/echo.iife.js" + }, + "overrides": { + "glob": "^9.0.0" + } +} diff --git a/src/channel/channel.ts b/packages/laravel-echo/src/channel/channel.ts similarity index 76% rename from src/channel/channel.ts rename to packages/laravel-echo/src/channel/channel.ts index 53b324d5..45e574f6 100644 --- a/src/channel/channel.ts +++ b/packages/laravel-echo/src/channel/channel.ts @@ -1,5 +1,5 @@ -import type { EchoOptionsWithDefaults } from '../connector'; -import type { BroadcastDriver } from '../echo'; +import type { EchoOptionsWithDefaults } from "../connector"; +import type { BroadcastDriver } from "../echo"; /** * This class represents a basic channel. @@ -19,14 +19,17 @@ export abstract class Channel { * Listen for a whisper event on the channel instance. */ listenForWhisper(event: string, callback: CallableFunction): this { - return this.listen('.client-' + event, callback); + return this.listen(".client-" + event, callback); } /** * Listen for an event on the channel instance. */ notification(callback: CallableFunction): this { - return this.listen('.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated', callback); + return this.listen( + ".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated", + callback, + ); } /** @@ -38,7 +41,7 @@ export abstract class Channel { * Stop listening for a whisper event on the channel instance. */ stopListeningForWhisper(event: string, callback?: CallableFunction): this { - return this.stopListening('.client-' + event, callback); + return this.stopListening(".client-" + event, callback); } /** diff --git a/packages/laravel-echo/src/channel/index.ts b/packages/laravel-echo/src/channel/index.ts new file mode 100644 index 00000000..1b134bd9 --- /dev/null +++ b/packages/laravel-echo/src/channel/index.ts @@ -0,0 +1,13 @@ +export * from "./channel"; +export * from "./presence-channel"; +export * from "./pusher-channel"; +export * from "./pusher-private-channel"; +export * from "./pusher-encrypted-private-channel"; +export * from "./pusher-presence-channel"; +export * from "./socketio-channel"; +export * from "./socketio-private-channel"; +export * from "./socketio-presence-channel"; +export * from "./null-channel"; +export * from "./null-private-channel"; +export * from "./null-encrypted-private-channel"; +export * from "./null-presence-channel"; diff --git a/src/channel/null-channel.ts b/packages/laravel-echo/src/channel/null-channel.ts similarity index 97% rename from src/channel/null-channel.ts rename to packages/laravel-echo/src/channel/null-channel.ts index 4b16f974..1804b986 100644 --- a/src/channel/null-channel.ts +++ b/packages/laravel-echo/src/channel/null-channel.ts @@ -1,4 +1,4 @@ -import { Channel } from './channel'; +import { Channel } from "./channel"; /** * This class represents a null channel. diff --git a/src/channel/null-encrypted-private-channel.ts b/packages/laravel-echo/src/channel/null-encrypted-private-channel.ts similarity index 86% rename from src/channel/null-encrypted-private-channel.ts rename to packages/laravel-echo/src/channel/null-encrypted-private-channel.ts index 4f967d11..60020f77 100644 --- a/src/channel/null-encrypted-private-channel.ts +++ b/packages/laravel-echo/src/channel/null-encrypted-private-channel.ts @@ -1,4 +1,4 @@ -import { NullChannel } from './null-channel'; +import { NullChannel } from "./null-channel"; /** * This class represents a null private channel. diff --git a/src/channel/null-presence-channel.ts b/packages/laravel-echo/src/channel/null-presence-channel.ts similarity index 75% rename from src/channel/null-presence-channel.ts rename to packages/laravel-echo/src/channel/null-presence-channel.ts index 6f1abdc4..6dff6027 100644 --- a/src/channel/null-presence-channel.ts +++ b/packages/laravel-echo/src/channel/null-presence-channel.ts @@ -1,10 +1,13 @@ -import { NullPrivateChannel } from './null-private-channel'; -import type { PresenceChannel } from './presence-channel'; +import { NullPrivateChannel } from "./null-private-channel"; +import type { PresenceChannel } from "./presence-channel"; /** * This class represents a null presence channel. */ -export class NullPresenceChannel extends NullPrivateChannel implements PresenceChannel { +export class NullPresenceChannel + extends NullPrivateChannel + implements PresenceChannel +{ /** * Register a callback to be called anytime the member list changes. */ diff --git a/src/channel/null-private-channel.ts b/packages/laravel-echo/src/channel/null-private-channel.ts similarity index 86% rename from src/channel/null-private-channel.ts rename to packages/laravel-echo/src/channel/null-private-channel.ts index 5e61a226..1d1bc60a 100644 --- a/src/channel/null-private-channel.ts +++ b/packages/laravel-echo/src/channel/null-private-channel.ts @@ -1,4 +1,4 @@ -import { NullChannel } from './null-channel'; +import { NullChannel } from "./null-channel"; /** * This class represents a null private channel. diff --git a/src/channel/presence-channel.ts b/packages/laravel-echo/src/channel/presence-channel.ts similarity index 93% rename from src/channel/presence-channel.ts rename to packages/laravel-echo/src/channel/presence-channel.ts index 9202b55a..7c1ee8ad 100644 --- a/src/channel/presence-channel.ts +++ b/packages/laravel-echo/src/channel/presence-channel.ts @@ -1,4 +1,4 @@ -import type { Channel } from './channel'; +import type { Channel } from "./channel"; /** * This interface represents a presence channel. diff --git a/src/channel/pusher-channel.ts b/packages/laravel-echo/src/channel/pusher-channel.ts similarity index 71% rename from src/channel/pusher-channel.ts rename to packages/laravel-echo/src/channel/pusher-channel.ts index e9894115..0e88cd4d 100644 --- a/src/channel/pusher-channel.ts +++ b/packages/laravel-echo/src/channel/pusher-channel.ts @@ -1,14 +1,16 @@ -import { EventFormatter } from '../util'; -import { Channel } from './channel'; -import type Pusher from 'pusher-js'; -import type { Channel as BasePusherChannel } from 'pusher-js'; -import type { EchoOptionsWithDefaults } from '../connector'; -import type { BroadcastDriver } from '../echo'; +import { EventFormatter } from "../util"; +import { Channel } from "./channel"; +import type Pusher from "pusher-js"; +import type { Channel as BasePusherChannel } from "pusher-js"; +import type { EchoOptionsWithDefaults } from "../connector"; +import type { BroadcastDriver } from "../echo"; /** * This class represents a Pusher channel. */ -export class PusherChannel extends Channel { +export class PusherChannel< + TBroadcastDriver extends BroadcastDriver, +> extends Channel { /** * The Pusher client instance. */ @@ -32,7 +34,11 @@ export class PusherChannel extends Cha /** * Create a new class instance. */ - constructor(pusher: Pusher, name: string, options: EchoOptionsWithDefaults) { + constructor( + pusher: Pusher, + name: string, + options: EchoOptionsWithDefaults, + ) { super(); this.name = name; @@ -71,13 +77,18 @@ export class PusherChannel extends Cha */ listenToAll(callback: CallableFunction): this { this.subscription.bind_global((event: string, data: unknown) => { - if (event.startsWith('pusher:')) { + if (event.startsWith("pusher:")) { return; } - let namespace = String(this.options.namespace ?? '').replace(/\./g, '\\'); + let namespace = String(this.options.namespace ?? "").replace( + /\./g, + "\\", + ); - let formattedEvent = event.startsWith(namespace) ? event.substring(namespace.length + 1) : '.' + event; + let formattedEvent = event.startsWith(namespace) + ? event.substring(namespace.length + 1) + : "." + event; callback(formattedEvent, data); }); @@ -90,7 +101,10 @@ export class PusherChannel extends Cha */ stopListening(event: string, callback?: CallableFunction): this { if (callback) { - this.subscription.unbind(this.eventFormatter.format(event), callback); + this.subscription.unbind( + this.eventFormatter.format(event), + callback, + ); } else { this.subscription.unbind(this.eventFormatter.format(event)); } @@ -115,7 +129,7 @@ export class PusherChannel extends Cha * Register a callback to be called anytime a subscription succeeds. */ subscribed(callback: CallableFunction): this { - this.on('pusher:subscription_succeeded', () => { + this.on("pusher:subscription_succeeded", () => { callback(); }); @@ -126,7 +140,7 @@ export class PusherChannel extends Cha * Register a callback to be called anytime a subscription error occurs. */ error(callback: CallableFunction): this { - this.on('pusher:subscription_error', (status: Record) => { + this.on("pusher:subscription_error", (status: Record) => { callback(status); }); diff --git a/src/channel/pusher-encrypted-private-channel.ts b/packages/laravel-echo/src/channel/pusher-encrypted-private-channel.ts similarity index 54% rename from src/channel/pusher-encrypted-private-channel.ts rename to packages/laravel-echo/src/channel/pusher-encrypted-private-channel.ts index f3c2068f..9228d87f 100644 --- a/src/channel/pusher-encrypted-private-channel.ts +++ b/packages/laravel-echo/src/channel/pusher-encrypted-private-channel.ts @@ -1,17 +1,20 @@ -import { PusherChannel } from './pusher-channel'; -import type { BroadcastDriver } from '../echo'; +import { PusherChannel } from "./pusher-channel"; +import type { BroadcastDriver } from "../echo"; /** * This class represents a Pusher private channel. */ export class PusherEncryptedPrivateChannel< - TBroadcastDriver extends BroadcastDriver + TBroadcastDriver extends BroadcastDriver, > extends PusherChannel { /** * Send a whisper event to other clients in the channel. */ whisper(eventName: string, data: Record): this { - this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); + this.pusher.channels.channels[this.name].trigger( + `client-${eventName}`, + data, + ); return this; } diff --git a/src/channel/pusher-presence-channel.ts b/packages/laravel-echo/src/channel/pusher-presence-channel.ts similarity index 68% rename from src/channel/pusher-presence-channel.ts rename to packages/laravel-echo/src/channel/pusher-presence-channel.ts index 83720aae..26f3eeb1 100644 --- a/src/channel/pusher-presence-channel.ts +++ b/packages/laravel-echo/src/channel/pusher-presence-channel.ts @@ -1,6 +1,6 @@ -import type { PresenceChannel } from './presence-channel'; -import { PusherPrivateChannel } from './pusher-private-channel'; -import type { BroadcastDriver } from '../echo'; +import type { PresenceChannel } from "./presence-channel"; +import { PusherPrivateChannel } from "./pusher-private-channel"; +import type { BroadcastDriver } from "../echo"; /** * This class represents a Pusher presence channel. @@ -13,7 +13,7 @@ export class PusherPresenceChannel * Register a callback to be called anytime the member list changes. */ here(callback: CallableFunction): this { - this.on('pusher:subscription_succeeded', (data: Record) => { + this.on("pusher:subscription_succeeded", (data: Record) => { callback(Object.keys(data.members).map((k) => data.members[k])); }); @@ -24,7 +24,7 @@ export class PusherPresenceChannel * Listen for someone joining the channel. */ joining(callback: CallableFunction): this { - this.on('pusher:member_added', (member: Record) => { + this.on("pusher:member_added", (member: Record) => { callback(member.info); }); @@ -35,7 +35,10 @@ export class PusherPresenceChannel * Send a whisper event to other clients in the channel. */ whisper(eventName: string, data: Record): this { - this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); + this.pusher.channels.channels[this.name].trigger( + `client-${eventName}`, + data, + ); return this; } @@ -44,7 +47,7 @@ export class PusherPresenceChannel * Listen for someone leaving the channel. */ leaving(callback: CallableFunction): this { - this.on('pusher:member_removed', (member: Record) => { + this.on("pusher:member_removed", (member: Record) => { callback(member.info); }); diff --git a/packages/laravel-echo/src/channel/pusher-private-channel.ts b/packages/laravel-echo/src/channel/pusher-private-channel.ts new file mode 100644 index 00000000..abaebaba --- /dev/null +++ b/packages/laravel-echo/src/channel/pusher-private-channel.ts @@ -0,0 +1,21 @@ +import { PusherChannel } from "./pusher-channel"; +import type { BroadcastDriver } from "../echo"; + +/** + * This class represents a Pusher private channel. + */ +export class PusherPrivateChannel< + TBroadcastDriver extends BroadcastDriver, +> extends PusherChannel { + /** + * Send a whisper event to other clients in the channel. + */ + whisper(eventName: string, data: Record): this { + this.pusher.channels.channels[this.name].trigger( + `client-${eventName}`, + data, + ); + + return this; + } +} diff --git a/src/channel/socketio-channel.ts b/packages/laravel-echo/src/channel/socketio-channel.ts similarity index 86% rename from src/channel/socketio-channel.ts rename to packages/laravel-echo/src/channel/socketio-channel.ts index 2aed222e..659f59d4 100644 --- a/src/channel/socketio-channel.ts +++ b/packages/laravel-echo/src/channel/socketio-channel.ts @@ -1,8 +1,8 @@ -import { EventFormatter } from '../util'; -import { Channel } from './channel'; -import type { Socket } from 'socket.io-client'; -import type { EchoOptionsWithDefaults } from '../connector'; -import type { BroadcastDriver } from '../echo'; +import { EventFormatter } from "../util"; +import { Channel } from "./channel"; +import type { Socket } from "socket.io-client"; +import type { EchoOptionsWithDefaults } from "../connector"; +import type { BroadcastDriver } from "../echo"; /** * This class represents a Socket.io channel. @@ -36,7 +36,11 @@ export class SocketIoChannel extends Channel { /** * Create a new class instance. */ - constructor(socket: Socket, name: string, options: EchoOptionsWithDefaults) { + constructor( + socket: Socket, + name: string, + options: EchoOptionsWithDefaults, + ) { super(); this.name = name; @@ -51,7 +55,7 @@ export class SocketIoChannel extends Channel { * Subscribe to a Socket.io channel. */ subscribe(): void { - this.socket.emit('subscribe', { + this.socket.emit("subscribe", { channel: this.name, auth: this.options.auth || {}, }); @@ -63,7 +67,7 @@ export class SocketIoChannel extends Channel { unsubscribe(): void { this.unbind(); - this.socket.emit('unsubscribe', { + this.socket.emit("unsubscribe", { channel: this.name, auth: this.options.auth || {}, }); @@ -91,7 +95,7 @@ export class SocketIoChannel extends Channel { * Register a callback to be called anytime a subscription succeeds. */ subscribed(callback: CallableFunction): this { - this.on('connect', (socket: Socket) => { + this.on("connect", (socket: Socket) => { callback(socket); }); @@ -142,7 +146,9 @@ export class SocketIoChannel extends Channel { this.listeners[event] = this.listeners[event] || []; if (callback) { - this.listeners[event] = this.listeners[event].filter((cb) => cb !== callback); + this.listeners[event] = this.listeners[event].filter( + (cb) => cb !== callback, + ); } if (!callback || this.listeners[event].length === 0) { diff --git a/src/channel/socketio-presence-channel.ts b/packages/laravel-echo/src/channel/socketio-presence-channel.ts similarity index 59% rename from src/channel/socketio-presence-channel.ts rename to packages/laravel-echo/src/channel/socketio-presence-channel.ts index a12a1348..da8d8075 100644 --- a/src/channel/socketio-presence-channel.ts +++ b/packages/laravel-echo/src/channel/socketio-presence-channel.ts @@ -1,15 +1,18 @@ -import type { PresenceChannel } from './presence-channel'; -import { SocketIoPrivateChannel } from './socketio-private-channel'; +import type { PresenceChannel } from "./presence-channel"; +import { SocketIoPrivateChannel } from "./socketio-private-channel"; /** * This class represents a Socket.io presence channel. */ -export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements PresenceChannel { +export class SocketIoPresenceChannel + extends SocketIoPrivateChannel + implements PresenceChannel +{ /** * Register a callback to be called anytime the member list changes. */ here(callback: CallableFunction): this { - this.on('presence:subscribed', (members: Record[]) => { + this.on("presence:subscribed", (members: Record[]) => { callback(members.map((m) => m.user_info)); }); @@ -20,7 +23,9 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P * Listen for someone joining the channel. */ joining(callback: CallableFunction): this { - this.on('presence:joining', (member: Record) => callback(member.user_info)); + this.on("presence:joining", (member: Record) => + callback(member.user_info), + ); return this; } @@ -29,7 +34,7 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P * Send a whisper event to other clients in the channel. */ whisper(eventName: string, data: unknown): this { - this.socket.emit('client event', { + this.socket.emit("client event", { channel: this.name, event: `client-${eventName}`, data: data, @@ -42,7 +47,9 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P * Listen for someone leaving the channel. */ leaving(callback: CallableFunction): this { - this.on('presence:leaving', (member: Record) => callback(member.user_info)); + this.on("presence:leaving", (member: Record) => + callback(member.user_info), + ); return this; } diff --git a/src/channel/socketio-private-channel.ts b/packages/laravel-echo/src/channel/socketio-private-channel.ts similarity index 80% rename from src/channel/socketio-private-channel.ts rename to packages/laravel-echo/src/channel/socketio-private-channel.ts index 3d45884b..3f03a19a 100644 --- a/src/channel/socketio-private-channel.ts +++ b/packages/laravel-echo/src/channel/socketio-private-channel.ts @@ -1,4 +1,4 @@ -import { SocketIoChannel } from './socketio-channel'; +import { SocketIoChannel } from "./socketio-channel"; /** * This class represents a Socket.io private channel. @@ -8,7 +8,7 @@ export class SocketIoPrivateChannel extends SocketIoChannel { * Send a whisper event to other clients in the channel. */ whisper(eventName: string, data: unknown): this { - this.socket.emit('client event', { + this.socket.emit("client event", { channel: this.name, event: `client-${eventName}`, data: data, diff --git a/src/connector/connector.ts b/packages/laravel-echo/src/connector/connector.ts similarity index 76% rename from src/connector/connector.ts rename to packages/laravel-echo/src/connector/connector.ts index dfd2053f..3eb2b50d 100644 --- a/src/connector/connector.ts +++ b/packages/laravel-echo/src/connector/connector.ts @@ -1,5 +1,5 @@ -import type { Channel, PresenceChannel } from '../channel'; -import type { BroadcastDriver, EchoOptions } from '../echo'; +import type { Channel, PresenceChannel } from "../channel"; +import type { BroadcastDriver, EchoOptions } from "../echo"; export type EchoOptionsWithDefaults = { broadcaster: TBroadcaster; @@ -24,7 +24,7 @@ export abstract class Connector< TBroadcastDriver extends BroadcastDriver, TPublic extends Channel, TPrivate extends Channel, - TPresence extends PresenceChannel + TPresence extends PresenceChannel, > { /** * Default connector options. @@ -33,16 +33,16 @@ export abstract class Connector< auth: { headers: {}, }, - authEndpoint: '/broadcasting/auth', + authEndpoint: "/broadcasting/auth", userAuthentication: { - endpoint: '/broadcasting/user-auth', + endpoint: "/broadcasting/user-auth", headers: {}, }, csrfToken: null, bearerToken: null, host: null, key: null, - namespace: 'App.Events', + namespace: "App.Events", } as const; /** @@ -71,15 +71,16 @@ export abstract class Connector< let token = this.csrfToken(); if (token) { - this.options.auth.headers['X-CSRF-TOKEN'] = token; - this.options.userAuthentication.headers['X-CSRF-TOKEN'] = token; + this.options.auth.headers["X-CSRF-TOKEN"] = token; + this.options.userAuthentication.headers["X-CSRF-TOKEN"] = token; } token = this.options.bearerToken; if (token) { - this.options.auth.headers['Authorization'] = 'Bearer ' + token; - this.options.userAuthentication.headers['Authorization'] = 'Bearer ' + token; + this.options.auth.headers["Authorization"] = "Bearer " + token; + this.options.userAuthentication.headers["Authorization"] = + "Bearer " + token; } } @@ -89,7 +90,11 @@ export abstract class Connector< protected csrfToken(): null | string { let selector; - if (typeof window !== 'undefined' && typeof window.Laravel !== 'undefined' && window.Laravel.csrfToken) { + if ( + typeof window !== "undefined" && + typeof window.Laravel !== "undefined" && + window.Laravel.csrfToken + ) { return window.Laravel.csrfToken; } @@ -98,11 +103,11 @@ export abstract class Connector< } if ( - typeof document !== 'undefined' && - typeof document.querySelector === 'function' && + typeof document !== "undefined" && + typeof document.querySelector === "function" && (selector = document.querySelector('meta[name="csrf-token"]')) ) { - return selector.getAttribute('content'); + return selector.getAttribute("content"); } return null; diff --git a/packages/laravel-echo/src/connector/index.ts b/packages/laravel-echo/src/connector/index.ts new file mode 100644 index 00000000..92d4ad5e --- /dev/null +++ b/packages/laravel-echo/src/connector/index.ts @@ -0,0 +1,4 @@ +export * from "./connector"; +export * from "./pusher-connector"; +export * from "./socketio-connector"; +export * from "./null-connector"; diff --git a/src/connector/null-connector.ts b/packages/laravel-echo/src/connector/null-connector.ts similarity index 76% rename from src/connector/null-connector.ts rename to packages/laravel-echo/src/connector/null-connector.ts index 34e7012d..ad7eab93 100644 --- a/src/connector/null-connector.ts +++ b/packages/laravel-echo/src/connector/null-connector.ts @@ -1,10 +1,20 @@ -import { Connector } from './connector'; -import { NullChannel, NullPrivateChannel, NullPresenceChannel, NullEncryptedPrivateChannel } from '../channel'; +import { Connector } from "./connector"; +import { + NullChannel, + NullPrivateChannel, + NullPresenceChannel, + NullEncryptedPrivateChannel, +} from "../channel"; /** * This class creates a null connector. */ -export class NullConnector extends Connector<'null', NullChannel, NullPrivateChannel, NullPresenceChannel> { +export class NullConnector extends Connector< + "null", + NullChannel, + NullPrivateChannel, + NullPresenceChannel +> { /** * All of the subscribed channel names. */ @@ -20,7 +30,11 @@ export class NullConnector extends Connector<'null', NullChannel, NullPrivateCha /** * Listen for an event on a channel instance. */ - listen(_name: string, _event: string, _callback: CallableFunction): NullChannel { + listen( + _name: string, + _event: string, + _callback: CallableFunction, + ): NullChannel { return new NullChannel(); } @@ -70,7 +84,7 @@ export class NullConnector extends Connector<'null', NullChannel, NullPrivateCha * Get the socket ID for the connection. */ socketId(): string { - return 'fake-socket-id'; + return "fake-socket-id"; } /** diff --git a/src/connector/pusher-connector.ts b/packages/laravel-echo/src/connector/pusher-connector.ts similarity index 50% rename from src/connector/pusher-connector.ts rename to packages/laravel-echo/src/connector/pusher-connector.ts index 3a5ca507..db495de3 100644 --- a/src/connector/pusher-connector.ts +++ b/packages/laravel-echo/src/connector/pusher-connector.ts @@ -1,8 +1,13 @@ -import { Connector, type EchoOptionsWithDefaults } from './connector'; -import { PusherChannel, PusherPrivateChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel } from '../channel'; -import type Pusher from 'pusher-js'; -import type { Options as PusherOptions } from 'pusher-js'; -import type { BroadcastDriver } from '../echo'; +import type Pusher from "pusher-js"; +import type { Options as PusherJsOptions } from "pusher-js"; +import { + PusherChannel, + PusherEncryptedPrivateChannel, + PusherPresenceChannel, + PusherPrivateChannel, +} from "../channel"; +import type { BroadcastDriver } from "../echo"; +import { Connector, type EchoOptionsWithDefaults } from "./connector"; type AnyPusherChannel = | PusherChannel @@ -10,10 +15,18 @@ type AnyPusherChannel = | PusherEncryptedPrivateChannel | PusherPresenceChannel; +export type PusherOptions = + EchoOptionsWithDefaults & { + key: string; + Pusher?: typeof Pusher; + } & PusherJsOptions; + /** * This class creates a connector to Pusher. */ -export class PusherConnector extends Connector< +export class PusherConnector< + TBroadcastDriver extends BroadcastDriver, +> extends Connector< TBroadcastDriver, PusherChannel, PusherPrivateChannel, @@ -29,23 +42,28 @@ export class PusherConnector extends C */ channels: Record = {}; - options: EchoOptionsWithDefaults & { - key: string; - Pusher?: typeof Pusher; - } & PusherOptions; + options: PusherOptions; /** * Create a fresh Pusher connection. */ connect(): void { - if (typeof this.options.client !== 'undefined') { + if (typeof this.options.client !== "undefined") { this.pusher = this.options.client as Pusher; } else if (this.options.Pusher) { - this.pusher = new this.options.Pusher(this.options.key, this.options); - } else if (typeof window !== 'undefined' && typeof window.Pusher !== 'undefined') { + this.pusher = new this.options.Pusher( + this.options.key, + this.options, + ); + } else if ( + typeof window !== "undefined" && + typeof window.Pusher !== "undefined" + ) { this.pusher = new window.Pusher(this.options.key, this.options); } else { - throw new Error('Pusher client not found. Should be globally available or passed via options.client'); + throw new Error( + "Pusher client not found. Should be globally available or passed via options.client", + ); } } @@ -59,7 +77,11 @@ export class PusherConnector extends C /** * Listen for an event on a channel instance. */ - listen(name: string, event: string, callback: CallableFunction): AnyPusherChannel { + listen( + name: string, + event: string, + callback: CallableFunction, + ): AnyPusherChannel { return this.channel(name).listen(event, callback); } @@ -68,7 +90,11 @@ export class PusherConnector extends C */ channel(name: string): AnyPusherChannel { if (!this.channels[name]) { - this.channels[name] = new PusherChannel(this.pusher, name, this.options); + this.channels[name] = new PusherChannel( + this.pusher, + name, + this.options, + ); } return this.channels[name]; @@ -78,48 +104,66 @@ export class PusherConnector extends C * Get a private channel instance by name. */ privateChannel(name: string): PusherPrivateChannel { - if (!this.channels['private-' + name]) { - this.channels['private-' + name] = new PusherPrivateChannel(this.pusher, 'private-' + name, this.options); + if (!this.channels["private-" + name]) { + this.channels["private-" + name] = new PusherPrivateChannel( + this.pusher, + "private-" + name, + this.options, + ); } - return this.channels['private-' + name] as PusherPrivateChannel; + return this.channels[ + "private-" + name + ] as PusherPrivateChannel; } /** * Get a private encrypted channel instance by name. */ - encryptedPrivateChannel(name: string): PusherEncryptedPrivateChannel { - if (!this.channels['private-encrypted-' + name]) { - this.channels['private-encrypted-' + name] = new PusherEncryptedPrivateChannel( - this.pusher, - 'private-encrypted-' + name, - this.options - ); + encryptedPrivateChannel( + name: string, + ): PusherEncryptedPrivateChannel { + if (!this.channels["private-encrypted-" + name]) { + this.channels["private-encrypted-" + name] = + new PusherEncryptedPrivateChannel( + this.pusher, + "private-encrypted-" + name, + this.options, + ); } - return this.channels['private-encrypted-' + name] as PusherEncryptedPrivateChannel; + return this.channels[ + "private-encrypted-" + name + ] as PusherEncryptedPrivateChannel; } /** * Get a presence channel instance by name. */ presenceChannel(name: string): PusherPresenceChannel { - if (!this.channels['presence-' + name]) { - this.channels['presence-' + name] = new PusherPresenceChannel( + if (!this.channels["presence-" + name]) { + this.channels["presence-" + name] = new PusherPresenceChannel( this.pusher, - 'presence-' + name, - this.options + "presence-" + name, + this.options, ); } - return this.channels['presence-' + name] as PusherPresenceChannel; + return this.channels[ + "presence-" + name + ] as PusherPresenceChannel; } /** * Leave the given channel, as well as its private and presence variants. */ leave(name: string): void { - let channels = [name, 'private-' + name, 'private-encrypted-' + name, 'presence-' + name]; + let channels = [ + name, + "private-" + name, + "private-encrypted-" + name, + "presence-" + name, + ]; channels.forEach((name: string) => { this.leaveChannel(name); diff --git a/src/connector/socketio-connector.ts b/packages/laravel-echo/src/connector/socketio-connector.ts similarity index 56% rename from src/connector/socketio-connector.ts rename to packages/laravel-echo/src/connector/socketio-connector.ts index ad4fdc8a..da127f83 100644 --- a/src/connector/socketio-connector.ts +++ b/packages/laravel-echo/src/connector/socketio-connector.ts @@ -1,14 +1,26 @@ -import { Connector } from './connector'; -import { SocketIoChannel, SocketIoPrivateChannel, SocketIoPresenceChannel } from '../channel'; -import type { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'; - -type AnySocketIoChannel = SocketIoChannel | SocketIoPrivateChannel | SocketIoPresenceChannel; +import { Connector } from "./connector"; +import { + SocketIoChannel, + SocketIoPrivateChannel, + SocketIoPresenceChannel, +} from "../channel"; +import type { + io, + ManagerOptions, + Socket, + SocketOptions, +} from "socket.io-client"; + +type AnySocketIoChannel = + | SocketIoChannel + | SocketIoPrivateChannel + | SocketIoPresenceChannel; /** * This class creates a connector to a Socket.io server. */ export class SocketIoConnector extends Connector< - 'socket.io', + "socket.io", SocketIoChannel, SocketIoPrivateChannel, SocketIoPresenceChannel @@ -29,9 +41,12 @@ export class SocketIoConnector extends Connector< connect(): void { let io = this.getSocketIO(); - this.socket = io(this.options.host ?? undefined, this.options as Partial); + this.socket = io( + this.options.host ?? undefined, + this.options as Partial, + ); - this.socket.on('reconnect', () => { + this.socket.on("reconnect", () => { Object.values(this.channels).forEach((channel) => { channel.subscribe(); }); @@ -42,21 +57,27 @@ export class SocketIoConnector extends Connector< * Get socket.io module from global scope or options. */ getSocketIO(): typeof io { - if (typeof this.options.client !== 'undefined') { + if (typeof this.options.client !== "undefined") { return this.options.client as typeof io; } - if (typeof window !== 'undefined' && typeof window.io !== 'undefined') { + if (typeof window !== "undefined" && typeof window.io !== "undefined") { return window.io; } - throw new Error('Socket.io client not found. Should be globally available or passed via options.client'); + throw new Error( + "Socket.io client not found. Should be globally available or passed via options.client", + ); } /** * Listen for an event on a channel instance. */ - listen(name: string, event: string, callback: CallableFunction): AnySocketIoChannel { + listen( + name: string, + event: string, + callback: CallableFunction, + ): AnySocketIoChannel { return this.channel(name).listen(event, callback); } @@ -65,7 +86,11 @@ export class SocketIoConnector extends Connector< */ channel(name: string): AnySocketIoChannel { if (!this.channels[name]) { - this.channels[name] = new SocketIoChannel(this.socket, name, this.options); + this.channels[name] = new SocketIoChannel( + this.socket, + name, + this.options, + ); } return this.channels[name]; @@ -75,33 +100,37 @@ export class SocketIoConnector extends Connector< * Get a private channel instance by name. */ privateChannel(name: string): SocketIoPrivateChannel { - if (!this.channels['private-' + name]) { - this.channels['private-' + name] = new SocketIoPrivateChannel(this.socket, 'private-' + name, this.options); + if (!this.channels["private-" + name]) { + this.channels["private-" + name] = new SocketIoPrivateChannel( + this.socket, + "private-" + name, + this.options, + ); } - return this.channels['private-' + name] as SocketIoPrivateChannel; + return this.channels["private-" + name] as SocketIoPrivateChannel; } /** * Get a presence channel instance by name. */ presenceChannel(name: string): SocketIoPresenceChannel { - if (!this.channels['presence-' + name]) { - this.channels['presence-' + name] = new SocketIoPresenceChannel( + if (!this.channels["presence-" + name]) { + this.channels["presence-" + name] = new SocketIoPresenceChannel( this.socket, - 'presence-' + name, - this.options + "presence-" + name, + this.options, ); } - return this.channels['presence-' + name] as SocketIoPresenceChannel; + return this.channels["presence-" + name] as SocketIoPresenceChannel; } /** * Leave the given channel, as well as its private and presence variants. */ leave(name: string): void { - let channels = [name, 'private-' + name, 'presence-' + name]; + let channels = [name, "private-" + name, "presence-" + name]; channels.forEach((name) => { this.leaveChannel(name); diff --git a/src/echo.ts b/packages/laravel-echo/src/echo.ts similarity index 54% rename from src/echo.ts rename to packages/laravel-echo/src/echo.ts index c0729606..4c2130c1 100644 --- a/src/echo.ts +++ b/packages/laravel-echo/src/echo.ts @@ -4,7 +4,6 @@ import { NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, - type PresenceChannel, PusherChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, @@ -12,9 +11,16 @@ import { SocketIoChannel, SocketIoPresenceChannel, SocketIoPrivateChannel, -} from './channel'; -import { Connector, PusherConnector, SocketIoConnector, NullConnector } from './connector'; -import { isConstructor } from './util'; + type PresenceChannel, +} from "./channel"; +import { + Connector, + NullConnector, + PusherConnector, + SocketIoConnector, + type PusherOptions, +} from "./connector"; +import { isConstructor } from "./util"; /** * This class is the primary API for interacting with broadcasting. @@ -23,7 +29,7 @@ export default class Echo { /** * The broadcasting connector. */ - connector: Broadcaster[Exclude]['connector']; + connector: Broadcaster[Exclude]["connector"]; /** * The Echo options. @@ -45,7 +51,7 @@ export default class Echo { /** * Get a channel instance by name. */ - channel(channel: string): Broadcaster[T]['public'] { + channel(channel: string): Broadcaster[T]["public"] { return this.connector.channel(channel); } @@ -53,22 +59,30 @@ export default class Echo { * Create a new connection. */ connect(): void { - if (this.options.broadcaster === 'reverb') { - this.connector = new PusherConnector({ + if (this.options.broadcaster === "reverb") { + this.connector = new PusherConnector<"reverb">({ ...this.options, - cluster: '', - } as EchoOptions<'reverb'>); - } else if (this.options.broadcaster === 'pusher') { - this.connector = new PusherConnector(this.options as EchoOptions<'pusher'>); - } else if (this.options.broadcaster === 'socket.io') { - this.connector = new SocketIoConnector(this.options as EchoOptions<'socket.io'>); - } else if (this.options.broadcaster === 'null') { - this.connector = new NullConnector(this.options as EchoOptions<'null'>); - } else if (typeof this.options.broadcaster === 'function' && isConstructor(this.options.broadcaster)) { - this.connector = new this.options.broadcaster(this.options as EchoOptions<'function'>); + cluster: "", + }); + } else if (this.options.broadcaster === "pusher") { + this.connector = new PusherConnector<"pusher">(this.options); + } else if (this.options.broadcaster === "ably") { + this.connector = new PusherConnector<"pusher">({ + ...this.options, + broadcaster: "pusher", + }); + } else if (this.options.broadcaster === "socket.io") { + this.connector = new SocketIoConnector(this.options); + } else if (this.options.broadcaster === "null") { + this.connector = new NullConnector(this.options); + } else if ( + typeof this.options.broadcaster === "function" && + isConstructor(this.options.broadcaster) + ) { + this.connector = new this.options.broadcaster(this.options); } else { throw new Error( - `Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} is not supported.` + `Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} is not supported.`, ); } } @@ -83,7 +97,7 @@ export default class Echo { /** * Get a presence channel instance by name. */ - join(channel: string): Broadcaster[T]['presence'] { + join(channel: string): Broadcaster[T]["presence"] { return this.connector.presenceChannel(channel); } @@ -113,36 +127,43 @@ export default class Echo { /** * Listen for an event on a channel instance. */ - listen(channel: string, event: string, callback: CallableFunction): Broadcaster[T]['public'] { + listen( + channel: string, + event: string, + callback: CallableFunction, + ): Broadcaster[T]["public"] { return this.connector.listen(channel, event, callback); } /** * Get a private channel instance by name. */ - private(channel: string): Broadcaster[T]['private'] { + private(channel: string): Broadcaster[T]["private"] { return this.connector.privateChannel(channel); } /** * Get a private encrypted channel instance by name. */ - encryptedPrivate(channel: string): Broadcaster[T]['encrypted'] { + encryptedPrivate(channel: string): Broadcaster[T]["encrypted"] { if (this.connectorSupportsEncryptedPrivateChannels(this.connector)) { return this.connector.encryptedPrivateChannel(channel); } throw new Error( `Broadcaster ${typeof this.options.broadcaster} ${String( - this.options.broadcaster - )} does not support encrypted private channels.` + this.options.broadcaster, + )} does not support encrypted private channels.`, ); } private connectorSupportsEncryptedPrivateChannels( - connector: unknown + connector: unknown, ): connector is PusherConnector | NullConnector { - return connector instanceof PusherConnector || connector instanceof NullConnector; + return ( + connector instanceof PusherConnector || + connector instanceof NullConnector + ); } /** @@ -157,19 +178,19 @@ export default class Echo { * send a connections socket id to a Laravel app with a X-Socket-Id header. */ registerInterceptors(): void { - if (typeof Vue === 'function' && Vue.http) { + if (typeof Vue === "function" && Vue.http) { this.registerVueRequestInterceptor(); } - if (typeof axios === 'function') { + if (typeof axios === "function") { this.registerAxiosRequestInterceptor(); } - if (typeof jQuery === 'function') { + if (typeof jQuery === "function") { this.registerjQueryAjaxSetup(); } - if (typeof Turbo === 'object') { + if (typeof Turbo === "object") { this.registerTurboRequestInterceptor(); } } @@ -178,13 +199,15 @@ export default class Echo { * Register a Vue HTTP interceptor to add the X-Socket-ID header. */ registerVueRequestInterceptor(): void { - Vue.http.interceptors.push((request: Record, next: CallableFunction) => { - if (this.socketId()) { - request.headers.set('X-Socket-ID', this.socketId()); - } + Vue.http.interceptors.push( + (request: Record, next: CallableFunction) => { + if (this.socketId()) { + request.headers.set("X-Socket-ID", this.socketId()); + } - next(); - }); + next(); + }, + ); } /** @@ -193,7 +216,7 @@ export default class Echo { registerAxiosRequestInterceptor(): void { axios.interceptors.request.use((config: Record) => { if (this.socketId()) { - config.headers['X-Socket-Id'] = this.socketId(); + config.headers["X-Socket-Id"] = this.socketId(); } return config; @@ -204,12 +227,18 @@ export default class Echo { * Register jQuery AjaxPrefilter to add the X-Socket-ID header. */ registerjQueryAjaxSetup(): void { - if (typeof jQuery.ajax != 'undefined') { - jQuery.ajaxPrefilter((_options: any, _originalOptions: any, xhr: Record) => { - if (this.socketId()) { - xhr.setRequestHeader('X-Socket-Id', this.socketId()); - } - }); + if (typeof jQuery.ajax != "undefined") { + jQuery.ajaxPrefilter( + ( + _options: any, + _originalOptions: any, + xhr: Record, + ) => { + if (this.socketId()) { + xhr.setRequestHeader("X-Socket-Id", this.socketId()); + } + }, + ); } } @@ -217,43 +246,63 @@ export default class Echo { * Register the Turbo Request interceptor to add the X-Socket-ID header. */ registerTurboRequestInterceptor(): void { - document.addEventListener('turbo:before-fetch-request', (event: Record) => { - event.detail.fetchOptions.headers['X-Socket-Id'] = this.socketId(); - }); + document.addEventListener( + "turbo:before-fetch-request", + (event: Record) => { + event.detail.fetchOptions.headers["X-Socket-Id"] = + this.socketId(); + }, + ); } } /** * Export channel classes for TypeScript. */ -export { Connector, Channel, type PresenceChannel }; +export { Channel, Connector, type PresenceChannel }; + +export { EventFormatter } from "./util"; -export { EventFormatter } from './util'; +type CustomOmit = { + [P in keyof T as Exclude]: T[P]; +}; /** * Specifies the broadcaster */ export type Broadcaster = { reverb: { - connector: PusherConnector<'reverb'>; - public: PusherChannel<'reverb'>; - private: PusherPrivateChannel<'reverb'>; - encrypted: PusherEncryptedPrivateChannel<'reverb'>; - presence: PusherPresenceChannel<'reverb'>; + connector: PusherConnector<"reverb">; + public: PusherChannel<"reverb">; + private: PusherPrivateChannel<"reverb">; + encrypted: PusherEncryptedPrivateChannel<"reverb">; + presence: PusherPresenceChannel<"reverb">; + options: GenericOptions<"reverb"> & + Partial, "cluster">>; }; pusher: { - connector: PusherConnector<'pusher'>; - public: PusherChannel<'pusher'>; - private: PusherPrivateChannel<'pusher'>; - encrypted: PusherEncryptedPrivateChannel<'pusher'>; - presence: PusherPresenceChannel<'pusher'>; + connector: PusherConnector<"pusher">; + public: PusherChannel<"pusher">; + private: PusherPrivateChannel<"pusher">; + encrypted: PusherEncryptedPrivateChannel<"pusher">; + presence: PusherPresenceChannel<"pusher">; + options: GenericOptions<"pusher"> & Partial>; }; - 'socket.io': { + ably: { + connector: PusherConnector<"pusher">; + public: PusherChannel<"pusher">; + private: PusherPrivateChannel<"pusher">; + encrypted: PusherEncryptedPrivateChannel<"pusher">; + presence: PusherPresenceChannel<"pusher">; + options: GenericOptions<"ably"> & Partial>; + }; + "socket.io": { connector: SocketIoConnector; public: SocketIoChannel; private: SocketIoPrivateChannel; encrypted: never; presence: SocketIoPresenceChannel; + options: GenericOptions<"socket.io">; }; null: { connector: NullConnector; @@ -261,6 +310,7 @@ export type Broadcaster = { private: NullPrivateChannel; encrypted: NullEncryptedPrivateChannel; presence: NullPresenceChannel; + options: GenericOptions<"null">; }; function: { connector: any; @@ -268,19 +318,20 @@ export type Broadcaster = { private: any; encrypted: any; presence: any; + options: GenericOptions<"function">; }; }; type Constructor = new (...args: any[]) => T; -export type BroadcastDriver = Exclude; +export type BroadcastDriver = Exclude; -export type EchoOptions = { +type GenericOptions = { /** * The broadcast connector. */ - broadcaster: TBroadcaster extends 'function' - ? Constructor> + broadcaster: TBroadcaster extends "function" + ? Constructor> : TBroadcaster; auth?: { @@ -299,3 +350,6 @@ export type EchoOptions = { [key: string]: any; }; + +export type EchoOptions = + Broadcaster[TBroadcaster]["options"]; diff --git a/packages/laravel-echo/src/index.iife.ts b/packages/laravel-echo/src/index.iife.ts new file mode 100644 index 00000000..542dd08e --- /dev/null +++ b/packages/laravel-echo/src/index.iife.ts @@ -0,0 +1 @@ +export { default } from "./echo"; diff --git a/src/util/event-formatter.ts b/packages/laravel-echo/src/util/event-formatter.ts similarity index 78% rename from src/util/event-formatter.ts rename to packages/laravel-echo/src/util/event-formatter.ts index 27f624c4..14d93b0c 100644 --- a/src/util/event-formatter.ts +++ b/packages/laravel-echo/src/util/event-formatter.ts @@ -13,13 +13,13 @@ export class EventFormatter { * Format the given event name. */ format(event: string): string { - if (['.', '\\'].includes(event.charAt(0))) { + if ([".", "\\"].includes(event.charAt(0))) { return event.substring(1); } else if (this.namespace) { - event = this.namespace + '.' + event; + event = this.namespace + "." + event; } - return event.replace(/\./g, '\\'); + return event.replace(/\./g, "\\"); } /** diff --git a/src/util/index.ts b/packages/laravel-echo/src/util/index.ts similarity index 61% rename from src/util/index.ts rename to packages/laravel-echo/src/util/index.ts index 2635f064..e26a33e1 100644 --- a/src/util/index.ts +++ b/packages/laravel-echo/src/util/index.ts @@ -2,7 +2,10 @@ function isConstructor(obj: unknown): obj is new (...args: any[]) => any { try { new (obj as new (...args: any[]) => any)(); } catch (err) { - if (err instanceof Error && err.message.includes('is not a constructor')) { + if ( + err instanceof Error && + err.message.includes("is not a constructor") + ) { return false; } } @@ -11,4 +14,4 @@ function isConstructor(obj: unknown): obj is new (...args: any[]) => any { } export { isConstructor }; -export * from './event-formatter'; +export * from "./event-formatter"; diff --git a/packages/laravel-echo/tests/channel/socketio-channel.test.ts b/packages/laravel-echo/tests/channel/socketio-channel.test.ts new file mode 100644 index 00000000..98d42f48 --- /dev/null +++ b/packages/laravel-echo/tests/channel/socketio-channel.test.ts @@ -0,0 +1,94 @@ +import type { Socket } from "socket.io-client"; +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { SocketIoChannel } from "../../src/channel"; +import { Connector } from "../../src/connector"; + +describe("SocketIoChannel", () => { + let channel: SocketIoChannel; + let socket: Socket; + + beforeEach(() => { + const channelName = "some.channel"; + let listeners: any[] = []; + socket = { + emit: (event: any, data: unknown) => { + listeners + .filter(([e]) => e === event) + .forEach(([, fn]) => fn(channelName, data)); + }, + on: (event: any, fn): any => listeners.push([event, fn]), + removeListener: (event: any, fn: any) => { + listeners = listeners.filter(([e, f]) => + !fn ? e !== event : e !== event || f !== fn, + ); + }, + } as Socket; + + channel = new SocketIoChannel(socket, channelName, { + broadcaster: "socket.io", + ...Connector._defaultOptions, + namespace: false, + }); + }); + + test("triggers all listeners for an event", () => { + const l1 = vi.fn(); + const l2 = vi.fn(); + const l3 = vi.fn(); + channel.listen("MyEvent", l1); + channel.listen("MyEvent", l2); + channel.listen("MyOtherEvent", l3); + + socket.emit("MyEvent", {}); + + expect(l1).toHaveBeenCalled(); + expect(l2).toHaveBeenCalled(); + expect(l3).not.toHaveBeenCalled(); + + socket.emit("MyOtherEvent", {}); + + expect(l3).toHaveBeenCalled(); + }); + + test("can remove a listener for an event", () => { + const l1 = vi.fn(); + const l2 = vi.fn(); + const l3 = vi.fn(); + channel.listen("MyEvent", l1); + channel.listen("MyEvent", l2); + channel.listen("MyOtherEvent", l3); + + channel.stopListening("MyEvent", l1); + + socket.emit("MyEvent", {}); + + expect(l1).not.toHaveBeenCalled(); + expect(l2).toHaveBeenCalled(); + expect(l3).not.toHaveBeenCalled(); + + socket.emit("MyOtherEvent", {}); + + expect(l3).toHaveBeenCalled(); + }); + + test("can remove all listeners for an event", () => { + const l1 = vi.fn(); + const l2 = vi.fn(); + const l3 = vi.fn(); + channel.listen("MyEvent", l1); + channel.listen("MyEvent", l2); + channel.listen("MyOtherEvent", l3); + + channel.stopListening("MyEvent"); + + socket.emit("MyEvent", {}); + + expect(l1).not.toHaveBeenCalled(); + expect(l2).not.toHaveBeenCalled(); + expect(l3).not.toHaveBeenCalled(); + + socket.emit("MyOtherEvent", {}); + + expect(l3).toHaveBeenCalled(); + }); +}); diff --git a/packages/laravel-echo/tests/echo.test.ts b/packages/laravel-echo/tests/echo.test.ts new file mode 100644 index 00000000..b31ffcf0 --- /dev/null +++ b/packages/laravel-echo/tests/echo.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, test } from "vitest"; +import { NullConnector } from "../src/connector"; +import Echo from "../src/echo"; + +describe("Echo", () => { + test("it will not throw error for supported driver", () => { + expect(() => new Echo({ broadcaster: "reverb" })).not.toThrow( + "Broadcaster string reverb is not supported.", + ); + + expect(() => new Echo({ broadcaster: "pusher" })).not.toThrow( + "Broadcaster string pusher is not supported.", + ); + + expect(() => new Echo({ broadcaster: "socket.io" })).not.toThrow( + "Broadcaster string socket.io is not supported.", + ); + + expect(() => new Echo({ broadcaster: "null" })).not.toThrow( + "Broadcaster string null is not supported.", + ); + expect(() => new Echo({ broadcaster: NullConnector })).not.toThrow(); + + // eslint-disable-next-line + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-empty-function + expect(() => new Echo({ broadcaster: () => {} })).not.toThrow( + "Broadcaster function is not supported.", + ); + }); + + test("it will throw error for unsupported driver", () => { + // eslint-disable-next-line + // @ts-ignore + expect(() => new Echo({ broadcaster: "foo" })).toThrow( + "Broadcaster string foo is not supported.", + ); + }); +}); diff --git a/packages/laravel-echo/tests/util/event-formatter.test.ts b/packages/laravel-echo/tests/util/event-formatter.test.ts new file mode 100644 index 00000000..69dfc66b --- /dev/null +++ b/packages/laravel-echo/tests/util/event-formatter.test.ts @@ -0,0 +1,48 @@ +import { beforeEach, describe, expect, test } from "vitest"; +import { EventFormatter } from "../../src/util"; + +describe("EventFormatter", () => { + let eventFormatter: EventFormatter; + + beforeEach(() => { + eventFormatter = new EventFormatter("App.Events"); + }); + + test("prepends an event with a namespace and replaces dot separators with backslashes", () => { + let formatted = eventFormatter.format("Users.UserCreated"); + + expect(formatted).toBe("App\\Events\\Users\\UserCreated"); + }); + + test("does not prepend a namespace when an event starts with a dot", () => { + let formatted = eventFormatter.format(".App\\Users\\UserCreated"); + + expect(formatted).toBe("App\\Users\\UserCreated"); + }); + + test("does not prepend a namespace when an event starts with a backslash", () => { + let formatted = eventFormatter.format("\\App\\Users\\UserCreated"); + + expect(formatted).toBe("App\\Users\\UserCreated"); + }); + + test("does not replace dot separators when the event starts with a dot", () => { + let formatted = eventFormatter.format(".users.created"); + + expect(formatted).toBe("users.created"); + }); + + test("does not replace dot separators when the event starts with a backslash", () => { + let formatted = eventFormatter.format("\\users.created"); + + expect(formatted).toBe("users.created"); + }); + + test("does not prepend a namespace when none is set", () => { + let eventFormatter = new EventFormatter(false); + + let formatted = eventFormatter.format("Users.UserCreated"); + + expect(formatted).toBe("Users\\UserCreated"); + }); +}); diff --git a/tsconfig.json b/packages/laravel-echo/tsconfig.json similarity index 69% rename from tsconfig.json rename to packages/laravel-echo/tsconfig.json index 65af0a48..e96a3f49 100644 --- a/tsconfig.json +++ b/packages/laravel-echo/tsconfig.json @@ -18,20 +18,9 @@ "emitDecoratorMetadata": true, "esModuleInterop": true, "strict": true, - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "dom", - "es2020" - ] + "typeRoots": ["node_modules/@types"], + "lib": ["dom", "es2020"] }, - "include": [ - "./typings/**/*.ts", - "./src/**/*.ts" - ], - "exclude": [ - "./node_modules", - "./tests/**/*.ts" - ] + "include": ["./typings/**/*.ts", "./src/**/*.ts"], + "exclude": ["./node_modules", "./tests/**/*.ts"] } diff --git a/typings/index.d.ts b/packages/laravel-echo/typings/index.d.ts similarity index 100% rename from typings/index.d.ts rename to packages/laravel-echo/typings/index.d.ts diff --git a/typings/window.d.ts b/packages/laravel-echo/typings/window.d.ts similarity index 69% rename from typings/window.d.ts rename to packages/laravel-echo/typings/window.d.ts index 2976ba82..b84c1f77 100644 --- a/typings/window.d.ts +++ b/packages/laravel-echo/typings/window.d.ts @@ -1,5 +1,5 @@ -import type { io } from 'socket.io-client'; -import type Pusher from 'pusher-js'; +import type { io } from "socket.io-client"; +import type Pusher from "pusher-js"; export {}; diff --git a/packages/laravel-echo/vite.config.ts b/packages/laravel-echo/vite.config.ts new file mode 100644 index 00000000..b7675207 --- /dev/null +++ b/packages/laravel-echo/vite.config.ts @@ -0,0 +1,52 @@ +import { resolve } from "path"; +import { defineConfig, UserConfig } from "vite"; +import dts from "vite-plugin-dts"; + +const config: UserConfig = (() => { + const common: Partial = { + rollupOptions: { + external: ["pusher-js", "socket.io-client"], + output: { + globals: { + "pusher-js": "Pusher", + "socket.io-client": "io", + }, + }, + }, + outDir: resolve(__dirname, "dist"), + sourcemap: true, + minify: true, + }; + + if (process.env.FORMAT === "iife") { + return { + build: { + lib: { + entry: resolve(__dirname, "src/echo.ts"), + name: "Echo", + formats: ["iife"], + fileName: () => "echo.iife.js", + }, + ...common, + emptyOutDir: false, // Don't empty the output directory for the second build + }, + }; + } + + return { + plugins: [dts()], + build: { + lib: { + entry: resolve(__dirname, "src/echo.ts"), + formats: ["es", "cjs"], + fileName: (format, entryName) => { + return `${entryName}.${format === "es" ? "js" : "common.js"}`; + }, + }, + emptyOutDir: true, + ...common, + }, + }; +})(); + +export default defineConfig(config); diff --git a/packages/react/README.md b/packages/react/README.md new file mode 100644 index 00000000..0fc48ffc --- /dev/null +++ b/packages/react/README.md @@ -0,0 +1,106 @@ +# Laravel Echo React Helpers + +## `configureEcho` + +You must call this function somewhere in your app _before_ you use `useEcho` in a component to configure your Echo instance. You only need to pass the required data: + +```ts +import { configureEcho } from "@laravel/echo-react"; + +configureEcho({ + broadcaster: "reverb", +}); +``` + +Based on your brodcaster, the package will fill in appropriate defaults for the rest of the config [based on the Echo documentation](https://laravel.com/docs/broadcasting#client-side-installation). You can always override these values by simply passing in your own. + +In the above example, the configuration would also fill in the following keys if they aren't present: + +```ts +{ + key: import.meta.env.VITE_REVERB_APP_KEY, + wsHost: import.meta.env.VITE_REVERB_HOST, + wsPort: import.meta.env.VITE_REVERB_PORT, + wssPort: import.meta.env.VITE_REVERB_PORT, + forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', + enabledTransports: ['ws', 'wss'], +} +``` + +## `useEcho` Hook + +Connect to private channel: + +```ts +import { useEcho } from "@laravel/echo-react"; + +const { leaveChannel, leave } = useEcho( + `orders.${orderId}`, + "OrderShipmentStatusUpdated", + (e) => { + console.log(e.order); + }, +); + +// Leave channel +leaveChannel(); + +// Leave a channel and also its associated private and presence channels +leave(); +``` + +Multiple events: + +```ts +useEcho( + `orders.${orderId}`, + ["OrderShipmentStatusUpdated", "OrderShipped"], + (e) => { + console.log(e.order); + }, +); +``` + +All events: + +```ts +useEcho(`orders.${orderId}`, "*", (e) => { + console.log(e.order); +}); +``` + +Specify shape of payload data: + +```ts +type OrderData = { + order: { + id: number; + user: { + id: number; + name: string; + }; + created_at: string; + }; +}; + +useEcho(`orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { + console.log(e.order.id); + console.log(e.order.user.id); +}); +``` + +Connect to public channel: + +```ts +useEchoPublic("posts", "PostPublished", (e) => { + console.log(e.post); +}); +``` + +Connect to presence channel: + +```ts +useEchoPresence("posts", "PostPublished", (e) => { + console.log(e.post); +}); +``` diff --git a/packages/react/eslint.config.mjs b/packages/react/eslint.config.mjs new file mode 100644 index 00000000..d58a9664 --- /dev/null +++ b/packages/react/eslint.config.mjs @@ -0,0 +1,42 @@ +import tsPlugin from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; + +const config = [ + { + ignores: ["dist/**/*"], + files: ["src/**/*.ts"], + languageOptions: { + parser: tsParser, // Use the imported parser object + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + project: "./tsconfig.json", // Path to your TypeScript configuration file + }, + }, + plugins: { + "@typescript-eslint": tsPlugin, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + ...tsPlugin.configs["recommended-requiring-type-checking"].rules, + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-unsafe-argument": "warn", + "@typescript-eslint/no-unsafe-assignment": "warn", + "@typescript-eslint/no-unsafe-call": "warn", + "@typescript-eslint/no-unsafe-function-type": "off", + "@typescript-eslint/no-unsafe-member-access": "warn", + "@typescript-eslint/no-unsafe-return": "warn", + "@typescript-eslint/no-unused-vars": [ + "warn", + { argsIgnorePattern: "^_" }, + ], + "no-console": "warn", + "prefer-const": "off", + }, + }, +]; + +export default config; diff --git a/packages/react/package.json b/packages/react/package.json new file mode 100644 index 00000000..1de3cead --- /dev/null +++ b/packages/react/package.json @@ -0,0 +1,87 @@ +{ + "name": "@laravel/echo-react", + "version": "2.0.2", + "description": "Laravel Echo library for beautiful Pusher and Socket.IO integration", + "keywords": [ + "laravel", + "pusher", + "ably", + "react" + ], + "homepage": "https://github.com/laravel/echotree/2.x/packages/react", + "repository": { + "type": "git", + "url": "https://github.com/laravel/echo" + }, + "license": "MIT", + "author": { + "name": "Taylor Otwell" + }, + "type": "module", + "main": "dist/echo.common.js", + "module": "dist/echo.js", + "types": "dist/echo.d.ts", + "scripts": { + "build": "vite build && FORMAT=iife vite build", + "lint": "eslint --config eslint.config.mjs \"src/**/*.ts\"", + "prepublish": "pnpm run build", + "release": "pnpm run test && git push --follow-tags && pnpm publish", + "test": "vitest", + "format": "prettier --write ." + }, + "devDependencies": { + "@babel/core": "^7.26.7", + "@babel/plugin-proposal-decorators": "^7.25.9", + "@babel/plugin-proposal-function-sent": "^7.25.9", + "@babel/plugin-proposal-throw-expressions": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-assign": "^7.25.9", + "@babel/preset-env": "^7.26.7", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^14.3.1", + "@testing-library/react-hooks": "^8.0.1", + "@types/node": "^20.0.0", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@typescript-eslint/eslint-plugin": "^8.21.0", + "@typescript-eslint/parser": "^8.21.0", + "eslint": "^9.0.0", + "jsdom": "^26.1.0", + "laravel-echo": "workspace:^", + "prettier": "^3.5.3", + "pusher-js": "^8.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "socket.io-client": "^4.0", + "tslib": "^2.8.1", + "typescript": "^5.7.0", + "vite": "^5.1.0", + "vite-plugin-dts": "^3.7.0", + "vitest": "^3.1.2" + }, + "peerDependencies": { + "pusher-js": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "socket.io-client": "*" + }, + "typesVersions": { + "*": { + "socket.io-client": [], + "pusher-js": [] + } + }, + "engines": { + "node": ">=20" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.common.js" + } + }, + "overrides": { + "glob": "^9.0.0" + } +} diff --git a/packages/react/src/hook/use-echo.ts b/packages/react/src/hook/use-echo.ts new file mode 100644 index 00000000..5211ef68 --- /dev/null +++ b/packages/react/src/hook/use-echo.ts @@ -0,0 +1,334 @@ +import Echo, { + type BroadcastDriver, + type Broadcaster, + type EchoOptions, +} from "laravel-echo"; +import Pusher from "pusher-js"; +import { useCallback, useEffect, useRef } from "react"; + +type Connection = + | Broadcaster[T]["public"] + | Broadcaster[T]["private"] + | Broadcaster[T]["presence"]; + +type ChannelData = { + count: number; + connection: Connection; +}; + +type Channel = { + name: string; + id: string; + visibility: "private" | "public" | "presence"; +}; + +type ConfigDefaults = Record< + O, + Broadcaster[O]["options"] +>; + +type ModelPayload = { + model: T; +}; + +type ChannelReturnType< + T extends BroadcastDriver, + V extends Channel["visibility"], +> = V extends "presence" + ? Broadcaster[T]["presence"] + : V extends "private" + ? Broadcaster[T]["private"] + : Broadcaster[T]["public"]; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type ModelName = T extends `${infer _}.${infer U}` + ? ModelName + : T; + +type ModelEvents = + | `${ModelName}Retrieved` + | `${ModelName}Creating` + | `${ModelName}Created` + | `${ModelName}Updating` + | `${ModelName}Updated` + | `${ModelName}Saving` + | `${ModelName}Saved` + | `${ModelName}Deleting` + | `${ModelName}Deleted` + | `${ModelName}Trashed` + | `${ModelName}ForceDeleting` + | `${ModelName}ForceDeleted` + | `${ModelName}Restoring` + | `${ModelName}Restored` + | `${ModelName}Replicating`; + +let echoInstance: Echo | null = null; +let echoConfig: EchoOptions | null = null; +const channels: Record> = {}; + +const subscribeToChannel = ( + channel: Channel, +): Connection => { + const instance = getEchoInstance(); + + if (channel.visibility === "presence") { + return instance.join(channel.name); + } + + if (channel.visibility === "private") { + return instance.private(channel.name); + } + + return instance.channel(channel.name); +}; + +const getEchoInstance = (): Echo => { + if (echoInstance) { + return echoInstance as Echo; + } + + if (!echoConfig) { + throw new Error( + "Echo has not been configured. Please call `configureEcho()`.", + ); + } + + echoConfig.Pusher ??= Pusher; + + echoInstance = new Echo(echoConfig); + + return echoInstance as Echo; +}; + +const leaveChannel = (channel: Channel, leaveAll: boolean): void => { + if (!channels[channel.id]) { + return; + } + + channels[channel.id].count -= 1; + + if (channels[channel.id].count > 0) { + return; + } + + if (leaveAll) { + getEchoInstance().leave(channel.name); + } else { + getEchoInstance().leaveChannel(channel.id); + } + + delete channels[channel.id]; +}; + +const toArray = (item: T | T[]): T[] => + Array.isArray(item) ? item : [item]; + +const resolveChannelSubscription = ( + channel: Channel, +): Connection | void => { + if (channels[channel.id]) { + channels[channel.id].count += 1; + + return channels[channel.id].connection; + } + + const channelSubscription = subscribeToChannel(channel); + + if (!channelSubscription) { + // eslint-disable-next-line no-console + console.warn(`Failed to subscribe to channel: ${channel.id}`); + return; + } + + channels[channel.id] = { + count: 1, + connection: channelSubscription, + }; + + return channelSubscription; +}; + +/** + * Configure the Echo instance with sensible defaults. + * + * @link https://laravel.com/docs/broadcasting#client-side-installation + */ +export const configureEcho = ( + config: EchoOptions, +): void => { + const defaults: ConfigDefaults = { + reverb: { + broadcaster: "reverb", + key: import.meta.env.VITE_REVERB_KEY, + wsHost: import.meta.env.VITE_REVERB_HOST, + wsPort: import.meta.env.VITE_REVERB_PORT, + wssPort: import.meta.env.VITE_REVERB_PORT, + forceTLS: + (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https", + enabledTransports: ["ws", "wss"], + }, + pusher: { + broadcaster: "reverb", + key: import.meta.env.VITE_PUSHER_APP_KEY, + cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, + forceTLS: true, + wsHost: import.meta.env.VITE_PUSHER_HOST, + wsPort: import.meta.env.VITE_PUSHER_PORT, + wssPort: import.meta.env.VITE_PUSHER_PORT, + enabledTransports: ["ws", "wss"], + }, + "socket.io": { + broadcaster: "socket.io", + host: import.meta.env.VITE_SOCKET_IO_HOST, + }, + null: { + broadcaster: "null", + }, + ably: { + broadcaster: "pusher", + key: import.meta.env.VITE_ABLY_PUBLIC_KEY, + wsHost: "realtime-pusher.ably.io", + wsPort: 443, + disableStats: true, + encrypted: true, + }, + }; + + echoConfig = { + ...defaults[config.broadcaster], + ...config, + } as EchoOptions; + + // Reset the instance if it was already created + if (echoInstance) { + echoInstance = null; + } +}; + +export const echo = (): Echo => + getEchoInstance(); + +export const useEcho = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, + TVisibility extends Channel["visibility"] = "private", +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], + visibility: TVisibility = "private" as TVisibility, +) => { + const callbackFunc = useCallback(callback, dependencies); + const subscription = useRef | null>(null); + + const events = toArray(event); + const channel: Channel = { + name: channelName, + id: ["private", "presence"].includes(visibility) + ? `${visibility}-${channelName}` + : channelName, + visibility, + }; + + const stopListening = () => { + events.forEach((e) => { + subscription.current!.stopListening(e, callbackFunc); + }); + }; + + const tearDown = useCallback((leaveAll: boolean = false) => { + stopListening(); + + leaveChannel(channel, leaveAll); + }, dependencies); + + useEffect(() => { + const channelSubscription = + resolveChannelSubscription(channel); + + if (!channelSubscription) { + return; + } + + subscription.current = channelSubscription; + + events.forEach((e) => { + subscription.current!.listen(e, callbackFunc); + }); + + return tearDown; + }, dependencies); + + return { + /** + * Leave the channel + */ + leaveChannel: tearDown, + /** + * Leave the channel and also its associated private and presence channels + */ + leave: () => tearDown(true), + /** + * Stop listening for an event without leaving the channel + */ + stopListening, + /** + * Channel instance + */ + channel: () => + subscription.current as ChannelReturnType, + }; +}; + +export const useEchoPresence = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], +) => { + return useEcho( + channelName, + event, + callback, + dependencies, + "presence", + ); +}; + +export const useEchoPublic = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], +) => { + return useEcho( + channelName, + event, + callback, + dependencies, + "public", + ); +}; + +export const useEchoModel = ( + model: TModel, + identifier: string | number, + event: ModelEvents | ModelEvents[], + callback: (payload: ModelPayload) => void, + dependencies: any[] = [], +) => { + return useEcho>( + `${model}.${identifier}`, + toArray(event).map((e) => (e.startsWith(".") ? e : `.${e}`)), + callback, + dependencies, + "private", + ); +}; diff --git a/packages/react/src/index.iife.ts b/packages/react/src/index.iife.ts new file mode 100644 index 00000000..4023d55a --- /dev/null +++ b/packages/react/src/index.iife.ts @@ -0,0 +1 @@ +export { configureEcho, echo, useEcho } from "./hook/use-echo"; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 00000000..4023d55a --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1 @@ +export { configureEcho, echo, useEcho } from "./hook/use-echo"; diff --git a/packages/react/src/vite-env.d.ts b/packages/react/src/vite-env.d.ts new file mode 100644 index 00000000..4fb35ce4 --- /dev/null +++ b/packages/react/src/vite-env.d.ts @@ -0,0 +1,21 @@ +/// + +interface ImportMetaEnv { + readonly VITE_PUSHER_APP_CLUSTER: string; + readonly VITE_PUSHER_APP_KEY: string; + readonly VITE_PUSHER_HOST: string; + readonly VITE_PUSHER_PORT: number; + + readonly VITE_REVERB_HOST: string; + readonly VITE_REVERB_KEY: string; + readonly VITE_REVERB_PORT: number; + readonly VITE_REVERB_SCHEME: string; + + readonly VITE_SOCKET_IO_HOST: string; + + readonly VITE_ABLY_PUBLIC_KEY: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/packages/react/tests/hooks.test.ts b/packages/react/tests/hooks.test.ts new file mode 100644 index 00000000..1f8e48c2 --- /dev/null +++ b/packages/react/tests/hooks.test.ts @@ -0,0 +1,758 @@ +import { renderHook } from "@testing-library/react"; +import Echo from "laravel-echo"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +const getEchoModule = async () => import("../src/hook/use-echo"); + +vi.mock("laravel-echo", () => { + const mockPrivateChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + }; + + const mockPublicChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + }; + + const mockPresenceChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + here: vi.fn(), + joining: vi.fn(), + leaving: vi.fn(), + whisper: vi.fn(), + }; + + const Echo = vi.fn(); + + Echo.prototype.private = vi.fn(() => mockPrivateChannel); + Echo.prototype.channel = vi.fn(() => mockPublicChannel); + Echo.prototype.encryptedPrivate = vi.fn(); + Echo.prototype.listen = vi.fn(); + Echo.prototype.leave = vi.fn(); + Echo.prototype.leaveChannel = vi.fn(); + Echo.prototype.leaveAllChannels = vi.fn(); + Echo.prototype.join = vi.fn(() => mockPresenceChannel); + + return { default: Echo }; +}); + +describe("echo helper", async () => { + beforeEach(() => { + vi.resetModules(); + }); + + it("throws error when Echo is not configured", async () => { + const echoModule = await getEchoModule(); + + expect(() => echoModule.echo()).toThrow("Echo has not been configured"); + }); + + it("creates Echo instance with proper configuration", async () => { + const echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + + expect(echoModule.echo()).toBeDefined(); + }); +}); + +describe("without echo configured", async () => { + beforeEach(() => { + vi.resetModules(); + }); + + it("throws error when Echo is not configured", async () => { + const echoModule = await getEchoModule(); + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + expect(() => + renderHook(() => + echoModule.useEcho( + channelName, + event, + mockCallback, + [], + "private", + ), + ), + ).toThrow("Echo has not been configured"); + }); +}); + +describe("useEcho hook", async () => { + let echoModule: typeof import("../src/hook/use-echo"); + let echoInstance: Echo<"null">; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + + echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("subscribes to a channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + expect(typeof result.current.leave).toBe("function"); + + expect(result.current).toHaveProperty("leave"); + expect(typeof result.current.leaveChannel).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + const { result, unmount } = renderHook(() => + echoModule.useEcho(channelName, events, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + + expect(echoInstance.private).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.private(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + expect(() => unmount()).not.toThrow(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + expect(echoInstance.private).toHaveBeenCalled(); + + expect(() => unmount()).not.toThrow(); + + expect(echoInstance.leaveChannel).toHaveBeenCalled(); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount: unmount1 } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + const { unmount: unmount2 } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + expect(echoInstance.private).toHaveBeenCalledTimes(1); + + expect(() => unmount1()).not.toThrow(); + + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + expect(() => unmount2()).not.toThrow(); + + expect(echoInstance.leaveChannel).toHaveBeenCalled(); + }); + + it("will register callbacks for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + expect(echoInstance.private).toHaveBeenCalledWith(channelName); + + expect(echoInstance.private(channelName).listen).toHaveBeenCalledWith( + event, + mockCallback, + ); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + result.current.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + "private-" + channelName, + ); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback), + ); + + result.current.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); + + it("can connect to a public channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEcho(channelName, event, mockCallback, [], "public"), + ); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + result.current.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); +}); + +describe("useEchoModel hook", async () => { + let echoModule: typeof import("../src/hook/use-echo"); + let echoInstance: Echo<"null">; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + + echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("subscribes to model channel and listens for model events", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const event = "UserCreated"; + + const { result } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + expect(typeof result.current.leave).toBe("function"); + expect(result.current).toHaveProperty("leave"); + expect(typeof result.current.leaveChannel).toBe("function"); + }); + + it("handles multiple model events", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const events = ["UserCreated", "UserUpdated"]; + + const { result, unmount } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + ["UserCreated", "UserUpdated"], + mockCallback, + ), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.private).toHaveBeenCalledWith(expectedChannelName); + + const channel = echoInstance.private(expectedChannelName); + + expect(channel.listen).toHaveBeenCalledWith( + `.${events[0]}`, + mockCallback, + ); + expect(channel.listen).toHaveBeenCalledWith( + `.${events[1]}`, + mockCallback, + ); + + expect(() => unmount()).not.toThrow(); + + expect(channel.stopListening).toHaveBeenCalledWith( + `.${events[0]}`, + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + `.${events[1]}`, + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const event = "UserCreated"; + + const { unmount } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.private).toHaveBeenCalledWith(expectedChannelName); + + expect(() => unmount()).not.toThrow(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `private-${expectedChannelName}`, + ); + }); + + it("won't subscribe multiple times to the same model channel", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const event = "UserCreated"; + + const { unmount: unmount1 } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + const { unmount: unmount2 } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.private).toHaveBeenCalledTimes(1); + expect(echoInstance.private).toHaveBeenCalledWith(expectedChannelName); + + expect(() => unmount1()).not.toThrow(); + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + expect(() => unmount2()).not.toThrow(); + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `private-${expectedChannelName}`, + ); + }); + + it("can leave a model channel", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const event = "UserCreated"; + + const { result } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + result.current.leaveChannel(); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `private-${expectedChannelName}`, + ); + }); + + it("can leave all model channel variations", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User"; + const identifier = "123"; + const event = "UserCreated"; + + const { result } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + result.current.leave(); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.leave).toHaveBeenCalledWith(expectedChannelName); + }); + + it("handles model events with dots in the name", async () => { + const mockCallback = vi.fn(); + const model = "App.Models.User.Profile"; + const identifier = "123"; + const event = "ProfileCreated"; + + const { result } = renderHook(() => + echoModule.useEchoModel( + model, + identifier, + event, + mockCallback, + ), + ); + + const expectedChannelName = `${model}.${identifier}`; + expect(echoInstance.private).toHaveBeenCalledWith(expectedChannelName); + + const channel = echoInstance.private(expectedChannelName); + expect(channel.listen).toHaveBeenCalledWith(`.${event}`, mockCallback); + }); +}); + +describe("useEchoPublic hook", async () => { + let echoModule: typeof import("../src/hook/use-echo"); + let echoInstance: Echo<"null">; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + + echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("subscribes to a public channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + expect(typeof result.current.leave).toBe("function"); + expect(result.current).toHaveProperty("leave"); + expect(typeof result.current.leaveChannel).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + const { result, unmount } = renderHook(() => + echoModule.useEchoPublic(channelName, events, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.channel(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + expect(() => unmount()).not.toThrow(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + expect(() => unmount()).not.toThrow(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount: unmount1 } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + const { unmount: unmount2 } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + expect(echoInstance.channel).toHaveBeenCalledTimes(1); + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + expect(() => unmount1()).not.toThrow(); + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + expect(() => unmount2()).not.toThrow(); + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + result.current.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPublic(channelName, event, mockCallback), + ); + + result.current.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); +}); + +describe("useEchoPresence hook", async () => { + let echoModule: typeof import("../src/hook/use-echo"); + let echoInstance: Echo<"null">; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + + echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("subscribes to a presence channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + expect(typeof result.current.leave).toBe("function"); + expect(result.current).toHaveProperty("leave"); + expect(typeof result.current.leaveChannel).toBe("function"); + expect(result.current).toHaveProperty("channel"); + expect(result.current.channel).not.toBeNull(); + expect(typeof result.current.channel().here).toBe("function"); + expect(typeof result.current.channel().joining).toBe("function"); + expect(typeof result.current.channel().leaving).toBe("function"); + expect(typeof result.current.channel().whisper).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + const { result, unmount } = renderHook(() => + echoModule.useEchoPresence(channelName, events, mockCallback), + ); + + expect(result.current).toHaveProperty("leaveChannel"); + + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.join(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + expect(() => unmount()).not.toThrow(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + expect(() => unmount()).not.toThrow(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { unmount: unmount1 } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + const { unmount: unmount2 } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + expect(echoInstance.join).toHaveBeenCalledTimes(1); + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + expect(() => unmount1()).not.toThrow(); + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + expect(() => unmount2()).not.toThrow(); + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + result.current.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + const { result } = renderHook(() => + echoModule.useEchoPresence(channelName, event, mockCallback), + ); + + result.current.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); +}); diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 00000000..6ef5fa66 --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "./dist", + "emitDeclarationOnly": true, + "module": "ES2020", + "moduleResolution": "node", + "outDir": "./dist", + "sourceMap": false, + "target": "ES2020", + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "importHelpers": true, + "strictPropertyInitialization": false, + "allowSyntheticDefaultImports": true, + "isolatedModules": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "strict": true, + "typeRoots": ["node_modules/@types"], + "lib": ["dom", "es2020"] + }, + "include": ["./typings/**/*.ts", "./src/**/*.ts", "./tests/**/*.ts"], + "exclude": ["./node_modules"] +} diff --git a/packages/react/vite.config.ts b/packages/react/vite.config.ts new file mode 100644 index 00000000..6dbe92a1 --- /dev/null +++ b/packages/react/vite.config.ts @@ -0,0 +1,56 @@ +import { resolve } from "path"; +import { defineConfig, UserConfig } from "vite"; +import dts from "vite-plugin-dts"; + +const config: UserConfig = (() => { + const common: Partial = { + rollupOptions: { + external: ["react", "pusher-js"], + output: { + globals: { + react: "React", + "pusher-js": "Pusher", + }, + }, + }, + outDir: resolve(__dirname, "dist"), + sourcemap: true, + minify: true, + }; + + if (process.env.FORMAT === "iife") { + return { + build: { + lib: { + entry: resolve(__dirname, "src/index.iife.ts"), + name: "EchoReact", + formats: ["iife"], + fileName: () => "echo-react.iife.js", + }, + emptyOutDir: false, // Don't empty the output directory for the second build + ...common, + }, + }; + } + + return { + plugins: [dts()], + build: { + lib: { + entry: resolve(__dirname, "src/index.ts"), + formats: ["es", "cjs"], + fileName: (format, entryName) => { + return `${entryName}.${format === "es" ? "js" : "common.js"}`; + }, + }, + emptyOutDir: true, + ...common, + }, + test: { + globals: true, + environment: "jsdom", + }, + }; +})(); + +export default defineConfig(config); diff --git a/packages/vue/eslint.config.mjs b/packages/vue/eslint.config.mjs new file mode 100644 index 00000000..d58a9664 --- /dev/null +++ b/packages/vue/eslint.config.mjs @@ -0,0 +1,42 @@ +import tsPlugin from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; + +const config = [ + { + ignores: ["dist/**/*"], + files: ["src/**/*.ts"], + languageOptions: { + parser: tsParser, // Use the imported parser object + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + project: "./tsconfig.json", // Path to your TypeScript configuration file + }, + }, + plugins: { + "@typescript-eslint": tsPlugin, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + ...tsPlugin.configs["recommended-requiring-type-checking"].rules, + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-unsafe-argument": "warn", + "@typescript-eslint/no-unsafe-assignment": "warn", + "@typescript-eslint/no-unsafe-call": "warn", + "@typescript-eslint/no-unsafe-function-type": "off", + "@typescript-eslint/no-unsafe-member-access": "warn", + "@typescript-eslint/no-unsafe-return": "warn", + "@typescript-eslint/no-unused-vars": [ + "warn", + { argsIgnorePattern: "^_" }, + ], + "no-console": "warn", + "prefer-const": "off", + }, + }, +]; + +export default config; diff --git a/packages/vue/package.json b/packages/vue/package.json new file mode 100644 index 00000000..b8c2b751 --- /dev/null +++ b/packages/vue/package.json @@ -0,0 +1,81 @@ +{ + "name": "@laravel/echo-vue", + "version": "2.0.2", + "description": "Laravel Echo library for beautiful Pusher and Socket.IO integration", + "keywords": [ + "laravel", + "pusher", + "ably", + "vue" + ], + "homepage": "https://github.com/laravel/echo/tree/2.x/packages/vue", + "repository": { + "type": "git", + "url": "https://github.com/laravel/echo" + }, + "license": "MIT", + "author": { + "name": "Taylor Otwell" + }, + "type": "module", + "main": "dist/echo.common.js", + "module": "dist/echo.js", + "types": "dist/echo.d.ts", + "scripts": { + "build": "vite build && FORMAT=iife vite build", + "lint": "eslint --config eslint.config.mjs \"src/**/*.ts\"", + "prepublish": "pnpm run build", + "release": "pnpm run test && git push --follow-tags && pnpm publish", + "test": "vitest", + "format": "prettier --write ." + }, + "devDependencies": { + "@babel/core": "^7.26.7", + "@babel/plugin-proposal-decorators": "^7.25.9", + "@babel/plugin-proposal-function-sent": "^7.25.9", + "@babel/plugin-proposal-throw-expressions": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-assign": "^7.25.9", + "@babel/preset-env": "^7.26.7", + "@testing-library/vue": "^8.1.0", + "@types/node": "^22.15.3", + "@typescript-eslint/eslint-plugin": "^8.21.0", + "@typescript-eslint/parser": "^8.21.0", + "@vue/test-utils": "^2.4.6", + "eslint": "^9.0.0", + "laravel-echo": "workspace:^", + "prettier": "^3.5.3", + "pusher-js": "^8.0", + "socket.io-client": "^4.0", + "tslib": "^2.8.1", + "typescript": "^5.7.0", + "vite": "^6.3.3", + "vite-plugin-dts": "^4.5.3", + "vitest": "^3.1.2" + }, + "peerDependencies": { + "pusher-js": "*", + "socket.io-client": "*", + "vue": "^3.0.0" + }, + "typesVersions": { + "*": { + "socket.io-client": [], + "pusher-js": [] + } + }, + "engines": { + "node": ">=20" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.common.js" + } + }, + "overrides": { + "glob": "^9.0.0" + } +} diff --git a/packages/vue/src/composable/useEcho.ts b/packages/vue/src/composable/useEcho.ts new file mode 100644 index 00000000..8a94743b --- /dev/null +++ b/packages/vue/src/composable/useEcho.ts @@ -0,0 +1,358 @@ +import Echo, { + type BroadcastDriver, + type Broadcaster, + type EchoOptions, +} from "laravel-echo"; +import Pusher from "pusher-js"; +import { onMounted, onUnmounted, ref, watch } from "vue"; + +type Connection = + | Broadcaster[T]["public"] + | Broadcaster[T]["private"] + | Broadcaster[T]["presence"]; + +type ChannelData = { + count: number; + connection: Connection; +}; + +type Channel = { + name: string; + id: string; + visibility: "private" | "public" | "presence"; +}; + +type ConfigDefaults = Record< + O, + Broadcaster[O]["options"] +>; + +type ModelPayload = { + model: T; +}; + +type ChannelReturnType< + T extends BroadcastDriver, + V extends Channel["visibility"], +> = V extends "presence" + ? Broadcaster[T]["presence"] + : V extends "private" + ? Broadcaster[T]["private"] + : Broadcaster[T]["public"]; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type ModelName = T extends `${infer _}.${infer U}` + ? ModelName + : T; + +type ModelEvents = + | `${ModelName}Retrieved` + | `${ModelName}Creating` + | `${ModelName}Created` + | `${ModelName}Updating` + | `${ModelName}Updated` + | `${ModelName}Saving` + | `${ModelName}Saved` + | `${ModelName}Deleting` + | `${ModelName}Deleted` + | `${ModelName}Trashed` + | `${ModelName}ForceDeleting` + | `${ModelName}ForceDeleted` + | `${ModelName}Restoring` + | `${ModelName}Restored` + | `${ModelName}Replicating`; + +let echoInstance: Echo | null = null; +let echoConfig: EchoOptions | null = null; +const channels: Record> = {}; + +const toArray = (item: T | T[]): T[] => + Array.isArray(item) ? item : [item]; + +const getEchoInstance = (): Echo => { + if (echoInstance) { + return echoInstance as Echo; + } + + if (!echoConfig) { + throw new Error( + "Echo has not been configured. Please call `configureEcho()` with your configuration options before using Echo.", + ); + } + + echoConfig.Pusher ??= Pusher; + + echoInstance = new Echo(echoConfig); + + return echoInstance as Echo; +}; + +const resolveChannelSubscription = ( + channel: Channel, +): Connection | null => { + if (channels[channel.id]) { + channels[channel.id].count += 1; + + return channels[channel.id].connection; + } + + const channelSubscription = subscribeToChannel(channel); + + if (!channelSubscription) { + // eslint-disable-next-line no-console + console.warn(`Failed to subscribe to channel: ${channel.id}`); + return null; + } + + channels[channel.id] = { + count: 1, + connection: channelSubscription, + }; + + return channelSubscription; +}; + +const subscribeToChannel = ( + channel: Channel, +): Connection => { + const instance = getEchoInstance(); + + if (channel.visibility === "presence") { + return instance.join(channel.name); + } + + if (channel.visibility === "private") { + return instance.private(channel.name); + } + + return instance.channel(channel.name); +}; + +const leaveChannel = (channel: Channel, leaveAll: boolean = false): void => { + if (!channels[channel.id]) { + return; + } + + channels[channel.id].count -= 1; + + if (channels[channel.id].count > 0) { + return; + } + + delete channels[channel.id]; + + if (leaveAll) { + getEchoInstance().leave(channel.name); + } else { + getEchoInstance().leaveChannel(channel.id); + } +}; + +/** + * Configure the Echo instance with sensible defaults. + * + * @link https://laravel.com/docs/broadcasting#client-side-installation + */ +export const configureEcho = ( + config: EchoOptions, +): void => { + const defaults: ConfigDefaults = { + reverb: { + broadcaster: "reverb", + key: import.meta.env.VITE_REVERB_KEY, + wsHost: import.meta.env.VITE_REVERB_HOST, + wsPort: import.meta.env.VITE_REVERB_PORT, + wssPort: import.meta.env.VITE_REVERB_PORT, + forceTLS: + (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https", + enabledTransports: ["ws", "wss"], + }, + pusher: { + broadcaster: "reverb", + key: import.meta.env.VITE_PUSHER_APP_KEY, + cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, + forceTLS: true, + wsHost: import.meta.env.VITE_PUSHER_HOST, + wsPort: import.meta.env.VITE_PUSHER_PORT, + wssPort: import.meta.env.VITE_PUSHER_PORT, + enabledTransports: ["ws", "wss"], + }, + "socket.io": { + broadcaster: "socket.io", + host: import.meta.env.VITE_SOCKET_IO_HOST, + }, + null: { + broadcaster: "null", + }, + ably: { + broadcaster: "pusher", + key: import.meta.env.VITE_ABLY_PUBLIC_KEY, + wsHost: "realtime-pusher.ably.io", + wsPort: 443, + disableStats: true, + encrypted: true, + }, + }; + + echoConfig = { + ...defaults[config.broadcaster], + ...config, + } as EchoOptions; + + // Reset the instance if it was already created + if (echoInstance) { + echoInstance = null; + } +}; + +export const echo = (): Echo => + getEchoInstance(); + +export const useEcho = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, + TVisibility extends Channel["visibility"] = "private", +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], + visibility: TVisibility = "private" as TVisibility, +) => { + const eventCallback = ref(callback); + + watch( + () => callback, + (newCallback) => { + eventCallback.value = newCallback; + }, + ); + + let subscription: Connection | null = null; + const events = Array.isArray(event) ? event : [event]; + const channel: Channel = { + name: channelName, + id: ["private", "presence"].includes(visibility) + ? `${visibility}-${channelName}` + : channelName, + visibility, + }; + + const setupSubscription = () => { + subscription = resolveChannelSubscription(channel); + + if (!subscription) { + return; + } + + events.forEach((e) => { + subscription!.listen(e, eventCallback.value); + }); + }; + + const stopListening = () => { + events.forEach((e) => { + subscription!.stopListening(e, eventCallback.value); + }); + }; + + const tearDown = (leaveAll: boolean = false) => { + stopListening(); + leaveChannel(channel, leaveAll); + }; + + onMounted(() => { + setupSubscription(); + }); + + onUnmounted(() => { + tearDown(); + }); + + if (dependencies.length > 0) { + watch( + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + () => dependencies, + () => { + tearDown(); + setupSubscription(); + }, + { deep: true }, + ); + } + + return { + /** + * Leave the channel + */ + leaveChannel: tearDown, + /** + * Leave the channel and also its associated private and presence channels + */ + leave: () => tearDown(true), + /** + * Stop listening for an event without leaving the channel + */ + stopListening, + /** + * Channel instance + */ + channel: () => subscription! as ChannelReturnType, + }; +}; + +export const useEchoPresence = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], +) => { + return useEcho( + channelName, + event, + callback, + dependencies, + "presence", + ); +}; + +export const useEchoPublic = < + TPayload, + TDriver extends BroadcastDriver = BroadcastDriver, +>( + channelName: string, + event: string | string[], + callback: (payload: TPayload) => void, + dependencies: any[] = [], +) => { + return useEcho( + channelName, + event, + callback, + dependencies, + "public", + ); +}; + +export const useEchoModel = < + TPayload, + TModel extends string, + TDriver extends BroadcastDriver = BroadcastDriver, +>( + model: TModel, + identifier: string | number, + event: ModelEvents | ModelEvents[], + callback: (payload: ModelPayload) => void, + dependencies: any[] = [], +) => { + return useEcho, TDriver, "private">( + `${model}.${identifier}`, + toArray(event).map((e) => (e.startsWith(".") ? e : `.${e}`)), + callback, + dependencies, + "private", + ); +}; diff --git a/packages/vue/src/index.iife.ts b/packages/vue/src/index.iife.ts new file mode 100644 index 00000000..1da389e3 --- /dev/null +++ b/packages/vue/src/index.iife.ts @@ -0,0 +1 @@ +export { configureEcho, echo, useEcho } from "./composable/useEcho"; diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts new file mode 100644 index 00000000..1da389e3 --- /dev/null +++ b/packages/vue/src/index.ts @@ -0,0 +1 @@ +export { configureEcho, echo, useEcho } from "./composable/useEcho"; diff --git a/packages/vue/src/vite-env.d.ts b/packages/vue/src/vite-env.d.ts new file mode 100644 index 00000000..4fb35ce4 --- /dev/null +++ b/packages/vue/src/vite-env.d.ts @@ -0,0 +1,21 @@ +/// + +interface ImportMetaEnv { + readonly VITE_PUSHER_APP_CLUSTER: string; + readonly VITE_PUSHER_APP_KEY: string; + readonly VITE_PUSHER_HOST: string; + readonly VITE_PUSHER_PORT: number; + + readonly VITE_REVERB_HOST: string; + readonly VITE_REVERB_KEY: string; + readonly VITE_REVERB_PORT: number; + readonly VITE_REVERB_SCHEME: string; + + readonly VITE_SOCKET_IO_HOST: string; + + readonly VITE_ABLY_PUBLIC_KEY: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/packages/vue/tests/composables.test.ts b/packages/vue/tests/composables.test.ts new file mode 100644 index 00000000..c9341f25 --- /dev/null +++ b/packages/vue/tests/composables.test.ts @@ -0,0 +1,604 @@ +import { mount } from "@vue/test-utils"; +import Echo from "laravel-echo"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { defineComponent } from "vue"; +import { + configureEcho, + useEcho, + useEchoPresence, + useEchoPublic, +} from "../src/composable/useEcho"; + +const getEchoModule = async () => import("../src/composable/useEcho"); + +const getUnConfiguredTestComponent = ( + channelName: string, + event: string | string[], + callback: (data: any) => void, + visibility: "private" | "public" = "private", +) => { + const TestComponent = defineComponent({ + setup() { + return { + ...useEcho(channelName, event, callback, [], visibility), + }; + }, + template: "
", + }); + + return mount(TestComponent); +}; + +const getTestComponent = ( + channelName: string, + event: string | string[], + callback: (data: any) => void, + dependencies: any[] = [], + visibility: "private" | "public" = "private", +) => { + const TestComponent = defineComponent({ + setup() { + configureEcho({ + broadcaster: "null", + }); + + return { + ...useEcho( + channelName, + event, + callback, + dependencies, + visibility, + ), + }; + }, + template: "
", + }); + + return mount(TestComponent); +}; + +const getPublicTestComponent = ( + channelName: string, + event: string | string[], + callback: (data: any) => void, + dependencies: any[] = [], +) => { + const TestComponent = defineComponent({ + setup() { + configureEcho({ + broadcaster: "null", + }); + + return { + ...useEchoPublic(channelName, event, callback, dependencies), + }; + }, + template: "
", + }); + + return mount(TestComponent); +}; + +const getPresenceTestComponent = ( + channelName: string, + event: string | string[], + callback: (data: any) => void, + dependencies: any[] = [], +) => { + const TestComponent = defineComponent({ + setup() { + configureEcho({ + broadcaster: "null", + }); + + return { + ...useEchoPresence(channelName, event, callback, dependencies), + }; + }, + template: "
", + }); + + return mount(TestComponent); +}; + +vi.mock("laravel-echo", () => { + const mockPrivateChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + }; + + const mockPublicChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + }; + + const mockPresenceChannel = { + leaveChannel: vi.fn(), + listen: vi.fn(), + stopListening: vi.fn(), + here: vi.fn(), + joining: vi.fn(), + leaving: vi.fn(), + whisper: vi.fn(), + }; + + const Echo = vi.fn(); + + Echo.prototype.private = vi.fn(() => mockPrivateChannel); + Echo.prototype.channel = vi.fn(() => mockPublicChannel); + Echo.prototype.encryptedPrivate = vi.fn(); + Echo.prototype.listen = vi.fn(); + Echo.prototype.leave = vi.fn(); + Echo.prototype.leaveChannel = vi.fn(); + Echo.prototype.leaveAllChannels = vi.fn(); + Echo.prototype.join = vi.fn(() => mockPresenceChannel); + + return { default: Echo }; +}); + +describe("echo helper", async () => { + beforeEach(() => { + vi.resetModules(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("throws error when Echo is not configured", async () => { + const echoModule = await getEchoModule(); + + expect(() => echoModule.echo()).toThrow("Echo has not been configured"); + }); + + it("creates Echo instance with proper configuration", async () => { + const echoModule = await getEchoModule(); + + echoModule.configureEcho({ + broadcaster: "null", + }); + + expect(echoModule.echo()).toBeDefined(); + }); +}); + +describe("without echo configured", async () => { + beforeEach(() => { + vi.resetModules(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("throws error when Echo is not configured", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + expect(() => + getUnConfiguredTestComponent( + channelName, + event, + mockCallback, + "private", + ), + ).toThrow("Echo has not been configured"); + }); +}); + +describe("useEcho hook", async () => { + let echoInstance: Echo<"null">; + let wrapper: ReturnType; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + }); + + afterEach(() => { + wrapper.unmount(); + vi.clearAllMocks(); + }); + + it("subscribes to a channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(wrapper.vm).toHaveProperty("leave"); + expect(typeof wrapper.vm.leave).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + wrapper = getTestComponent(channelName, events, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(echoInstance.private).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.private(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + wrapper.unmount(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + expect(echoInstance.private).toHaveBeenCalled(); + + wrapper.unmount(); + + expect(echoInstance.leaveChannel).toHaveBeenCalled(); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + const wrapper2 = getTestComponent(channelName, event, mockCallback); + + expect(echoInstance.private).toHaveBeenCalledTimes(1); + + wrapper.unmount(); + + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + wrapper2.unmount(); + + expect(echoInstance.leaveChannel).toHaveBeenCalled(); + }); + + it("will register callbacks for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + expect(echoInstance.private).toHaveBeenCalledWith(channelName); + + expect(echoInstance.private(channelName).listen).toHaveBeenCalledWith( + event, + mockCallback, + ); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + wrapper.vm.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + "private-" + channelName, + ); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent(channelName, event, mockCallback); + + wrapper.vm.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); + + it("can connect to a public channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getTestComponent( + channelName, + event, + mockCallback, + [], + "public", + ); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + wrapper.vm.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); +}); + +describe("useEchoPublic hook", async () => { + let echoInstance: Echo<"null">; + let wrapper: ReturnType; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + }); + + afterEach(() => { + wrapper.unmount(); + vi.clearAllMocks(); + }); + + it("subscribes to a public channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPublicTestComponent(channelName, event, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(wrapper.vm).toHaveProperty("leave"); + expect(typeof wrapper.vm.leave).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + wrapper = getPublicTestComponent(channelName, events, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.channel(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + wrapper.unmount(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPublicTestComponent(channelName, event, mockCallback); + + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + wrapper.unmount(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPublicTestComponent(channelName, event, mockCallback); + + const wrapper2 = getPublicTestComponent( + channelName, + event, + mockCallback, + ); + + expect(echoInstance.channel).toHaveBeenCalledTimes(1); + expect(echoInstance.channel).toHaveBeenCalledWith(channelName); + + wrapper.unmount(); + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + wrapper2.unmount(); + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPublicTestComponent(channelName, event, mockCallback); + + wrapper.vm.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith(channelName); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPublicTestComponent(channelName, event, mockCallback); + + wrapper.vm.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); +}); + +describe("useEchoPresence hook", async () => { + let echoInstance: Echo<"null">; + let wrapper: ReturnType; + + beforeEach(async () => { + vi.resetModules(); + + echoInstance = new Echo({ + broadcaster: "null", + }); + }); + + afterEach(() => { + wrapper.unmount(); + vi.clearAllMocks(); + }); + + it("subscribes to a presence channel and listens for events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPresenceTestComponent(channelName, event, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(wrapper.vm).toHaveProperty("leave"); + expect(typeof wrapper.vm.leave).toBe("function"); + + expect(wrapper.vm).toHaveProperty("channel"); + expect(wrapper.vm.channel).not.toBeNull(); + expect(typeof wrapper.vm.channel().here).toBe("function"); + expect(typeof wrapper.vm.channel().joining).toBe("function"); + expect(typeof wrapper.vm.channel().leaving).toBe("function"); + expect(typeof wrapper.vm.channel().whisper).toBe("function"); + }); + + it("handles multiple events", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const events = ["event1", "event2"]; + + wrapper = getPresenceTestComponent(channelName, events, mockCallback); + + expect(wrapper.vm).toHaveProperty("leaveChannel"); + expect(typeof wrapper.vm.leaveChannel).toBe("function"); + + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + const channel = echoInstance.join(channelName); + + expect(channel.listen).toHaveBeenCalledWith(events[0], mockCallback); + expect(channel.listen).toHaveBeenCalledWith(events[1], mockCallback); + + wrapper.unmount(); + + expect(channel.stopListening).toHaveBeenCalledWith( + events[0], + mockCallback, + ); + expect(channel.stopListening).toHaveBeenCalledWith( + events[1], + mockCallback, + ); + }); + + it("cleans up subscriptions on unmount", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPresenceTestComponent(channelName, event, mockCallback); + + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + wrapper.unmount(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("won't subscribe multiple times to the same channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPresenceTestComponent(channelName, event, mockCallback); + + const wrapper2 = getPresenceTestComponent( + channelName, + event, + mockCallback, + ); + + expect(echoInstance.join).toHaveBeenCalledTimes(1); + expect(echoInstance.join).toHaveBeenCalledWith(channelName); + + wrapper.unmount(); + expect(echoInstance.leaveChannel).not.toHaveBeenCalled(); + + wrapper2.unmount(); + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("can leave a channel", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPresenceTestComponent(channelName, event, mockCallback); + + wrapper.vm.leaveChannel(); + + expect(echoInstance.leaveChannel).toHaveBeenCalledWith( + `presence-${channelName}`, + ); + }); + + it("can leave all channel variations", async () => { + const mockCallback = vi.fn(); + const channelName = "test-channel"; + const event = "test-event"; + + wrapper = getPresenceTestComponent(channelName, event, mockCallback); + + wrapper.vm.leave(); + + expect(echoInstance.leave).toHaveBeenCalledWith(channelName); + }); +}); diff --git a/packages/vue/tsconfig.json b/packages/vue/tsconfig.json new file mode 100644 index 00000000..e96a3f49 --- /dev/null +++ b/packages/vue/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "./dist", + "emitDeclarationOnly": true, + "module": "ES2020", + "moduleResolution": "bundler", + "outDir": "./dist", + "sourceMap": false, + "target": "ES2020", + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "importHelpers": true, + "strictPropertyInitialization": false, + "allowSyntheticDefaultImports": true, + "isolatedModules": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "strict": true, + "typeRoots": ["node_modules/@types"], + "lib": ["dom", "es2020"] + }, + "include": ["./typings/**/*.ts", "./src/**/*.ts"], + "exclude": ["./node_modules", "./tests/**/*.ts"] +} diff --git a/packages/vue/vite.config.ts b/packages/vue/vite.config.ts new file mode 100644 index 00000000..7a8cb456 --- /dev/null +++ b/packages/vue/vite.config.ts @@ -0,0 +1,56 @@ +import { resolve } from "path"; +import { defineConfig, UserConfig } from "vite"; +import dts from "vite-plugin-dts"; + +const config: UserConfig = (() => { + const common: Partial = { + rollupOptions: { + external: ["vue", "pusher-js"], + output: { + globals: { + vue: "Vue", + "pusher-js": "Pusher", + }, + }, + }, + outDir: resolve(__dirname, "dist"), + sourcemap: true, + minify: true, + }; + + if (process.env.FORMAT === "iife") { + return { + build: { + lib: { + entry: resolve(__dirname, "src/index.iife.ts"), + name: "EchoVue", + formats: ["iife"], + fileName: () => "echo-vue.iife.js", + }, + emptyOutDir: false, // Don't empty the output directory for the second build + ...common, + }, + }; + } + + return { + plugins: [dts()], + build: { + lib: { + entry: resolve(__dirname, "src/index.ts"), + formats: ["es", "cjs"], + fileName: (format, entryName) => { + return `${entryName}.${format === "es" ? "js" : "common.js"}`; + }, + }, + emptyOutDir: true, + ...common, + }, + test: { + globals: true, + environment: "jsdom", + }, + }; +})(); + +export default defineConfig(config); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..cdefee7d --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,6270 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} + + packages/laravel-echo: + devDependencies: + '@babel/core': + specifier: ^7.26.7 + version: 7.27.1 + '@babel/plugin-proposal-decorators': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-function-sent': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-throw-expressions': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-export-namespace-from': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-numeric-separator': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-object-assign': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/preset-env': + specifier: ^7.26.7 + version: 7.27.1(@babel/core@7.27.1) + '@types/node': + specifier: ^20.0.0 + version: 20.17.32 + '@typescript-eslint/eslint-plugin': + specifier: ^8.21.0 + version: 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.21.0 + version: 8.31.1(eslint@9.25.1)(typescript@5.8.3) + eslint: + specifier: ^9.0.0 + version: 9.25.1 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + pusher-js: + specifier: ^8.0 + version: 8.4.0 + socket.io-client: + specifier: ^4.0 + version: 4.8.1 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + typescript: + specifier: ^5.7.0 + version: 5.8.3 + vite: + specifier: ^5.0.0 + version: 5.4.19(@types/node@20.17.32) + vite-plugin-dts: + specifier: ^3.0.0 + version: 3.9.1(@types/node@20.17.32)(rollup@4.40.1)(typescript@5.8.3)(vite@5.4.19(@types/node@20.17.32)) + vitest: + specifier: ^3.1.2 + version: 3.1.2(@types/node@20.17.32)(jsdom@26.1.0) + + packages/react: + devDependencies: + '@babel/core': + specifier: ^7.26.7 + version: 7.27.1 + '@babel/plugin-proposal-decorators': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-function-sent': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-throw-expressions': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-export-namespace-from': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-numeric-separator': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-object-assign': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/preset-env': + specifier: ^7.26.7 + version: 7.27.1(@babel/core@7.27.1) + '@testing-library/dom': + specifier: ^10.4.0 + version: 10.4.0 + '@testing-library/react': + specifier: ^14.3.1 + version: 14.3.1(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@testing-library/react-hooks': + specifier: ^8.0.1 + version: 8.0.1(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@types/node': + specifier: ^20.0.0 + version: 20.17.32 + '@types/react': + specifier: ^19.1.2 + version: 19.1.2 + '@types/react-dom': + specifier: ^19.1.2 + version: 19.1.3(@types/react@19.1.2) + '@typescript-eslint/eslint-plugin': + specifier: ^8.21.0 + version: 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.21.0 + version: 8.31.1(eslint@9.25.1)(typescript@5.8.3) + eslint: + specifier: ^9.0.0 + version: 9.25.1 + jsdom: + specifier: ^26.1.0 + version: 26.1.0 + laravel-echo: + specifier: workspace:^ + version: link:../laravel-echo + prettier: + specifier: ^3.5.3 + version: 3.5.3 + pusher-js: + specifier: ^8.0 + version: 8.4.0 + react: + specifier: ^19.1.0 + version: 19.1.0 + react-dom: + specifier: ^19.1.0 + version: 19.1.0(react@19.1.0) + socket.io-client: + specifier: ^4.0 + version: 4.8.1 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + typescript: + specifier: ^5.7.0 + version: 5.8.3 + vite: + specifier: ^5.1.0 + version: 5.4.19(@types/node@20.17.32) + vite-plugin-dts: + specifier: ^3.7.0 + version: 3.9.1(@types/node@20.17.32)(rollup@4.40.1)(typescript@5.8.3)(vite@5.4.19(@types/node@20.17.32)) + vitest: + specifier: ^3.1.2 + version: 3.1.2(@types/node@20.17.32)(jsdom@26.1.0) + + packages/vue: + dependencies: + vue: + specifier: ^3.0.0 + version: 3.5.13(typescript@5.8.3) + devDependencies: + '@babel/core': + specifier: ^7.26.7 + version: 7.27.1 + '@babel/plugin-proposal-decorators': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-function-sent': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-throw-expressions': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-export-namespace-from': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-numeric-separator': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-object-assign': + specifier: ^7.25.9 + version: 7.27.1(@babel/core@7.27.1) + '@babel/preset-env': + specifier: ^7.26.7 + version: 7.27.1(@babel/core@7.27.1) + '@testing-library/vue': + specifier: ^8.1.0 + version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.8.3)) + '@types/node': + specifier: ^22.15.3 + version: 22.15.3 + '@typescript-eslint/eslint-plugin': + specifier: ^8.21.0 + version: 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.21.0 + version: 8.31.1(eslint@9.25.1)(typescript@5.8.3) + '@vue/test-utils': + specifier: ^2.4.6 + version: 2.4.6 + eslint: + specifier: ^9.0.0 + version: 9.25.1 + laravel-echo: + specifier: workspace:^ + version: link:../laravel-echo + prettier: + specifier: ^3.5.3 + version: 3.5.3 + pusher-js: + specifier: ^8.0 + version: 8.4.0 + socket.io-client: + specifier: ^4.0 + version: 4.8.1 + tslib: + specifier: ^2.8.1 + version: 2.8.1 + typescript: + specifier: ^5.7.0 + version: 5.8.3 + vite: + specifier: ^6.3.3 + version: 6.3.4(@types/node@22.15.3) + vite-plugin-dts: + specifier: ^4.5.3 + version: 4.5.3(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3)(vite@6.3.4(@types/node@22.15.3)) + vitest: + specifier: ^3.1.2 + version: 3.1.2(@types/node@22.15.3)(jsdom@26.1.0) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@asamuzakjp/css-color@3.1.5': + resolution: {integrity: sha512-w7AmVyTTiU41fNLsFDf+gA2Dwtbx2EJtn2pbJNAGSRAg50loXy1uLXA3hEpD8+eydcomTurw09tq5/AyceCaGg==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.27.1': + resolution: {integrity: sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.27.1': + resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.27.1': + resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.1': + resolution: {integrity: sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.1': + resolution: {integrity: sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.1': + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.27.0': + resolution: {integrity: sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.27.1': + resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.4': + resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.1': + resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.27.1': + resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.1': + resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.1': + resolution: {integrity: sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1': + resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1': + resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-decorators@7.27.1': + resolution: {integrity: sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-function-sent@7.27.1': + resolution: {integrity: sha512-xA8Bqt8p12TxOFy3os20LxmOoHjyhzRC3zBql57d2W/YarNHgxHB4IlLHf3nXb7N6vSZ6kAdOoK2z5h0evGMhw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-throw-expressions@7.27.1': + resolution: {integrity: sha512-pnGZCFdGiN3vHk54wWIvLJV3MXviRjCkSWhPtCkra6AW3AP3AcrRByT5jOnuk6nwu9VYT/B7ujdaLiBnkmc0hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.27.1': + resolution: {integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.27.1': + resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.27.1': + resolution: {integrity: sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.27.1': + resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.27.1': + resolution: {integrity: sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.27.1': + resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.27.1': + resolution: {integrity: sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.27.1': + resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.27.1': + resolution: {integrity: sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.27.1': + resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.27.1': + resolution: {integrity: sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.27.1': + resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.27.1': + resolution: {integrity: sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.27.1': + resolution: {integrity: sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.27.1': + resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-assign@7.27.1': + resolution: {integrity: sha512-LP6tsnirA6iy13uBKiYgjJsfQrodmlSrpZModtlo1Vk8sOO68gfo7dfA9TGJyEgxTiO7czK4EGZm8FJEZtk4kQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.27.1': + resolution: {integrity: sha512-/sSliVc9gHE20/7D5qsdGlq7RG5NCDTWsAhyqzGuq174EtWJoGzIu1BQ7G56eDsTcy1jseBZwv50olSdXOlGuA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.27.1': + resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.27.1': + resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.1': + resolution: {integrity: sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.27.1': + resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.27.1': + resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.27.1': + resolution: {integrity: sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.27.1': + resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.27.1': + resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.27.1': + resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.27.1': + resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.27.1': + resolution: {integrity: sha512-TZ5USxFpLgKDpdEt8YWBR7p6g+bZo6sHaXLqP2BY/U0acaoI8FTVflcYCr/v94twM1C5IWFdZ/hscq9WjUeLXA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.1': + resolution: {integrity: sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.1': + resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.1': + resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} + engines: {node: '>=6.9.0'} + + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.3': + resolution: {integrity: sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-color-parser@3.0.9': + resolution: {integrity: sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-parser-algorithms@3.0.4': + resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-tokenizer@3.0.3': + resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + engines: {node: '>=18'} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.25.3': + resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.3': + resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.25.3': + resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.25.3': + resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.25.3': + resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.3': + resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.25.3': + resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.3': + resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.25.3': + resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.25.3': + resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.25.3': + resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.25.3': + resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.25.3': + resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.25.3': + resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.3': + resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.25.3': + resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.3': + resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.3': + resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.3': + resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.3': + resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.3': + resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.3': + resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.3': + resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.3': + resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.3': + resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.6.1': + resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.25.1': + resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@microsoft/api-extractor-model@7.28.13': + resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} + + '@microsoft/api-extractor-model@7.30.5': + resolution: {integrity: sha512-0ic4rcbcDZHz833RaTZWTGu+NpNgrxVNjVaor0ZDUymfDFzjA/Uuk8hYziIUIOEOSTfmIQqyzVwlzxZxPe7tOA==} + + '@microsoft/api-extractor@7.43.0': + resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==} + hasBin: true + + '@microsoft/api-extractor@7.52.5': + resolution: {integrity: sha512-6WWgjjg6FkoDWpF/O3sjB05OkszpI5wtKJqd8fUIR/JJUv8IqNCGr1lJUZJnc1HegcT9gAvyf98KfH0wFncU0w==} + hasBin: true + + '@microsoft/tsdoc-config@0.16.2': + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + + '@microsoft/tsdoc-config@0.17.1': + resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==} + + '@microsoft/tsdoc@0.14.2': + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.40.1': + resolution: {integrity: sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.40.1': + resolution: {integrity: sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.40.1': + resolution: {integrity: sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.40.1': + resolution: {integrity: sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.40.1': + resolution: {integrity: sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.40.1': + resolution: {integrity: sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.40.1': + resolution: {integrity: sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.40.1': + resolution: {integrity: sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.40.1': + resolution: {integrity: sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.40.1': + resolution: {integrity: sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.40.1': + resolution: {integrity: sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.1': + resolution: {integrity: sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.40.1': + resolution: {integrity: sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.40.1': + resolution: {integrity: sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.40.1': + resolution: {integrity: sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.40.1': + resolution: {integrity: sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.40.1': + resolution: {integrity: sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.40.1': + resolution: {integrity: sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.40.1': + resolution: {integrity: sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.40.1': + resolution: {integrity: sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==} + cpu: [x64] + os: [win32] + + '@rushstack/node-core-library@4.0.2': + resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/node-core-library@5.13.0': + resolution: {integrity: sha512-IGVhy+JgUacAdCGXKUrRhwHMTzqhWwZUI+qEPcdzsb80heOw0QPbhhoVsoiMF7Klp8eYsp7hzpScMXmOa3Uhfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.2': + resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} + + '@rushstack/rig-package@0.5.3': + resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==} + + '@rushstack/terminal@0.10.0': + resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/terminal@0.15.2': + resolution: {integrity: sha512-7Hmc0ysK5077R/IkLS9hYu0QuNafm+TbZbtYVzCMbeOdMjaRboLKrhryjwZSRJGJzu+TV1ON7qZHeqf58XfLpA==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.19.1': + resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==} + + '@rushstack/ts-command-line@5.0.0': + resolution: {integrity: sha512-SW6nqZVxH26Rxz25+lJQRlnXI/YCrNH7NfDEWPPm9i0rwkSE6Rgtmzw96cuZgQjacOh0sw77d6V4SvgarAfr8g==} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/dom@9.3.4': + resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} + engines: {node: '>=14'} + + '@testing-library/react-hooks@8.0.1': + resolution: {integrity: sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==} + engines: {node: '>=12'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + + '@testing-library/react@14.3.1': + resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==} + engines: {node: '>=14'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + + '@testing-library/vue@8.1.0': + resolution: {integrity: sha512-ls4RiHO1ta4mxqqajWRh8158uFObVrrtAPoxk7cIp4HrnQUj/ScKzqz53HxYpG3X6Zb7H2v+0eTGLSoy8HQ2nA==} + engines: {node: '>=14'} + peerDependencies: + '@vue/compiler-sfc': '>= 3' + vue: '>= 3' + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@20.17.32': + resolution: {integrity: sha512-zeMXFn8zQ+UkjK4ws0RiOC9EWByyW1CcVmLe+2rQocXRsGEDxUCwPEIVgpsGcLHS/P8JkT0oa3839BRABS0oPw==} + + '@types/node@22.15.3': + resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} + + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} + peerDependencies: + '@types/react': ^18.0.0 + + '@types/react-dom@19.1.3': + resolution: {integrity: sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.1.2': + resolution: {integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==} + + '@typescript-eslint/eslint-plugin@8.31.1': + resolution: {integrity: sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.31.1': + resolution: {integrity: sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.31.1': + resolution: {integrity: sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.31.1': + resolution: {integrity: sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.31.1': + resolution: {integrity: sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.31.1': + resolution: {integrity: sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.31.1': + resolution: {integrity: sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.31.1': + resolution: {integrity: sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitest/expect@3.1.2': + resolution: {integrity: sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==} + + '@vitest/mocker@3.1.2': + resolution: {integrity: sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.1.2': + resolution: {integrity: sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==} + + '@vitest/runner@3.1.2': + resolution: {integrity: sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==} + + '@vitest/snapshot@3.1.2': + resolution: {integrity: sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==} + + '@vitest/spy@3.1.2': + resolution: {integrity: sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==} + + '@vitest/utils@3.1.2': + resolution: {integrity: sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==} + + '@volar/language-core@1.11.1': + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + + '@volar/language-core@2.4.13': + resolution: {integrity: sha512-MnQJ7eKchJx5Oz+YdbqyFUk8BN6jasdJv31n/7r6/WwlOOv7qzvot6B66887l2ST3bUW4Mewml54euzpJWA6bg==} + + '@volar/source-map@1.11.1': + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + + '@volar/source-map@2.4.13': + resolution: {integrity: sha512-l/EBcc2FkvHgz2ZxV+OZK3kMSroMr7nN3sZLF2/f6kWW66q8+tEL4giiYyFjt0BcubqJhBt6soYIrAPhg/Yr+Q==} + + '@volar/typescript@1.11.1': + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + + '@volar/typescript@2.4.13': + resolution: {integrity: sha512-Ukz4xv84swJPupZeoFsQoeJEOm7U9pqsEnaGGgt5ni3SCTa22m8oJP5Nng3Wed7Uw5RBELdLxxORX8YhJPyOgQ==} + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-sfc@3.5.13': + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + + '@vue/compiler-ssr@3.5.13': + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/language-core@1.8.27': + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.13': + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + + '@vue/runtime-core@3.5.13': + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + + '@vue/runtime-dom@3.5.13': + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + + '@vue/server-renderer@3.5.13': + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} + peerDependencies: + vue: 3.5.13 + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + + '@vue/test-utils@2.4.6': + resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ajv@8.13.0: + resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + babel-plugin-polyfill-corejs2@0.4.13: + resolution: {integrity: sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.4: + resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + browserslist@4.24.5: + resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001715: + resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} + + caniuse-lite@1.0.30001716: + resolution: {integrity: sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.2: + resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssstyle@4.3.1: + resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==} + engines: {node: '>=18'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + editorconfig@1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + + electron-to-chromium@1.5.144: + resolution: {integrity: sha512-eJIaMRKeAzxfBSxtjYnoIAw/tdD6VIH6tHBZepZnAbE3Gyqqs5mGN87DvcldPUbVkIljTK8pY0CMcUljP64lfQ==} + + electron-to-chromium@1.5.149: + resolution: {integrity: sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + engine.io-client@6.6.3: + resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.0: + resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.3: + resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.25.1: + resolution: {integrity: sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.2.1: + resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + engines: {node: '>=12.0.0'} + + exsolve@1.0.5: + resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.4.4: + resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-beautify@1.15.4: + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} + hasBin: true + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + local-pkg@1.1.1: + resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==} + engines: {node: '>=14'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + nwsapi@2.2.20: + resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.1.0: + resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pusher-js@8.4.0: + resolution: {integrity: sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==} + + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-dom@19.1.0: + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + peerDependencies: + react: ^19.1.0 + + react-error-boundary@3.1.4: + resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13.1' + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.40.1: + resolution: {integrity: sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + socket.io-client@4.8.1: + resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} + engines: {node: '>=10.0.0'} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.13: + resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + validator@13.15.0: + resolution: {integrity: sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==} + engines: {node: '>= 0.10'} + + vite-node@3.1.2: + resolution: {integrity: sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite-plugin-dts@3.9.1: + resolution: {integrity: sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite-plugin-dts@4.5.3: + resolution: {integrity: sha512-P64VnD00dR+e8S26ESoFELqc17+w7pKkwlBpgXteOljFyT0zDwD8hH4zXp49M/kciy//7ZbVXIwQCekBJjfWzA==} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite@5.4.19: + resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@6.3.4: + resolution: {integrity: sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + 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 + + vitest@3.1.2: + resolution: {integrity: sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.1.2 + '@vitest/ui': 3.1.2 + 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 + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-component-type-helpers@2.2.10: + resolution: {integrity: sha512-iDUO7uQK+Sab2tYuiP9D1oLujCWlhHELHMgV/cB13cuGbG4qwkLHvtfWb6FzvxrIOPDnU0oHsz2MlQjhYDeaHA==} + + vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + + vue-tsc@1.8.27: + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + + vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + 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 + + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + 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 + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xmlhttprequest-ssl@2.1.2: + resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} + engines: {node: '>=0.4.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@asamuzakjp/css-color@3.1.5': + dependencies: + '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-color-parser': 3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + lru-cache: 10.4.3 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.27.1': {} + + '@babel/core@7.27.1': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helpers': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/template': 7.27.1 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.27.1': + dependencies: + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.27.1 + + '@babel/helper-annotate-as-pure@7.27.1': + dependencies: + '@babel/types': 7.27.1 + + '@babel/helper-compilation-targets@7.27.1': + dependencies: + '@babel/compat-data': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.24.5 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.1 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.27.1 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.27.0(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.1 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + debug: 4.4.0 + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.27.1 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.1 + '@babel/helper-wrap-function': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.27.1': + dependencies: + '@babel/template': 7.27.1 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.27.1': + dependencies: + '@babel/template': 7.27.1 + '@babel/types': 7.27.1 + + '@babel/parser@7.27.1': + dependencies: + '@babel/types': 7.27.1 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.27.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-decorators@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.27.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-function-sent@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-wrap-function': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + + '@babel/plugin-proposal-throw-expressions@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-async-generator-functions@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.1) + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-block-scoping@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1) + '@babel/traverse': 7.27.1 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.1 + + '@babel/plugin-transform-destructuring@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-object-assign@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-object-rest-spread@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.27.1) + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-regenerator@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/preset-env@7.27.1(@babel/core@7.27.1)': + dependencies: + '@babel/compat-data': 7.27.1 + '@babel/core': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.27.1) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.27.1) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-block-scoping': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-destructuring': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-object-rest-spread': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.27.1) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.27.1) + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.27.1) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.27.1) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.27.1) + core-js-compat: 3.41.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.27.1)': + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.27.1 + esutils: 2.0.3 + + '@babel/runtime@7.27.0': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.27.1': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 + + '@babel/traverse@7.27.1': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/template': 7.27.1 + '@babel/types': 7.27.1 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.27.1': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@csstools/color-helpers@5.0.2': {} + + '@csstools/css-calc@2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-color-parser@3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/color-helpers': 5.0.2 + '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-tokenizer@3.0.3': {} + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.25.3': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.25.3': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.25.3': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.25.3': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.25.3': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.25.3': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.25.3': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.25.3': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.25.3': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.25.3': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.25.3': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.25.3': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.25.3': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.25.3': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.25.3': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.25.3': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.25.3': + optional: true + + '@esbuild/netbsd-arm64@0.25.3': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.25.3': + optional: true + + '@esbuild/openbsd-arm64@0.25.3': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.25.3': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.25.3': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.25.3': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.25.3': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.25.3': + optional: true + + '@eslint-community/eslint-utils@4.6.1(eslint@9.25.1)': + dependencies: + eslint: 9.25.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.1': {} + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.25.1': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@microsoft/api-extractor-model@7.28.13(@types/node@20.17.32)': + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.17.32) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor-model@7.30.5(@types/node@22.15.3)': + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.13.0(@types/node@22.15.3) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.43.0(@types/node@20.17.32)': + dependencies: + '@microsoft/api-extractor-model': 7.28.13(@types/node@20.17.32) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.17.32) + '@rushstack/rig-package': 0.5.2 + '@rushstack/terminal': 0.10.0(@types/node@20.17.32) + '@rushstack/ts-command-line': 4.19.1(@types/node@20.17.32) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.10 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.4.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.52.5(@types/node@22.15.3)': + dependencies: + '@microsoft/api-extractor-model': 7.30.5(@types/node@22.15.3) + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.13.0(@types/node@22.15.3) + '@rushstack/rig-package': 0.5.3 + '@rushstack/terminal': 0.15.2(@types/node@22.15.3) + '@rushstack/ts-command-line': 5.0.0(@types/node@22.15.3) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.10 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.8.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.16.2': + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + + '@microsoft/tsdoc-config@0.17.1': + dependencies: + '@microsoft/tsdoc': 0.15.1 + ajv: 8.12.0 + jju: 1.4.0 + resolve: 1.22.10 + + '@microsoft/tsdoc@0.14.2': {} + + '@microsoft/tsdoc@0.15.1': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@one-ini/wasm@0.1.1': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/pluginutils@5.1.4(rollup@4.40.1)': + dependencies: + '@types/estree': 1.0.7 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.40.1 + + '@rollup/rollup-android-arm-eabi@4.40.1': + optional: true + + '@rollup/rollup-android-arm64@4.40.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.40.1': + optional: true + + '@rollup/rollup-darwin-x64@4.40.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.40.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.40.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.40.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.40.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.40.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.40.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.40.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.40.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.40.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.40.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.40.1': + optional: true + + '@rushstack/node-core-library@4.0.2(@types/node@20.17.32)': + dependencies: + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.10 + semver: 7.5.4 + z-schema: 5.0.5 + optionalDependencies: + '@types/node': 20.17.32 + + '@rushstack/node-core-library@5.13.0(@types/node@22.15.3)': + dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) + fs-extra: 11.3.0 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.10 + semver: 7.5.4 + optionalDependencies: + '@types/node': 22.15.3 + + '@rushstack/rig-package@0.5.2': + dependencies: + resolve: 1.22.10 + strip-json-comments: 3.1.1 + + '@rushstack/rig-package@0.5.3': + dependencies: + resolve: 1.22.10 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.10.0(@types/node@20.17.32)': + dependencies: + '@rushstack/node-core-library': 4.0.2(@types/node@20.17.32) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.17.32 + + '@rushstack/terminal@0.15.2(@types/node@22.15.3)': + dependencies: + '@rushstack/node-core-library': 5.13.0(@types/node@22.15.3) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 22.15.3 + + '@rushstack/ts-command-line@4.19.1(@types/node@20.17.32)': + dependencies: + '@rushstack/terminal': 0.10.0(@types/node@20.17.32) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/ts-command-line@5.0.0(@types/node@22.15.3)': + dependencies: + '@rushstack/terminal': 0.15.2(@types/node@22.15.3) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@socket.io/component-emitter@3.1.2': {} + + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.27.0 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/dom@9.3.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/runtime': 7.27.0 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/react-hooks@8.0.1(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + react: 19.1.0 + react-error-boundary: 3.1.4(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + react-dom: 19.1.0(react@19.1.0) + + '@testing-library/react@14.3.1(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@testing-library/dom': 9.3.4 + '@types/react-dom': 18.3.7(@types/react@19.1.2) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + transitivePeerDependencies: + - '@types/react' + + '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.8.3))': + dependencies: + '@babel/runtime': 7.27.0 + '@testing-library/dom': 9.3.4 + '@vue/test-utils': 2.4.6 + vue: 3.5.13(typescript@5.8.3) + optionalDependencies: + '@vue/compiler-sfc': 3.5.13 + + '@types/argparse@1.0.38': {} + + '@types/aria-query@5.0.4': {} + + '@types/estree@1.0.7': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@20.17.32': + dependencies: + undici-types: 6.19.8 + + '@types/node@22.15.3': + dependencies: + undici-types: 6.21.0 + + '@types/react-dom@18.3.7(@types/react@19.1.2)': + dependencies: + '@types/react': 19.1.2 + + '@types/react-dom@19.1.3(@types/react@19.1.2)': + dependencies: + '@types/react': 19.1.2 + + '@types/react@19.1.2': + dependencies: + csstype: 3.1.3 + + '@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.31.1(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.31.1 + '@typescript-eslint/type-utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.31.1 + eslint: 9.25.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.31.1 + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.31.1 + debug: 4.4.0 + eslint: 9.25.1 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.31.1': + dependencies: + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/visitor-keys': 8.31.1 + + '@typescript-eslint/type-utils@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) + debug: 4.4.0 + eslint: 9.25.1 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.31.1': {} + + '@typescript-eslint/typescript-estree@8.31.1(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/visitor-keys': 8.31.1 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1) + '@typescript-eslint/scope-manager': 8.31.1 + '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) + eslint: 9.25.1 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.31.1': + dependencies: + '@typescript-eslint/types': 8.31.1 + eslint-visitor-keys: 4.2.0 + + '@vitest/expect@3.1.2': + dependencies: + '@vitest/spy': 3.1.2 + '@vitest/utils': 3.1.2 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.1.2(vite@5.4.19(@types/node@20.17.32))': + dependencies: + '@vitest/spy': 3.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 5.4.19(@types/node@20.17.32) + + '@vitest/mocker@3.1.2(vite@5.4.19(@types/node@22.15.3))': + dependencies: + '@vitest/spy': 3.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 5.4.19(@types/node@22.15.3) + + '@vitest/pretty-format@3.1.2': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.1.2': + dependencies: + '@vitest/utils': 3.1.2 + pathe: 2.0.3 + + '@vitest/snapshot@3.1.2': + dependencies: + '@vitest/pretty-format': 3.1.2 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.1.2': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@3.1.2': + dependencies: + '@vitest/pretty-format': 3.1.2 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + + '@volar/language-core@1.11.1': + dependencies: + '@volar/source-map': 1.11.1 + + '@volar/language-core@2.4.13': + dependencies: + '@volar/source-map': 2.4.13 + + '@volar/source-map@1.11.1': + dependencies: + muggle-string: 0.3.1 + + '@volar/source-map@2.4.13': {} + + '@volar/typescript@1.11.1': + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + + '@volar/typescript@2.4.13': + dependencies: + '@volar/language-core': 2.4.13 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.27.1 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-sfc@3.5.13': + dependencies: + '@babel/parser': 7.27.1 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.3 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.13': + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/language-core@1.8.27(typescript@5.8.3)': + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + computeds: 0.0.1 + minimatch: 9.0.5 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.16 + optionalDependencies: + typescript: 5.8.3 + + '@vue/language-core@2.2.0(typescript@5.8.3)': + dependencies: + '@volar/language-core': 2.4.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 0.4.14 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.8.3 + + '@vue/reactivity@3.5.13': + dependencies: + '@vue/shared': 3.5.13 + + '@vue/runtime-core@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/runtime-dom@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.8.3))': + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13(typescript@5.8.3) + + '@vue/shared@3.5.13': {} + + '@vue/test-utils@2.4.6': + dependencies: + js-beautify: 1.15.4 + vue-component-type-helpers: 2.2.10 + + abbrev@2.0.0: {} + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + agent-base@7.1.3: {} + + ajv-draft-04@1.0.0(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@3.0.1(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.13.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + alien-signals@0.4.14: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + assertion-error@2.0.1: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.27.1): + dependencies: + '@babel/compat-data': 7.27.1 + '@babel/core': 7.27.1 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.27.1): + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.1) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.27.1): + dependencies: + '@babel/core': 7.27.1 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.1) + transitivePeerDependencies: + - supports-color + + balanced-match@1.0.2: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001715 + electron-to-chromium: 1.5.144 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + browserslist@4.24.5: + dependencies: + caniuse-lite: 1.0.30001716 + electron-to-chromium: 1.5.149 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.5) + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001715: {} + + caniuse-lite@1.0.30001716: {} + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + check-error@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@10.0.1: {} + + commander@9.5.0: + optional: true + + compare-versions@6.1.1: {} + + computeds@0.0.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + confbox@0.2.2: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + convert-source-map@2.0.0: {} + + core-js-compat@3.41.0: + dependencies: + browserslist: 4.24.4 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssstyle@4.3.1: + dependencies: + '@asamuzakjp/css-color': 3.1.5 + rrweb-cssom: 0.8.0 + + csstype@3.1.3: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + de-indent@1.0.2: {} + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decimal.js@10.5.0: {} + + deep-eql@5.0.2: {} + + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + dequal@2.0.3: {} + + dom-accessibility-api@0.5.16: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + editorconfig@1.0.4: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.7.1 + + electron-to-chromium@1.5.144: {} + + electron-to-chromium@1.5.149: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + engine.io-client@6.6.3: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + xmlhttprequest-ssl: 2.1.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + engine.io-parser@5.2.3: {} + + entities@4.5.0: {} + + entities@6.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.25.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.3 + '@esbuild/android-arm': 0.25.3 + '@esbuild/android-arm64': 0.25.3 + '@esbuild/android-x64': 0.25.3 + '@esbuild/darwin-arm64': 0.25.3 + '@esbuild/darwin-x64': 0.25.3 + '@esbuild/freebsd-arm64': 0.25.3 + '@esbuild/freebsd-x64': 0.25.3 + '@esbuild/linux-arm': 0.25.3 + '@esbuild/linux-arm64': 0.25.3 + '@esbuild/linux-ia32': 0.25.3 + '@esbuild/linux-loong64': 0.25.3 + '@esbuild/linux-mips64el': 0.25.3 + '@esbuild/linux-ppc64': 0.25.3 + '@esbuild/linux-riscv64': 0.25.3 + '@esbuild/linux-s390x': 0.25.3 + '@esbuild/linux-x64': 0.25.3 + '@esbuild/netbsd-arm64': 0.25.3 + '@esbuild/netbsd-x64': 0.25.3 + '@esbuild/openbsd-arm64': 0.25.3 + '@esbuild/openbsd-x64': 0.25.3 + '@esbuild/sunos-x64': 0.25.3 + '@esbuild/win32-arm64': 0.25.3 + '@esbuild/win32-ia32': 0.25.3 + '@esbuild/win32-x64': 0.25.3 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.25.1: + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.13.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.25.1 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.7 + + esutils@2.0.3: {} + + expect-type@1.2.1: {} + + exsolve@1.0.5: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.4.4(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + 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 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globals@11.12.0: {} + + globals@14.0.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-lazy@4.0.0: {} + + imurmurhash@0.1.4: {} + + ini@1.3.8: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-weakmap@2.0.2: {} + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jju@1.4.0: {} + + js-beautify@1.15.4: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.4.5 + js-cookie: 3.0.5 + nopt: 7.2.1 + + js-cookie@3.0.5: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdom@26.1.0: + dependencies: + cssstyle: 4.3.1 + data-urls: 5.0.0 + decimal.js: 10.5.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.20 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.18.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.0.2: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kolorist@1.8.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + local-pkg@1.1.1: + dependencies: + mlly: 1.7.4 + pkg-types: 2.1.0 + quansync: 0.2.10 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.debounce@4.0.8: {} + + lodash.get@4.4.2: {} + + lodash.isequal@4.5.0: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + loupe@3.1.3: {} + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lz-string@1.5.0: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + math-intrinsics@1.1.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.11 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + mlly@1.7.4: + dependencies: + acorn: 8.14.1 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 + + ms@2.1.3: {} + + muggle-string@0.3.1: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.19: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + nwsapi@2.2.20: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.0 + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + pkg-types@2.1.0: + dependencies: + confbox: 0.2.2 + exsolve: 1.0.5 + pathe: 2.0.3 + + possible-typed-array-names@1.1.0: {} + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@3.5.3: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + proto-list@1.2.4: {} + + punycode@2.3.1: {} + + pusher-js@8.4.0: + dependencies: + tweetnacl: 1.0.3 + + quansync@0.2.10: {} + + queue-microtask@1.2.3: {} + + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + + react-error-boundary@3.1.4(react@19.1.0): + dependencies: + '@babel/runtime': 7.27.0 + react: 19.1.0 + + react-is@17.0.2: {} + + react@19.1.0: {} + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.14.1: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.2.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} + + regjsparser@0.12.0: + dependencies: + jsesc: 3.0.2 + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve@1.19.0: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + rollup@4.40.1: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.40.1 + '@rollup/rollup-android-arm64': 4.40.1 + '@rollup/rollup-darwin-arm64': 4.40.1 + '@rollup/rollup-darwin-x64': 4.40.1 + '@rollup/rollup-freebsd-arm64': 4.40.1 + '@rollup/rollup-freebsd-x64': 4.40.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.1 + '@rollup/rollup-linux-arm-musleabihf': 4.40.1 + '@rollup/rollup-linux-arm64-gnu': 4.40.1 + '@rollup/rollup-linux-arm64-musl': 4.40.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.1 + '@rollup/rollup-linux-riscv64-gnu': 4.40.1 + '@rollup/rollup-linux-riscv64-musl': 4.40.1 + '@rollup/rollup-linux-s390x-gnu': 4.40.1 + '@rollup/rollup-linux-x64-gnu': 4.40.1 + '@rollup/rollup-linux-x64-musl': 4.40.1 + '@rollup/rollup-win32-arm64-msvc': 4.40.1 + '@rollup/rollup-win32-ia32-msvc': 4.40.1 + '@rollup/rollup-win32-x64-msvc': 4.40.1 + fsevents: 2.3.3 + + rrweb-cssom@0.8.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.26.0: {} + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + semver@7.7.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + socket.io-client@4.8.1: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-client: 6.6.3 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + stackback@0.0.2: {} + + std-env@3.9.0: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.13: + dependencies: + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + ts-api-utils@2.1.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + + tslib@2.8.1: {} + + tweetnacl@1.0.3: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript@5.4.2: {} + + typescript@5.8.2: {} + + typescript@5.8.3: {} + + ufo@1.6.1: {} + + undici-types@6.19.8: {} + + undici-types@6.21.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + update-browserslist-db@1.1.3(browserslist@4.24.5): + dependencies: + browserslist: 4.24.5 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + validator@13.15.0: {} + + vite-node@3.1.2(@types/node@20.17.32): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 5.4.19(@types/node@20.17.32) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite-node@3.1.2(@types/node@22.15.3): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 5.4.19(@types/node@22.15.3) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite-plugin-dts@3.9.1(@types/node@20.17.32)(rollup@4.40.1)(typescript@5.8.3)(vite@5.4.19(@types/node@20.17.32)): + dependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@20.17.32) + '@rollup/pluginutils': 5.1.4(rollup@4.40.1) + '@vue/language-core': 1.8.27(typescript@5.8.3) + debug: 4.4.0 + kolorist: 1.8.0 + magic-string: 0.30.17 + typescript: 5.8.3 + vue-tsc: 1.8.27(typescript@5.8.3) + optionalDependencies: + vite: 5.4.19(@types/node@20.17.32) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite-plugin-dts@4.5.3(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3)(vite@6.3.4(@types/node@22.15.3)): + dependencies: + '@microsoft/api-extractor': 7.52.5(@types/node@22.15.3) + '@rollup/pluginutils': 5.1.4(rollup@4.40.1) + '@volar/typescript': 2.4.13 + '@vue/language-core': 2.2.0(typescript@5.8.3) + compare-versions: 6.1.1 + debug: 4.4.0 + kolorist: 1.8.0 + local-pkg: 1.1.1 + magic-string: 0.30.17 + typescript: 5.8.3 + optionalDependencies: + vite: 6.3.4(@types/node@22.15.3) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite@5.4.19(@types/node@20.17.32): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.3 + rollup: 4.40.1 + optionalDependencies: + '@types/node': 20.17.32 + fsevents: 2.3.3 + + vite@5.4.19(@types/node@22.15.3): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.3 + rollup: 4.40.1 + optionalDependencies: + '@types/node': 22.15.3 + fsevents: 2.3.3 + + vite@6.3.4(@types/node@22.15.3): + dependencies: + esbuild: 0.25.3 + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.3 + rollup: 4.40.1 + tinyglobby: 0.2.13 + optionalDependencies: + '@types/node': 22.15.3 + fsevents: 2.3.3 + + vitest@3.1.2(@types/node@20.17.32)(jsdom@26.1.0): + dependencies: + '@vitest/expect': 3.1.2 + '@vitest/mocker': 3.1.2(vite@5.4.19(@types/node@20.17.32)) + '@vitest/pretty-format': 3.1.2 + '@vitest/runner': 3.1.2 + '@vitest/snapshot': 3.1.2 + '@vitest/spy': 3.1.2 + '@vitest/utils': 3.1.2 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.13 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 5.4.19(@types/node@20.17.32) + vite-node: 3.1.2(@types/node@20.17.32) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.17.32 + jsdom: 26.1.0 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vitest@3.1.2(@types/node@22.15.3)(jsdom@26.1.0): + dependencies: + '@vitest/expect': 3.1.2 + '@vitest/mocker': 3.1.2(vite@5.4.19(@types/node@22.15.3)) + '@vitest/pretty-format': 3.1.2 + '@vitest/runner': 3.1.2 + '@vitest/snapshot': 3.1.2 + '@vitest/spy': 3.1.2 + '@vitest/utils': 3.1.2 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.13 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 5.4.19(@types/node@22.15.3) + vite-node: 3.1.2(@types/node@22.15.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.15.3 + jsdom: 26.1.0 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vscode-uri@3.1.0: {} + + vue-component-type-helpers@2.2.10: {} + + vue-template-compiler@2.7.16: + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + vue-tsc@1.8.27(typescript@5.8.3): + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.8.3) + semver: 7.7.1 + typescript: 5.8.3 + + vue@3.5.13(typescript@5.8.3): + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.8.3)) + '@vue/shared': 3.5.13 + optionalDependencies: + typescript: 5.8.3 + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + ws@8.17.1: {} + + ws@8.18.1: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + xmlhttprequest-ssl@2.1.2: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yocto-queue@0.1.0: {} + + z-schema@5.0.5: + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.15.0 + optionalDependencies: + commander: 9.5.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 00000000..dee51e92 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/release.sh b/release.sh new file mode 100755 index 00000000..80209922 --- /dev/null +++ b/release.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# Function to get current version from package.json +get_current_version() { + local package_json=$1 + if [ -f "$package_json" ]; then + grep '"version":' "$package_json" | cut -d\" -f4 + else + echo "Error: package.json not found at $package_json" + exit 1 + fi +} + +# Function to get package name from package.json +get_package_name() { + local package_json=$1 + if [ -f "$package_json" ]; then + grep '"name":' "$package_json" | cut -d\" -f4 + else + echo "Error: package.json not found at $package_json" + exit 1 + fi +} + +# Function to update version +update_version() { + local package_dir=$1 + local version_type=$2 + + case $version_type in + "patch") + pnpm version patch --no-git-tag-version + ;; + "minor") + pnpm version minor --no-git-tag-version + ;; + "major") + pnpm version major --no-git-tag-version + ;; + *) + echo "Invalid version type. Please choose patch/minor/major" + exit 1 + ;; + esac +} + +# Main script +echo "Starting package version management..." + +# Get root package version +root_package_json="packages/laravel-echo/package.json" +current_version=$(get_current_version "$root_package_json") +echo "" +echo "Current version: $current_version" +echo "" + +# Get version type once +read -p "Update version? (patch/minor/major): " version_type +echo "" + +# Iterate through packages directory +for package_dir in packages/*; do + if [ -d "$package_dir" ]; then + echo "Updating version for $package_dir" + + cd $package_dir + + # Update version + update_version "$package_dir" "$version_type" + + cd ../.. + + echo "" + fi +done + +# Get new version from root package +new_version=$(get_current_version "$root_package_json") + +# Install dependencies +echo "Updating lock file..." +pnpm i + +# Create single git tag +echo "" +echo "Creating git tag: v$new_version" +git tag "v$new_version" +echo "" + +echo "Running release process..." +echo "" +pnpm -r run release + +# Echo joke +echo "Released! (Released!) (Released!)" diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index d8e2b737..00000000 --- a/rollup.config.js +++ /dev/null @@ -1,50 +0,0 @@ -import babel from '@rollup/plugin-babel'; -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; - -export default [ - { - input: './src/echo.ts', - output: [ - { file: './dist/echo.js', format: 'esm' }, - { file: './dist/echo.common.js', format: 'cjs' }, - ], - plugins: [ - resolve(), - typescript({ - tsconfig: './tsconfig.json', // Ensures Rollup aligns with your TS settings - }), - babel({ - babelHelpers: 'bundled', - extensions: ['.ts'], - exclude: 'node_modules/**', - presets: ['@babel/preset-env'], - plugins: [ - '@babel/plugin-transform-numeric-separator', - '@babel/plugin-transform-export-namespace-from', - ['@babel/plugin-proposal-decorators', { legacy: true }], - '@babel/plugin-proposal-function-sent', - '@babel/plugin-proposal-throw-expressions', - '@babel/plugin-transform-object-assign', - ], - }), - ], - external: ['jquery', 'axios', 'vue', '@hotwired/turbo', 'tslib'], // Compatible packages not included in the bundle - }, - { - input: './src/index.iife.ts', - output: [{ file: './dist/echo.iife.js', format: 'iife', name: 'Echo' }], - plugins: [ - resolve(), - typescript({ - tsconfig: './tsconfig.json', - }), - babel({ - babelHelpers: 'bundled', - extensions: ['.ts'], - exclude: 'node_modules/**', - }), - ], - external: ['jquery', 'axios', 'vue', '@hotwired/turbo', 'tslib'], // Compatible packages not included in the bundle - }, -]; diff --git a/src/channel/index.ts b/src/channel/index.ts deleted file mode 100644 index 668f6385..00000000 --- a/src/channel/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export * from './channel'; -export * from './presence-channel'; -export * from './pusher-channel'; -export * from './pusher-private-channel'; -export * from './pusher-encrypted-private-channel'; -export * from './pusher-presence-channel'; -export * from './socketio-channel'; -export * from './socketio-private-channel'; -export * from './socketio-presence-channel'; -export * from './null-channel'; -export * from './null-private-channel'; -export * from './null-encrypted-private-channel'; -export * from './null-presence-channel'; diff --git a/src/channel/pusher-private-channel.ts b/src/channel/pusher-private-channel.ts deleted file mode 100644 index 59f36e92..00000000 --- a/src/channel/pusher-private-channel.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PusherChannel } from './pusher-channel'; -import type { BroadcastDriver } from '../echo'; - -/** - * This class represents a Pusher private channel. - */ -export class PusherPrivateChannel extends PusherChannel { - /** - * Send a whisper event to other clients in the channel. - */ - whisper(eventName: string, data: Record): this { - this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); - - return this; - } -} diff --git a/src/connector/index.ts b/src/connector/index.ts deleted file mode 100644 index 8353a357..00000000 --- a/src/connector/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './connector'; -export * from './pusher-connector'; -export * from './socketio-connector'; -export * from './null-connector'; diff --git a/src/index.iife.ts b/src/index.iife.ts deleted file mode 100644 index 3f6747e5..00000000 --- a/src/index.iife.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './echo'; diff --git a/tests/channel/socketio-channel.test.ts b/tests/channel/socketio-channel.test.ts deleted file mode 100644 index 1211ddaa..00000000 --- a/tests/channel/socketio-channel.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { SocketIoChannel } from '../../src/channel'; -import type { Socket } from 'socket.io-client'; -import { Connector } from '../../src/connector'; - -describe('SocketIoChannel', () => { - let channel: SocketIoChannel; - let socket: Socket; - - beforeEach(() => { - const channelName = 'some.channel'; - let listeners: any[] = []; - socket = { - emit: (event: any, data: unknown) => { - listeners.filter(([e]) => e === event).forEach(([, fn]) => fn(channelName, data)); - }, - on: (event: any, fn): any => listeners.push([event, fn]), - removeListener: (event: any, fn: any) => { - listeners = listeners.filter(([e, f]) => (!fn ? e !== event : e !== event || f !== fn)); - }, - } as Socket; - - channel = new SocketIoChannel(socket, channelName, { - broadcaster: 'socket.io', - ...Connector._defaultOptions, - namespace: false, - }); - }); - - test('triggers all listeners for an event', () => { - const l1 = jest.fn(); - const l2 = jest.fn(); - const l3 = jest.fn(); - channel.listen('MyEvent', l1); - channel.listen('MyEvent', l2); - channel.listen('MyOtherEvent', l3); - - socket.emit('MyEvent', {}); - - expect(l1).toBeCalled(); - expect(l2).toBeCalled(); - expect(l3).not.toBeCalled(); - - socket.emit('MyOtherEvent', {}); - - expect(l3).toBeCalled(); - }); - - test('can remove a listener for an event', () => { - const l1 = jest.fn(); - const l2 = jest.fn(); - const l3 = jest.fn(); - channel.listen('MyEvent', l1); - channel.listen('MyEvent', l2); - channel.listen('MyOtherEvent', l3); - - channel.stopListening('MyEvent', l1); - - socket.emit('MyEvent', {}); - - expect(l1).not.toBeCalled(); - expect(l2).toBeCalled(); - expect(l3).not.toBeCalled(); - - socket.emit('MyOtherEvent', {}); - - expect(l3).toBeCalled(); - }); - - test('can remove all listeners for an event', () => { - const l1 = jest.fn(); - const l2 = jest.fn(); - const l3 = jest.fn(); - channel.listen('MyEvent', l1); - channel.listen('MyEvent', l2); - channel.listen('MyOtherEvent', l3); - - channel.stopListening('MyEvent'); - - socket.emit('MyEvent', {}); - - expect(l1).not.toBeCalled(); - expect(l2).not.toBeCalled(); - expect(l3).not.toBeCalled(); - - socket.emit('MyOtherEvent', {}); - - expect(l3).toBeCalled(); - }); -}); diff --git a/tests/echo.test.ts b/tests/echo.test.ts deleted file mode 100644 index bf12a061..00000000 --- a/tests/echo.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Echo from '../src/echo'; -import { NullConnector } from '../src/connector'; - -describe('Echo', () => { - test('it will not throw error for supported driver', () => { - expect(() => new Echo({ broadcaster: 'reverb' })).not.toThrowError( - 'Broadcaster string reverb is not supported.' - ); - - expect(() => new Echo({ broadcaster: 'pusher' })).not.toThrowError( - 'Broadcaster string pusher is not supported.' - ); - - expect(() => new Echo({ broadcaster: 'socket.io' })).not.toThrowError( - 'Broadcaster string socket.io is not supported.' - ); - - expect(() => new Echo({ broadcaster: 'null' })).not.toThrowError('Broadcaster string null is not supported.'); - expect(() => new Echo({ broadcaster: NullConnector })).not.toThrowError(); - - // eslint-disable-next-line - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-empty-function - expect(() => new Echo({ broadcaster: () => {} })).not.toThrowError('Broadcaster function is not supported.'); - }); - - test('it will throw error for unsupported driver', () => { - // eslint-disable-next-line - // @ts-ignore - expect(() => new Echo({ broadcaster: 'foo' })).toThrowError('Broadcaster string foo is not supported.'); - }); -}); diff --git a/tests/util/event-formatter.test.ts b/tests/util/event-formatter.test.ts deleted file mode 100644 index 49492ab1..00000000 --- a/tests/util/event-formatter.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { EventFormatter } from '../../src/util'; - -describe('EventFormatter', () => { - let eventFormatter: EventFormatter; - - beforeEach(() => { - eventFormatter = new EventFormatter('App.Events'); - }); - - test('prepends an event with a namespace and replaces dot separators with backslashes', () => { - let formatted = eventFormatter.format('Users.UserCreated'); - - expect(formatted).toBe('App\\Events\\Users\\UserCreated'); - }); - - test('does not prepend a namespace when an event starts with a dot', () => { - let formatted = eventFormatter.format('.App\\Users\\UserCreated'); - - expect(formatted).toBe('App\\Users\\UserCreated'); - }); - - test('does not prepend a namespace when an event starts with a backslash', () => { - let formatted = eventFormatter.format('\\App\\Users\\UserCreated'); - - expect(formatted).toBe('App\\Users\\UserCreated'); - }); - - test('does not replace dot separators when the event starts with a dot', () => { - let formatted = eventFormatter.format('.users.created'); - - expect(formatted).toBe('users.created'); - }); - - test('does not replace dot separators when the event starts with a backslash', () => { - let formatted = eventFormatter.format('\\users.created'); - - expect(formatted).toBe('users.created'); - }); - - test('does not prepend a namespace when none is set', () => { - let eventFormatter = new EventFormatter(false); - - let formatted = eventFormatter.format('Users.UserCreated'); - - expect(formatted).toBe('Users\\UserCreated'); - }); -});