diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5a6a76f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +[*.json] +indent_style = space +indent_size = 2 diff --git a/.eslintignore b/.eslintignore index 884a4d8..9209ef5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,2 @@ -node_modules -out +node_modules +out diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 1f5f799..9164902 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -118,6 +118,7 @@ const IMPORT_PLUGIN_RULES = { const JSDOC_PLUGIN_RULES = { // Types are described in TypeScript 'jsdoc/require-param-type': 'off', + 'jsdoc/require-throws-type': 'off', 'jsdoc/no-undefined-types': 'off', 'jsdoc/require-returns-type': 'off', @@ -265,10 +266,6 @@ function mergeRules(...ruleSets) { module.exports = { root: true, parser: '@typescript-eslint/parser', - parserOptions: { - tsconfigRootDir: path.join(__dirname), - project: 'tsconfig.eslint.json', - }, plugins: [ 'import', 'import-newlines', @@ -285,7 +282,7 @@ module.exports = { 'plugin:n/recommended', ], ignorePatterns: [ - 'dist', + 'out', 'coverage', ], settings: { diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index c5ab9c9..d53fc16 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -38,6 +38,9 @@ jobs: - name: List files run: ls -alt + - name: Build shared library + run: pnpm --filter @vscode-adblock-syntax/shared build + - name: Check TypeScript types run: pnpm test:compile @@ -45,11 +48,26 @@ jobs: run: pnpm lint:md - name: Run ESLint - run: pnpm lint:ts + run: pnpm lint:code - - name: Run Jest tests + - name: Run Vitest tests run: pnpm test + - name: Build extension + run: pnpm build + + - name: Package extension + run: pnpm package + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: vscode-adblock-build + path: | + out/vscode-adblock.vsix + syntaxes/out/adblock.plist + retention-days: 30 + notify: name: Send Slack notification on failure needs: check_code diff --git a/.husky/install.mjs b/.husky/install.mjs new file mode 100644 index 0000000..1ce1cb4 --- /dev/null +++ b/.husky/install.mjs @@ -0,0 +1,12 @@ +// See: https://typicode.github.io/husky/how-to.html#ci-server-and-docker +import ci from 'ci-info'; + +// Do not initialize Husky in CI environments. +if (ci.isCI) { + console.log('Skipping Husky initialization, because we detected a CI environment:', ci.name); + process.exit(0); +} + +// Initialize Husky programmatically. +const husky = (await import('husky')).default; +console.log(husky()); diff --git a/.husky/pre-commit b/.husky/pre-commit index 4bf1cfd..7d8bd53 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,11 @@ -pnpm test:compile -pnpm lint:staged -pnpm test +# Exit immediately if a command fails +set -e +lint-staged + +# Corepack automatically adds a "packageManager" field to package.json. +# We don't want to commit this field, so we remove it from the staged version +# while keeping it in the working directory for local development. if git diff --cached --name-only | grep -q "package.json"; then echo "package.json is being committed. Checking if packageManager field is present..." diff --git a/.lintstagedrc b/.lintstagedrc deleted file mode 100644 index 8271ebe..0000000 --- a/.lintstagedrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "*.ts": "eslint", - "*.md": "markdownlint" -} diff --git a/.lintstagedrc.js b/.lintstagedrc.js new file mode 100644 index 0000000..dd39e6c --- /dev/null +++ b/.lintstagedrc.js @@ -0,0 +1,22 @@ +/** + * Lint-staged configuration for the monorepo root. + * + * Delegates to workspace-level configs for package-specific linting with + * type checking (tsc-files) and related tests (vitest related). + * + * @type {import('lint-staged').Config} + */ + +module.exports = { + // Root markdown files + '*.md': 'markdownlint', + + // Root-level tools and scripts + 'tools/**/*.{ts,js,cjs,mjs}': 'eslint --cache', + + // Delegate to workspace configs (they have tsc-files + vitest related) + 'client/**/*.{ts,js,md}': () => 'pnpm --filter @vscode-adblock-syntax/client exec lint-staged', + 'server/**/*.{ts,js,md}': () => 'pnpm --filter @vscode-adblock-syntax/server exec lint-staged', + 'shared/**/*.{ts,js,md}': () => 'pnpm --filter @vscode-adblock-syntax/shared exec lint-staged', + 'syntaxes/**/*.{ts,js,md,yaml-tmlanguage}': () => 'pnpm --filter @vscode-adblock-syntax/syntaxes exec lint-staged', +}; diff --git a/.markdownlint.json b/.markdownlint.json index 0934646..d66e758 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,15 +1,37 @@ { - "ul-indent": { "indent": 4 }, + "ul-indent": { + "indent": 4 + }, "line-length": { "stern": true, "line_length": 120 }, - "no-multiple-blanks": { "maximum": 2 }, - "no-inline-html": { "allowed_elements": ["a", "details", "summary", "img", "pre"]}, - "no-duplicate-heading": { "siblings_only": true }, + "no-multiple-blanks": { + "maximum": 2 + }, + "no-inline-html": { + "allowed_elements": [ + "a", + "details", + "summary", + "img", + "pre", + "div", + "p" + ] + }, + "no-duplicate-heading": { + "siblings_only": true + }, "no-blanks-blockquote": false, "no-bare-urls": false, - "ul-style": { "style": "dash" }, - "blanks-around-fences": { "list_items": false }, - "emphasis-style": { "style": "asterisk" } + "ul-style": { + "style": "dash" + }, + "blanks-around-fences": { + "list_items": false + }, + "emphasis-style": { + "style": "asterisk" + } } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 0a679e3..038c1a5 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,8 @@ -{ - "recommendations": [ - "connor4312.esbuild-problem-matchers", - "dbaeumer.vscode-eslint" - ] -} +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "davidanson.vscode-markdownlint", + "vitest.explorer", + "editorconfig.editorconfig" + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 50b2c68..2fd004b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,10 +1,81 @@ { "version": "2.0.0", "tasks": [ + { + "label": "Shared lib rspack build (watch)", + "type": "shell", + "command": "pnpm exec cross-env NODE_ENV=dev pnpm --silent --filter @vscode-adblock-syntax/shared rspack --watch", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "panel": "dedicated", + "reveal": "never", + "close": true + }, + "problemMatcher": { + "owner": "rspack", + "source": "rspack", + "fileLocation": [ + "relative", + "${workspaceFolder}/shared" + ], + "pattern": [ + { + // ERROR in ./src/server.ts 8:0-25 + "regexp": "^(ERROR|WARNING) in\\s+(.+)\\s+(\\d+):(\\d+)(?:-\\d+)?", + "severity": 1, // ERROR | WARNING + "file": 2, // ./src/server.ts + "line": 3, // 8 + "column": 4 // 0 + }, + { + // × Module not found: ... + "regexp": "^\\s+×\\s+(.*)$", + "message": 1 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": ".*" + }, + // e.g.: "Rspack 1.6.7 compiled with 1 error in 71 ms" + "endsPattern": { + "regexp": "Rspack .* compiled .*" + } + } + }, + }, + { + "label": "Shared lib tsc build (watch)", + "type": "shell", + "command": "pnpm --silent --filter @vscode-adblock-syntax/shared exec tsc --project tsconfig.build.json --emitDeclarationOnly --watch --preserveWatchOutput", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "panel": "dedicated", + "reveal": "never", + "close": true + }, + "problemMatcher": "$tsc-watch" + }, + { + "label": "Shared lib dev build (watch)", + "dependsOn": [ + "Shared lib rspack build (watch)", + "Shared lib tsc build (watch)" + ] + }, { "label": "Server dev build (watch)", - "type": "npm", - "script": "watch:server", + "type": "shell", + "command": "pnpm exec cross-env NODE_ENV=dev pnpm --silent --filter @vscode-adblock-syntax/server build --watch", "isBackground": true, "group": { "kind": "build", @@ -15,12 +86,47 @@ "reveal": "never", "close": true }, - "problemMatcher": "$esbuild-watch", + "problemMatcher": { + "owner": "rspack", + "source": "rspack", + "fileLocation": [ + "relative", + "${workspaceFolder}/server" + ], + "pattern": [ + { + // ERROR in ./src/server.ts 8:0-25 + "regexp": "^(ERROR|WARNING) in\\s+(.+)\\s+(\\d+):(\\d+)(?:-\\d+)?", + "severity": 1, // ERROR | WARNING + "file": 2, // ./src/server.ts + "line": 3, // 8 + "column": 4 // 0 + }, + { + // × Module not found: ... + "regexp": "^\\s+×\\s+(.*)$", + "message": 1 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": ".*" + }, + // e.g.: "Rspack 1.6.7 compiled with 1 error in 71 ms" + "endsPattern": { + "regexp": "Rspack .* compiled .*" + } + } + }, + "dependsOn": [ + "Shared lib dev build (watch)" + ] }, { "label": "Client dev build (watch)", - "type": "npm", - "script": "watch:client", + "type": "shell", + "command": "pnpm exec cross-env NODE_ENV=dev pnpm --silent --filter @vscode-adblock-syntax/client build --watch", "isBackground": true, "group": { "kind": "build", @@ -31,12 +137,47 @@ "reveal": "never", "close": true }, - "problemMatcher": "$esbuild-watch", + "problemMatcher": { + "owner": "rspack", + "source": "rspack", + "fileLocation": [ + "relative", + "${workspaceFolder}/client" + ], + "pattern": [ + { + // ERROR in ./src/server.ts 8:0-25 + "regexp": "^(ERROR|WARNING) in\\s+(.+)\\s+(\\d+):(\\d+)(?:-\\d+)?", + "severity": 1, // ERROR | WARNING + "file": 2, // ./src/server.ts + "line": 3, // 8 + "column": 4 // 0 + }, + { + // × Module not found: ... + "regexp": "^\\s+×\\s+(.*)$", + "message": 1 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": ".*" + }, + // e.g.: "Rspack 1.6.7 compiled with 1 error in 71 ms" + "endsPattern": { + "regexp": "Rspack .* compiled .*" + } + } + }, + "dependsOn": [ + "Shared lib dev build (watch)" + ] }, { "label": "Grammar dev build (watch)", - "type": "npm", - "script": "watch:grammar", + "type": "shell", + "command": "pnpm exec cross-env NODE_ENV=dev pnpm --silent --filter @vscode-adblock-syntax/syntaxes build --watch", "isBackground": true, "group": { "kind": "build", @@ -76,10 +217,11 @@ "label": "Extension dev build (watch)", "dependsOrder": "sequence", "dependsOn": [ + "Shared lib dev build (watch)", "Grammar dev build (watch)", "Server dev build (watch)", "Client dev build (watch)" - ], + ] }, // Terminate watch tasks after debugging // https://github.com/microsoft/vscode/issues/90786#issuecomment-587415345 diff --git a/CHANGELOG.md b/CHANGELOG.md index f83dfbc..1a3dcda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/ [Semantic Versioning]: https://semver.org/spec/v2.0.0.html +## [2.1.1] (prerelease) - 2025-12-15 + +### Changed + +- Internal improvements and code refactoring. +- Project structure optimizations. + +> **Note:** Starting from v2.1.0, we follow an odd/even versioning scheme for pre-releases. +> Version 2.1.x will be the pre-release track, and 2.2.0 will be the next stable release. + +[2.1.1]: https://github.com/AdguardTeam/VscodeAdblockSyntax/compare/2.0.4...2.1.1 + ## [2.0.4] (prerelease) - 2025-11-28 ### Changed @@ -17,6 +29,8 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic - Loading AGLint on Windows. +[2.0.4]: https://github.com/AdguardTeam/VscodeAdblockSyntax/compare/2.0.3...2.0.4 + ## [2.0.3] (prerelease) - 2025-11-28 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 22f769a..9d89582 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,10 +11,20 @@ Table of Contents: - [Prerequisites](#prerequisites) - [Initial setup](#initial-setup) - [Project structure](#project-structure) + - [Main packages](#main-packages) + - [Supporting folders](#supporting-folders) - [Running the extension in development mode](#running-the-extension-in-development-mode) - [Creating a production build](#creating-a-production-build) - [Updating syntax highlighting](#updating-syntax-highlighting) - [Available commands](#available-commands) + - [Build commands](#build-commands) + - [Package commands](#package-commands) + - [Package-level build commands](#package-level-build-commands) + - [Utility commands](#utility-commands) + - [Linting \& testing commands](#linting--testing-commands) +- [Versioning policy](#versioning-policy) + - [VS Code extension versioning requirements](#vs-code-extension-versioning-requirements) + - [Pre-release versioning strategy](#pre-release-versioning-strategy) - [Useful links](#useful-links) ## Prerequisites @@ -43,16 +53,31 @@ After cloning the repository, follow these steps to initialize the project: ## Project structure -The most important folders in the project are: +This project uses a **monorepo structure** with **pnpm workspaces**. Each package is independent with its own +`package.json`, build system, and tests. + +### Main packages - [**client**][client-dir]: VSCode extension code which has access to all VS Code Namespace API. -- [**server**][server-dir]: Language analysis tool running in a separate process. + - Built with Rspack + - Contains the extension activation logic and VSCode integration +- [**server**][server-dir]: Language server running in a separate process. + - Built with Rspack with code splitting for large dependencies + - Handles AGLint integration, diagnostics, and language features +- [**shared**][shared-dir]: Shared utilities used by both client and server packages. + - Built with Rspack + - Contains common types and utilities - [**syntaxes**][syntaxes-dir]: TextMate grammars for syntax highlighting. -- [**test**][test-dir]: Various tests for the extension. - - [**grammar**][test-grammar-dir]: Unit tests for the TextMate grammar. - - [**static**][test-static-dir]: Static test files for testing the extension in development mode. - - [**aglint**][test-static-aglint-dir]: AGLint test project. - - [**rules**][test-static-rules-dir]: Rules for testing the syntax highlighting visually. + - Converts YAML grammar to PList format for VSCode + - Contains grammar tests and utilities + +### Supporting folders + +- [**test**][test-dir]: Static test files and test workspaces. + - [**static/aglint**][test-static-aglint-dir]: AGLint test project workspace. + - [**static/rules**][test-static-rules-dir]: Rules for testing the syntax highlighting visually. +- [**tools**][tools-dir]: Build and utility scripts for the project. +- [**bamboo-specs**][bamboo-specs-dir]: CI/CD pipeline configurations. > [!NOTE] > To learn more about the client-server architecture of VSCode extensions, refer to the [VSCode Language Server @@ -71,26 +96,25 @@ If you've made changes to the extension code and want to test them, follow these > [!IMPORTANT] > When you start the debugging, VSCode starts the watch build commands in separate terminals. To interpret the terminal -> output correctly, VSCode relies on [problem matchers][vscode-problem-matcher-docs]. Since ESBuild is not supported by -> VSCode by default, you need to install the [ESBuild Problem Matchers][esbuild-problem-matcher-extension] extension to -> make able VSCode to parse its output. -> Without this extension, VSCode cannot recognize when ESBuild completes its build or encounters errors. This results in -> an endless run, preventing the opening of the Extension Development Host. +> output correctly, VSCode relies on [problem matchers][vscode-problem-matcher-docs], +> otherwise the watch build will not stop when it encounters an error. ## Creating a production build To create a production build of the extension: -1. Run `pnpm build:prod` command. This generates a production build and a `.vsix` file in the `out` folder. -1. To ensure the build is correct, install the generated `.vsix` file in VSCode. Open the command palette +1. Run `pnpm build` command to build packages. +2. Run `pnpm package` command to package the extension into a `.vsix` file. +3. To ensure the build is correct, install the generated `.vsix` file in VSCode. Open the command palette (`Ctrl + Shift + P`), select "Extensions: Install from VSIX...", and choose the `vscode-adblock.vsix` file. ## Updating syntax highlighting -1. Update the TM grammar in the `syntaxes/adblock.yaml-tmLanguage` file. +1. Update the TM grammar in the `syntaxes/adblock.yaml-tmlanguage` file. 1. Create/modify example rules in the `test/static/rules` folder. Add link for GitHub issues to rules if related to some issue. -1. Create/modify unit tests in `test/grammar`. Ensure tests pass by running `pnpm test`. +1. Create/modify unit tests in `syntaxes/test/adblock`. Ensure tests pass by running + `pnpm --filter @vscode-adblock-syntax/syntaxes test`. > [!TIP] > Open the `test/static` folder in the "Extension Development Host" window and you can check the syntax highlighting @@ -103,39 +127,84 @@ To create a production build of the extension: During development, you can use the following commands (listed in `package.json`). -- `pnpm build:grammar` - Compiles the TextMate (TM) grammar into a PList format, since VSCode does not natively support - YAML grammars. -- `pnpm build:prod` - Generates a production build of the extension, including a `.vsix` file in the `out` directory for - VSCode installation. -- `pnpm build:txt` - Creates a `build.txt` file in the out directory containing the current version number, primarily - for Continuous Integration (CI) purposes. -- `pnpm build:vsix` - Produces a `.vsix` file in the out directory, which is used to install the extension in VSCode. -- `pnpm clean` - Removes all generated files in the output directories, cleaning up the build results. -- `pnpm esbuild:server` - Base ESBuild command for building the server with the common options. -- `pnpm esbuild:client` - Base ESBuild command for building the client with the common options. -- `pnpm extract-changelog` - Extract changes from the `CHANGELOG.md` for a specific version. Typically, this is used by - CI. -- `pnpm increment` - Increment the patch version number of the extension in the `package.json` file. Typically, this is - used by CI. +### Build commands + +- `pnpm build` - Build all packages recursively with minification enabled. + +### Package commands + +- `pnpm package` - Package the extension into a `.vsix` file in the `out` directory. +- `pnpm package:pre` - Package the extension with the `--pre-release` flag for prerelease builds. + +### Package-level build commands + +Each package can be built independently using pnpm workspace filters: + +- `pnpm --filter @vscode-adblock-syntax/shared build` - Build the shared package with Rspack. +- `pnpm --filter @vscode-adblock-syntax/client build` - Build the client package with Rspack. +- `pnpm --filter @vscode-adblock-syntax/server build` - Build the server package with Rspack (includes code splitting). +- `pnpm --filter @vscode-adblock-syntax/syntaxes build` - Build the syntaxes package (converts grammar to PList format). + +> [!NOTE] +> Rspack builds are configured via `rspack.config.ts` files in each package. Production mode is enabled via +> `NODE_ENV=production` environment variable, which is set automatically by the root `pnpm build` command. + +### Utility commands + +- `pnpm clean` - Removes all generated files using the clean utility script. +- `pnpm increment` - Increment the patch version number in the `package.json` file. Typically used by CI. + +### Linting & testing commands + +- `pnpm lint` - Run all linters recursively across all packages. +- `pnpm lint:code` - Lint the code with [ESLint][eslint]. - `pnpm lint:md` - Lint the markdown files with [markdownlint][markdownlint]. -- `pnpm lint:staged` - Run linters on staged files. Typically, this is used by Husky Git hooks. -- `pnpm lint:ts` - Lint the *ts* code with [ESLint][eslint]. -- `pnpm lint` - Run all linters. -- `pnpm test:compile` - Check if the code compiles with [TypeScript][typescript]. -- `pnpm test` - Run tests with [Jest][jest]. -- `pnpm watch:client` - Watch for changes in the client code and create a development build automatically. -- `pnpm watch:grammar` - Watch for changes in the TM grammar and rebuild it automatically. -- `pnpm watch:server` - Watch for changes in the server code and create a development build automatically. +- `pnpm test` - Run tests recursively across all packages with [Vitest][vitest]. +- `pnpm test:compile` - Type-check all packages without emitting files. + +You can also run linting and tests for individual packages: + +- `pnpm --filter @vscode-adblock-syntax/shared lint` / `test` +- `pnpm --filter @vscode-adblock-syntax/client lint` / `test` +- `pnpm --filter @vscode-adblock-syntax/server lint` / `test` +- `pnpm --filter @vscode-adblock-syntax/syntaxes lint` / `test` > [!NOTE] -> Watch commands (e.g., `pnpm watch:client`) are typically used by VSCode tasks (see -> [`.vscode/tasks.json`][vscode-tasks-file] file and -> [*Running the extension in development mode*](#running-the-extension-in-development-mode) section). -> In most cases, you don't need to run them manually. +> Watch builds are handled automatically by VSCode tasks when you start debugging (see +> [`.vscode/tasks.json`][vscode-tasks-file] file). Each package (shared, client, server, syntaxes) has its own watch +> task that rebuilds on file changes. > [!NOTE] > Linting and testing commands are called automatically by Husky Git hooks and CI. You can run them manually if needed. +## Versioning policy + +This project follows [Semantic Versioning (SemVer)][semver] with specific requirements for VS Code extensions. +See [VS Code pre-release extensions documentation][vscode-prerelease] for more details. + +### VS Code extension versioning requirements + +> [!IMPORTANT] +> VS Code Marketplace and Open VSX **only support `major.minor.patch` format**. Pre-release tags like `1.0.0-alpha` or +> `1.0.0-beta` are **NOT supported** and will be rejected by the stores. + +### Pre-release versioning strategy + +To support pre-release versions while maintaining compatibility, we use an **odd/even minor version scheme**: + +- **Release versions**: `major.EVEN.patch` → e.g., `2.0.0`, `2.0.1`, `2.2.0` +- **Pre-release versions**: `major.ODD.patch` → e.g., `2.1.0`, `2.1.1`, `2.3.0` + +**Version progression example:** + +```text +2.0.0 → 2.1.0 (start pre-release) → 2.1.1 (pre-release update) → 2.2.0 (promote to release) +``` + +> [!WARNING] +> VS Code auto-updates to the highest version. Always ensure pre-release versions are higher than release versions to +> prevent downgrading pre-release users. + ## Useful links Explore the following links for more information on development: @@ -146,24 +215,25 @@ Explore the following links for more information on development: - [VSCode Extension Samples](https://github.com/microsoft/vscode-extension-samples) - [Online test page for TextMate grammars][nova-light-show] +[bamboo-specs-dir]: ./bamboo-specs [client-dir]: ./client [contribute]: https://adguard.com/contribute.html -[esbuild-problem-matcher-extension]: https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers [eslint]: https://eslint.org/ [husky]: https://typicode.github.io/husky -[jest]: https://jestjs.io/ [markdownlint]: https://github.com/DavidAnson/markdownlint [nova-light-show]: https://novalightshow.netlify.app/ +[semver]: https://semver.org/ [server-dir]: ./server +[shared-dir]: ./shared [syntaxes-dir]: ./syntaxes [test-dir]: ./test -[test-grammar-dir]: ./test/grammar [test-static-aglint-dir]: ./test/static/aglint -[test-static-dir]: ./test/static [test-static-rules-dir]: ./test/static/rules -[typescript]: https://www.typescriptlang.org/ +[tools-dir]: ./tools +[vitest]: https://vitest.dev/ [vscode-extensions-file]: ./.vscode/extensions.json [vscode-ls-extension-guide]: https://code.visualstudio.com/api/language-extensions/language-server-extension-guide +[vscode-prerelease]: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#prerelease-extensions [vscode-problem-matcher-docs]: https://code.visualstudio.com/docs/editor/tasks#_processing-task-output-with-problem-matchers [vscode-tasks-file]: ./.vscode/tasks.json [vscode]: https://code.visualstudio.com/ diff --git a/README.md b/README.md index f501c78..b0ab004 100644 --- a/README.md +++ b/README.md @@ -1,220 +1,232 @@ -  -

- AGLint -

-

Adblock Language support for VSCode.

-

- Supported syntaxes: -

-

- AdGuard | - uBlock Origin | - AdBlock | - Adblock Plus -

- -

- Visual Studio Marketplace Version (including pre-releases) - Open VSX Version - License - Open GitHub Issues - Open GitHub Pull Requests -

- +
+ +AGLint + +# Adblock Syntax for VSCode -Table of Contents: +**Complete adblock filter list support for VSCode** -- [Introduction](#introduction) - - [Features](#features) - - [Syntax highlighting](#syntax-highlighting) - - [AGLint integration (linter)](#aglint-integration-linter) - - [Configuration](#configuration) - - [GitHub Linguist support](#github-linguist-support) - - [Ideas \& Questions](#ideas--questions) - - [Reporting Issues](#reporting-issues) - - [Contributing](#contributing) - - [License](#license) - - [References](#references) +> **Note:** This is a development tool for creating and editing adblock filter lists, not an ad blocker for VSCode. -# Introduction +[![VSCode Marketplace][badge-vscode]][marketplace] +[![Open VSX][badge-openvsx]][openvsx] +[![License][badge-license]][license] -This extension adds support for AdGuard, uBlock Origin and Adblock Plus syntaxes to Visual Studio Code, so you can write -adblock rules in a convenient way. It also provides a linter to check your rules for errors. +AdGuard AdGuard・ +uBlock Origin uBlock Origin・ +AdBlock AdBlock・ +Adblock Plus Adblock Plus -**We recommend using this extension if you are working with adblock rules.** +[Install][marketplace] • [Documentation](#features) • [Report Issue][issues] • [Contributing][contributing] -You can easily install the update from the Visual Studio Marketplace or the Open VSX Registry: +
+ +--- + + -- [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=adguard.adblock) -- [Open VSX Registry](https://open-vsx.org/extension/adguard/adblock) +## ✨ Features -Here is a screenshot of the extension in action: +- 🎨 **Syntax highlighting** — Full support for AdGuard, uBlock Origin, and Adblock Plus filter syntax +- 🔍 **Real-time linting** — Powered by [AGLint][aglint] with instant validation and error detection +- 🛠️ **Auto-fixing** — Automatically fix issues with AGLint's suggestions and quick fixes +- 🌐 **Multi-platform validation** — Platform-specific compatibility warnings and syntax checks +- 🐙 **GitHub integration** — Syntax highlighting on GitHub via [Linguist][linguist] +- ⚙️ **Flexible configuration** — VSCode settings and AGLint config file (`.aglintrc`) support +- 🚀 **Auto-discovery** — Automatically finds AGLint in your workspace (local or global) +--- + +## 📷 Screenshot + + Adblock Syntax in action + -GitHub Linguist support is also available, so you can highlight your adblock rules in GitHub repositories. See -[GitHub Linguist support](#github-linguist-support) for more details. Quick example: +--- -```adblock -! This is an example rule -example.org##.banner -||example.net/script.js$script,third-party,domain=example.com -``` +## 📦 Installation -## Features +### Quick Install -In this section we will describe the main features of this extension. +1. Open VSCode +2. Press `Ctrl+P` / `Cmd+P` +3. Type: `ext install adguard.adblock` +4. Press `Enter` -### Syntax highlighting +### Manual Install -Syntax highlighting is available for AdGuard, uBlock Origin and Adblock Plus syntaxes. Nowadays it is unimaginable to -work with code without highlighting, which helps you to distinguish different parts of the code and makes it easier -to read. +**VSCode Marketplace:** -### AGLint integration (linter) +1. Open [VSCode Marketplace][marketplace] +2. Click **Install** +3. VSCode will open automatically -This extension integrates [AGLint][aglint] to check your rules for syntax errors, invalid domains, -incompatible CSS selectors, unknown scriptlets, and other issues. For more details, see the [AGLint repository][aglint]. +**Open VSX (for VSCodium, etc.):** -The extension automatically searches for AGLint installations in this order: +1. Open [Open VSX Registry][openvsx] +2. Click **Download** +3. Install the `.vsix` file manually -1. Local workspace installation -2. Global installation -3. Prompts to install if not found +### Verify Installation -Using a local installation ensures consistent results with your project's AGLint version. +1. Open any `.txt` file with adblock rules +2. Add a filter rule: `example.org##.banner` +3. You should see syntax highlighting -> [!WARNING] -> Please note that the linter is under active development, so it may not work properly for some rules. If you -> find any issues, please report them [here][aglintissues]. We look forward to your feedback, your help is very -> important to us! +**Note:** AGLint linting requires [AGLint][aglint] to be installed in your workspace or globally. +See [AGLint Configuration](#-aglint-configuration) for setup details. -### Configuration +--- -This extension provides the following configuration options: +## ⚙️ Configuration - -| Option | Description | Default value | Possible values | -| ------ | ----------- | ------------- | --------------- | -| `adblock.enableAglint` | Enable or disable AGLint integration. If disabled, only syntax highlighting and other language features will be available. | `true` | `true`, `false` | -| `adblock.enableInMemoryAglintCache` | ⚠️ **Experimental**: Enable or disable in-memory caching of linting results for better performance. | `false` | `true`, `false` | - -**Note:** AGLint debug logging is automatically enabled when VSCode's log level is set to "Debug" or "Trace" via "Developer: Set Log Level". - -> **💡 Tip**: To control AGLint logging verbosity, use VSCode's built-in log level control: -> Open Command Palette (**Cmd+Shift+P**) → **Developer: Set Log Level...** → Select **AGLint** - -### GitHub Linguist support - -GitHub supports adblock syntax officially via the [Linguist][linguist] library. Our extension provides a -[TMLanguage file][tmlanguagefile], which is used by Linguist to highlight adblock rules (VSCode highlight also based on -this file). This means that if you have a repository with adblock rules, GitHub can highlight your `.txt` files, if the -following conditions are met: - -- If a `*.txt` file **begins** with an adblock agent (such as `[Adblock Plus 2.0]`, `[AdGuard]`, `[uBlock Origin]`, - `[Adblock Plus 2.0; AdGuard]`, etc.), then it will be highlighted as an adblock file automatically. You can find the - detection heuristics [here][linguistheur]. -- In any other cases, you can override the language classification by adding the following lines to `.gitattributes` - file: - ```gitattributes - # Override classification for *.txt files, so they are highlighted as adblock files. - # - This example will match all *.txt files in the repository, but you can - # customize path(s) to match only specific files, such as /filters/*.txt - # or /filters/*.adblock. See https://git-scm.com/docs/gitattributes for more details. - # - By default, Adblock language doesn't show up in the repository's language statistics, - # but adding linguist-detectable will resolve this, so it is recommended to add it. - *.txt linguist-language=AdBlock linguist-detectable - ``` - You can find more information about overriding language classification [here][linguistoverride]. - -In addition, adblock code blocks can be inserted in markdown files and comments according to the following pattern: - -
-```adblock
-! Example rule
-example.org##.banner
+| Setting                               | Description                             | Default |
+|---------------------------------------|-----------------------------------------|---------|
+| `adblock.enableAglint`                | Enable AGLint linting                   | `true`  |
+| `adblock.enableInMemoryAglintCache`   | Cache linting results for performance   | `false` |
+
+**💡 Tip**: Control AGLint logging via VSCode's built-in log level:
+Command Palette → **Developer: Set Log Level** → **AGLint**
+
+---
+
+## 📝 AGLint Configuration
+
+AGLint requires a configuration file to enable linting.
+The extension will automatically detect AGLint in your workspace.
+
+### Quick Setup
+
+Run in your project root:
+
+```bash
+npx aglint --init
 ```
-
-will be rendered as: +This creates an interactive wizard to generate a configuration file. + +### Configuration File + +Supported file names (YAML recommended): + +- `.aglintrc.yaml` / `.aglintrc.yml` (recommended) +- `.aglintrc.json` / `.aglintrc` +- `aglint.config.json` / `aglint.config.yaml` -```adblock -! Example rule -example.org##.banner +### Example Configuration + +```yaml +# .aglintrc.yaml +root: true +extends: + - aglint:recommended ``` -## Ideas & Questions +### Available Presets + +- `aglint:recommended` — Recommended rules for most projects +- `aglint:all` — All available rules (strict) + +For detailed configuration options, rule customization, and cascading configs, +see the [AGLint documentation][aglint-docs]. + +--- + +## 🐙 GitHub Support + +GitHub uses this extension's [grammar file][grammar-file] via [Linguist][linguist] for syntax highlighting. -If you have any questions or ideas for new features, please open an issue or a discussion. We will be happy to discuss -it with you. +Your filter lists will be automatically highlighted on GitHub if they start with an agent comment +like `[Adblock Plus 2.0]` or `[AdGuard]`. -## Reporting Issues +[grammar-file]: https://github.com/AdguardTeam/VscodeAdblockSyntax/blob/master/syntaxes/adblock.yaml-tmlanguage -If you found a bug or have a feature request, please report it [here][issues]. Please make sure to include as much -information as possible, including screenshots or example rules. +--- -Please note that the highlighter issues on GitHub will not be fixed immediately when we update the TMLanguage in this -repository. GitHub's highlighter is only updated after Linguist releases. This process happens roughly every quarter. -Before release, Linguist maintainers will update all integrated TMLanguage to the latest version. You can find more -information about Linguist's release process [here][linguistrelease]. +## 🤝 Contributing -## Contributing +Contributions are welcome! Please read our [Contributing Guide][contributing] for details on how to get started. -If you want to contribute to this project, please read the [CONTRIBUTING][contributing] file. +## 📝 License -## License +This project is licensed under the MIT License - see the [LICENSE][license] file for details. -This extension is licensed under the MIT License. See the [LICENSE][license] file for details. +--- -## References +## 🔗 Resources -Here are some useful links to help you write adblock rules. This list is not exhaustive, so if you know any other useful -resources, please let us know. +### 📚 Filter Syntax Documentation -- Syntax documentation: - - AdGuard logo [AdGuard: *How to create your own ad filters*][adg-filters] - - uBlock Origin logo [uBlock Origin: *Static filter syntax*][ubo-filters] - - Adblock Plus logo [Adblock Plus: *How to write filters*][abp-filters] -- Extended CSS documentation: - - [MDN: *CSS selectors*][mdn-css-selectors] - - AdGuard logo [AdGuard: *Extended CSS capabilities*][adg-ext-css] - - uBlock Origin logo [uBlock Origin: *Procedural cosmetic filters*][ubo-procedural] - - Adblock Plus logo [Adblock Plus: *Extended CSS selectors*][abp-ext-css] -- Scriptlets: - - AdGuard logo [AdGuard scriptlets][adg-scriptlets] - - uBlock Origin logo [uBlock Origin scriptlets][ubo-scriptlets] - - Adblock Plus logo [Adblock Plus snippets][abp-snippets] -- Third party libraries: - - [CSSTree docs][css-tree-docs] -- AdGuard logo [AdGuard's compatibility table][adg-compatibility-table] +- AdGuard [AdGuard Filter Syntax][adg-syntax] +- uBlock Origin [uBlock Origin Static Filters][ubo-syntax] +- Adblock Plus [Adblock Plus Filter Guide][abp-syntax] -[abp-ext-css]: https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide-emulation -[abp-filters]: https://help.eyeo.com/adblockplus/how-to-write-filters -[abp-snippets]: https://help.eyeo.com/adblockplus/snippet-filters-tutorial#snippets-ref -[adg-compatibility-table]: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/compatibility-table.md -[adg-ext-css]: https://github.com/AdguardTeam/ExtendedCss/blob/master/README.md -[adg-filters]: https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters -[adg-scriptlets]: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#scriptlets +### 🎯 Scriptlets & Snippets + + +- AdGuard [AdGuard Scriptlets][adg-scriptlets] +- uBlock Origin [uBlock Origin Scriptlets][ubo-scriptlets] +- Adblock Plus [Adblock Plus Snippets][abp-snippets] + + +### 🎨 Extended CSS + + +- [MDN CSS Selectors][mdn-css] +- AdGuard [AdGuard Extended CSS][adg-extcss] +- uBlock Origin [uBlock Origin Procedural Filters][ubo-procedural] +- Adblock Plus [Adblock Plus Extended CSS][abp-extcss] + + +### 🛠️ Tools + +- [AGLint][aglint] - Adblock filter linter +- [Compatibility Tables][compat-tables] - Cross-platform feature support + +--- + +
+ +Made with ❤️ by [AdGuard][adguard] + +[Report Issue][issues] • [Request Feature][feature-request] • [Ask Question][discussions] + +
+ + +[adguard]: https://adguard.com [aglint]: https://github.com/AdguardTeam/AGLint -[aglintissues]: https://github.com/AdguardTeam/AGLint/issues -[contributing]: https://github.com/AdguardTeam/VscodeAdblockSyntax/blob/master/CONTRIBUTING.md -[css-tree-docs]: https://github.com/csstree/csstree/tree/master/docs +[aglint-docs]: https://github.com/AdguardTeam/AGLint/tree/master/docs +[badge-license]: https://img.shields.io/github/license/AdguardTeam/VscodeAdblockSyntax +[badge-openvsx]: https://img.shields.io/open-vsx/v/adguard/adblock?label=Open%20VSX +[badge-vscode]: https://img.shields.io/visual-studio-marketplace/v/adguard.adblock?label=VSCode%20Marketplace +[contributing]: CONTRIBUTING.md +[discussions]: https://github.com/AdguardTeam/VscodeAdblockSyntax/discussions +[feature-request]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/new [issues]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues -[license]: https://github.com/AdguardTeam/VscodeAdblockSyntax/blob/master/LICENSE.md +[license]: LICENSE.md [linguist]: https://github.com/github/linguist -[linguistheur]: https://github.com/github/linguist/blob/c1c34e5260797b4d598f5ec76f19723bfc5a1894/lib/linguist/heuristics.yml#L708-L728 -[linguistoverride]: https://github.com/github/linguist/blob/master/docs/overrides.md -[linguistrelease]: https://github.com/github/linguist/blob/master/docs/releasing.md -[mdn-css-selectors]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors -[tmlanguagefile]: https://github.com/AdguardTeam/VscodeAdblockSyntax/blob/master/syntaxes/adblock.tmLanguage.json -[ubo-filters]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax +[marketplace]: https://marketplace.visualstudio.com/items?itemName=adguard.adblock +[openvsx]: https://open-vsx.org/extension/adguard/adblock + + +[abp-extcss]: https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#elemhide-emulation +[abp-snippets]: https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial +[abp-syntax]: https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters +[adg-extcss]: https://github.com/AdguardTeam/ExtendedCss +[adg-scriptlets]: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md +[adg-syntax]: https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters +[compat-tables]: https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree/src/compatibility-tables +[mdn-css]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors [ubo-procedural]: https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters -[ubo-scriptlets]: https://github.com/gorhill/uBlock/wiki/Resources-Library#available-general-purpose-scriptlets +[ubo-scriptlets]: https://github.com/gorhill/uBlock/wiki/Resources-Library +[ubo-syntax]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax diff --git a/bamboo-specs/build-prerelease.yaml b/bamboo-specs/build-prerelease.yaml index e06eeba..ad7621a 100644 --- a/bamboo-specs/build-prerelease.yaml +++ b/bamboo-specs/build-prerelease.yaml @@ -43,6 +43,9 @@ Build: # Install dependencies pnpm install + # Build shared library first (required by client and server) + pnpm --filter @vscode-adblock-syntax/shared build + # Check TypeScript types pnpm test:compile @@ -50,16 +53,22 @@ Build: pnpm lint:md # Run ESLint - pnpm lint:ts + pnpm lint:code - # Run Jest tests + # Run Vitest tests pnpm test - # Create prerelease build - pnpm build:prerelease + # Create production build + pnpm build + + # Package build into .vsix file + pnpm package:pre + + # Show tree of files in .vsix file + pnpm exec vsce ls --tree # Create build.txt file with version - pnpm build:txt + pnpm exec tsx tools/build-txt.ts - inject-variables: file: out/build.txt scope: RESULT @@ -99,8 +108,13 @@ Build: pattern: adblock.plist shared: true required: true + - name: build.txt + location: out + pattern: build.txt + shared: true + required: true requirements: - - adg-docker: true + - adg-docker: 'true' triggers: [] diff --git a/bamboo-specs/build.yaml b/bamboo-specs/build.yaml index c7d6adf..2cb269e 100644 --- a/bamboo-specs/build.yaml +++ b/bamboo-specs/build.yaml @@ -43,6 +43,9 @@ Build: # Install dependencies pnpm install + # Build shared library first (required by client and server) + pnpm --filter @vscode-adblock-syntax/shared build + # Check TypeScript types pnpm test:compile @@ -50,16 +53,22 @@ Build: pnpm lint:md # Run ESLint - pnpm lint:ts + pnpm lint:code - # Run Jest tests + # Run Vitest tests pnpm test # Create production build - pnpm build:prod + pnpm build + + # Package build into .vsix file + pnpm package + + # Show tree of files in .vsix file + pnpm exec vsce ls --tree # Create build.txt file with version - pnpm build:txt + pnpm exec tsx tools/build-txt.ts - inject-variables: file: out/build.txt scope: RESULT @@ -99,8 +108,13 @@ Build: pattern: adblock.plist shared: true required: true + - name: build.txt + location: out + pattern: build.txt + shared: true + required: true requirements: - - adg-docker: true + - adg-docker: 'true' triggers: [] diff --git a/bamboo-specs/deploy-prerelease.yaml b/bamboo-specs/deploy-prerelease.yaml index 5cc55c8..5c67a15 100644 --- a/bamboo-specs/deploy-prerelease.yaml +++ b/bamboo-specs/deploy-prerelease.yaml @@ -117,6 +117,7 @@ GitHub: - name: vscode-adblock.vsix - name: EXTRACTED_CHANGES.md - name: adblock.plist + - name: build.txt - script: interpreter: SHELL scripts: diff --git a/bamboo-specs/deploy.yaml b/bamboo-specs/deploy.yaml index 4b2f8b0..13c78f5 100644 --- a/bamboo-specs/deploy.yaml +++ b/bamboo-specs/deploy.yaml @@ -117,6 +117,7 @@ GitHub: - name: vscode-adblock.vsix - name: EXTRACTED_CHANGES.md - name: adblock.plist + - name: build.txt - script: interpreter: SHELL scripts: diff --git a/bamboo-specs/increment.yaml b/bamboo-specs/increment.yaml index e56b421..0068815 100644 --- a/bamboo-specs/increment.yaml +++ b/bamboo-specs/increment.yaml @@ -49,7 +49,7 @@ Increment: scripts: - "./bamboo-specs/scripts/cleanup.sh" requirements: - - adg-docker: true + - adg-docker: 'true' branches: create: manually diff --git a/bamboo-specs/test.yaml b/bamboo-specs/test.yaml index 6e064e1..6087333 100644 --- a/bamboo-specs/test.yaml +++ b/bamboo-specs/test.yaml @@ -7,58 +7,236 @@ plan: variables: dockerNode: adguard/node-ssh:22.14--0 +# Package dependencies: +# - Shared: no dependencies (base package) +# - Syntaxes: no dependencies (independent) +# - Client: depends on Shared +# - Server: depends on Shared +# +# Stage 1: +# - Test Shared (base package); +# - Test Syntaxes (independent). +# +# Stage 2: +# - Test Client (depends on Shared); +# - Test Server (depends on Shared). +# +# Stage 3: +# - Build & Package (final assembly and artifact creation). +# +# Note: Cleanup is performed after each stage to prevent disk space issues +# and ensure clean state for subsequent builds. + stages: - - Build: + - Stage 1: &stage manual: false final: false jobs: - - Build + - Test Shared + - Test Syntaxes + - Stage 2: + <<: *stage + jobs: + - Test Client + - Test Server + - Stage 3: + <<: *stage + jobs: + - Build and Package -Build: - key: BUILD - docker: +Test Shared: + key: TESTSHARED + docker: &docker image: '${bamboo.dockerNode}' volumes: ${system.PNPM_DIR}: "${bamboo.cachePnpm}" tasks: - checkout: force-clean-build: true - - script: + - script: &setup-script interpreter: SHELL scripts: - |- - set -e - set -x + set -ex # Fix mixed logs exec 2>&1 - ls -laht + ls -alt # Set cache directory pnpm config set store-dir ${bamboo.cachePnpm} # Install dependencies pnpm install + - script: + interpreter: SHELL + scripts: + - |- + set -ex - # Check TypeScript types - pnpm test:compile + # Build shared library + pnpm --filter @vscode-adblock-syntax/shared build + + # Run TypeScript type checking + pnpm --filter @vscode-adblock-syntax/shared exec tsc --noEmit + + # Run ESLint + pnpm --filter @vscode-adblock-syntax/shared lint:code # Run markdownlint - pnpm lint:md + pnpm --filter @vscode-adblock-syntax/shared lint:md + + # Run tests + pnpm --filter @vscode-adblock-syntax/shared test --run --no-color + final-tasks: + - script: &cleanup-script + interpreter: SHELL + scripts: + - "./bamboo-specs/scripts/cleanup.sh" + requirements: &requirements + - adg-docker: 'true' + +Test Syntaxes: + key: TESTSYNTAXES + docker: *docker + tasks: + - checkout: + force-clean-build: true + - script: *setup-script + - script: + interpreter: SHELL + scripts: + - |- + set -ex + + # Build syntaxes + pnpm --filter @vscode-adblock-syntax/syntaxes build + + # Run TypeScript type checking + pnpm --filter @vscode-adblock-syntax/syntaxes exec tsc --noEmit # Run ESLint - pnpm lint:ts + pnpm --filter @vscode-adblock-syntax/syntaxes lint:code - # Run Jest tests - pnpm test + # Run markdownlint + pnpm --filter @vscode-adblock-syntax/syntaxes lint:md + + # Run tests + pnpm --filter @vscode-adblock-syntax/syntaxes test --run --no-color final-tasks: + - script: *cleanup-script + requirements: *requirements + +Test Client: + key: TESTCLIENT + docker: *docker + tasks: + - checkout: + force-clean-build: true + - script: *setup-script - script: interpreter: SHELL scripts: - - "./bamboo-specs/scripts/cleanup.sh" - requirements: - - adg-docker: true + - |- + set -ex + + # Build shared first (dependency) + pnpm --filter @vscode-adblock-syntax/shared build + + # Build client + pnpm --filter @vscode-adblock-syntax/client build + + # Run TypeScript type checking + pnpm --filter @vscode-adblock-syntax/client exec tsc --noEmit + + # Run ESLint + pnpm --filter @vscode-adblock-syntax/client lint:code + + # Run markdownlint + pnpm --filter @vscode-adblock-syntax/client lint:md + + # Run tests + pnpm --filter @vscode-adblock-syntax/client test --run --no-color + final-tasks: + - script: *cleanup-script + requirements: *requirements + +Test Server: + key: TESTSERVER + docker: *docker + tasks: + - checkout: + force-clean-build: true + - script: *setup-script + - script: + interpreter: SHELL + scripts: + - |- + set -ex + + # Build shared first (dependency) + pnpm --filter @vscode-adblock-syntax/shared build + + # Build server + pnpm --filter @vscode-adblock-syntax/server build + + # Run TypeScript type checking + pnpm --filter @vscode-adblock-syntax/server exec tsc --noEmit + + # Run ESLint + pnpm --filter @vscode-adblock-syntax/server lint:code + + # Run markdownlint + pnpm --filter @vscode-adblock-syntax/server lint:md + + # Run tests + pnpm --filter @vscode-adblock-syntax/server test --run --no-color + final-tasks: + - script: *cleanup-script + requirements: *requirements + +Build and Package: + key: BUILDPACKAGE + docker: *docker + tasks: + - checkout: + force-clean-build: true + - script: *setup-script + - script: + interpreter: SHELL + scripts: + - |- + set -ex + + # Build all packages + pnpm build + + # Final type check for all packages + pnpm test:compile + + # Package into .vsix file + pnpm package + + # Show tree of files in .vsix file + pnpm exec vsce ls --tree + final-tasks: + - script: + interpreter: SHELL + scripts: + - "./bamboo-specs/scripts/cleanup.sh out/vscode-adblock.vsix,syntaxes/out/adblock.plist" + artifacts: + - name: vscode-adblock.vsix + location: out + pattern: vscode-adblock.vsix + shared: true + required: true + - name: adblock.plist + location: syntaxes/out + pattern: adblock.plist + shared: true + required: true + requirements: *requirements branches: create: for-pull-request diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs new file mode 100644 index 0000000..fb10704 --- /dev/null +++ b/client/.eslintrc.cjs @@ -0,0 +1,9 @@ +const path = require('node:path'); + +module.exports = { + extends: '../.eslintrc.cjs', + parserOptions: { + tsconfigRootDir: path.join(__dirname), + project: 'tsconfig.json', + }, +}; diff --git a/client/.lintstagedrc.js b/client/.lintstagedrc.js new file mode 100644 index 0000000..a589197 --- /dev/null +++ b/client/.lintstagedrc.js @@ -0,0 +1,33 @@ +/** @type {import('lint-staged').Configuration} */ +const path = require('node:path'); + +/** + * Make file path relative to the current working directory + * + * @param {string} file File path + * + * @returns {string} Relative path + */ +const makeRelative = (file) => path.relative(process.cwd(), file); + +module.exports = { + '**/*.md': 'markdownlint', + '**/*.js': 'eslint --cache', + '**/*.ts': [ + // Type-check only the staged TS files while still honoring tsconfig + // Exclude config files that import build tools (they're checked by tsconfig.json) + (files) => { + const filesToCheck = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return filesToCheck.length > 0 ? `tsc-files --noEmit ${filesToCheck.join(' ')}` : 'echo "No files to type-check"'; + }, + + // Run tests that are related to those changed files + (files) => { + const testableFiles = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return testableFiles.length > 0 ? `vitest related --run ${testableFiles.map(makeRelative).join(' ')}` : 'echo "No test files"'; + }, + + // Lint the staged TS files + 'eslint --cache', + ], +}; diff --git a/client/README.md b/client/README.md new file mode 100644 index 0000000..06e33cf --- /dev/null +++ b/client/README.md @@ -0,0 +1,6 @@ +# @vscode-adblock-syntax/client + +Language client for Adblock/AdGuard/uBlock filters syntax. + +This package implements the VSCode language client that communicates with the language +server to provide linting and language features for adblock filter lists. diff --git a/client/package.json b/client/package.json index 84596a0..a6436ce 100644 --- a/client/package.json +++ b/client/package.json @@ -1,15 +1,30 @@ { - "name": "aglint-client", + "name": "@vscode-adblock-syntax/client", + "description": "Language client for Adblock/AdGuard/uBlock filters syntax.", "version": "2.0.0", "license": "MIT", "author": "AdGuard Software Ltd.", - "description": "Integrates AGLint into VSCode", "private": true, + "scripts": { + "prebuild": "rimraf out", + "build": "rspack", + "test": "vitest", + "lint:code": "eslint . --cache --ext .ts --ext .js --ext .cjs", + "lint:md": "markdownlint . --ignore-path ../.markdownlintignore", + "lint": "pnpm run lint:code && pnpm run lint:md" + }, "dependencies": { - "valibot": "^1.1.0", - "vscode-languageclient": "10.0.0-next.15" + "@vscode-adblock-syntax/shared": "workspace:^", + "valibot": "catalog:", + "vscode-languageclient": "catalog:" }, "devDependencies": { - "@types/vscode": "^1.74.0" + "@rspack/cli": "catalog:", + "@rspack/core": "catalog:", + "@types/vscode": "catalog:", + "rimraf": "catalog:", + "tsc-files": "catalog:", + "tsx": "catalog:", + "vitest": "catalog:" } } diff --git a/client/rspack.config.ts b/client/rspack.config.ts new file mode 100644 index 0000000..fc97116 --- /dev/null +++ b/client/rspack.config.ts @@ -0,0 +1,105 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { resolve } from 'node:path'; + +import { defineConfig } from '@rspack/cli'; + +const isProduction = process.env.NODE_ENV === 'production'; + +export default defineConfig({ + target: 'node', + mode: isProduction ? 'production' : 'development', + + stats: 'normal', + + entry: { + extension: './src/extension.ts', + }, + + output: { + path: resolve(__dirname, 'out'), + filename: '[name].js', // -> extension.js + chunkFilename: '[name].[contenthash:8].js', // -> vendors.abc12345.js, agtree-compatibility.def67890.js + libraryTarget: 'commonjs2', + clean: true, + }, + + resolve: { + extensions: ['.ts', '.js'], + }, + + module: { + rules: [ + { + test: /\.ts$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + }, + target: 'es2020', + }, + }, + }, + exclude: /node_modules/, + }, + ], + }, + + externals: { + vscode: 'commonjs vscode', + }, + + optimization: { + minimize: isProduction, + splitChunks: { + chunks: 'all', + minSize: 20000, + cacheGroups: { + // Automatically split all other vendors by package name + defaultVendors: { + test: /[\\/]node_modules[\\/]/, + name(module: any) { + const { context } = module; + + // Handle pnpm's .pnpm directory structure + // pnpm creates these paths: + // - node_modules/.pnpm/@/node_modules/ + // - node_modules/.pnpm/@scope+package@/node_modules/@scope/package + // - node_modules/.pnpm/node_modules/ (edge case) + const pnpmMatch = context.match( + /[\\/]\.pnpm[\\/](?:@?[^@/\\]+@[^/\\]+[\\/])?node_modules[\\/]((?:@[^/\\]+[\\/])?[^/\\]+)/, + ); + if (pnpmMatch) { + const packageName = pnpmMatch[1] + .replace('@', '') + .replace(/\//g, '-'); + return `vendors/${packageName}`; + } + + // Standard node_modules structure (npm/yarn) + // - node_modules/ + // - node_modules/@scope/package + const packageNameMatch = context.match( + /[\\/]node_modules[\\/]((?:@[^/\\]+[\\/])?[^/\\]+)/, + ); + if (packageNameMatch) { + const packageName = packageNameMatch[1] + .replace('@', '') + .replace(/\//g, '-'); + return `vendors/${packageName}`; + } + + return 'vendors/vendor'; + }, + chunks: 'all', + priority: 10, + reuseExistingChunk: true, + }, + }, + }, + }, + + devtool: isProduction ? false : 'source-map', +}); diff --git a/client/src/constants.ts b/client/src/constants.ts new file mode 100644 index 0000000..b1c69cd --- /dev/null +++ b/client/src/constants.ts @@ -0,0 +1,74 @@ +/** + * @file Constants used across the extension. + */ + +import { FileScheme } from '@vscode-adblock-syntax/shared'; + +/** + * Supported file extensions. + */ +export const SUPPORTED_FILE_EXTENSIONS: ReadonlySet = new Set([ + 'txt', + 'adblock', + 'ublock', + 'adguard', +]); + +/** + * Possible names of the config file. + */ +export const CONFIG_FILE_NAMES: ReadonlySet = new Set([ + // aglint.config stuff + 'aglint.config.json', + 'aglint.config.yaml', + 'aglint.config.yml', + + // .aglintrc stuff + '.aglintrc', + '.aglintrc.json', + '.aglintrc.yaml', + '.aglintrc.yml', +]); + +/** + * Name of the ignore file. + */ +export const IGNORE_FILE_NAME = '.aglintignore'; + +/** + * Default document scheme for filtering documents. + */ +export const DOCUMENT_SCHEME = FileScheme.File; + +/** + * Language ID for adblock filter lists. + */ +export const LANGUAGE_ID = 'adblock'; + +/** + * Client ID for the language client. + */ +export const CLIENT_ID = 'aglint'; + +/** + * Display name for the language client. + */ +export const CLIENT_NAME = 'AGLint'; + +/** + * Priority for the VS Code status bar item. + * + * Higher values mean the item is placed more to the left *within its alignment group*. + * For {@link StatusBarAlignment.Right}, a higher number positions it closer + * to the center of the status bar; a lower number moves it toward the right edge. + * + * This project uses `100` as a balanced value; it is prominent but not far-left, + * following the example from `vscode-extension-samples`: + * https://github.com/microsoft/vscode-extension-samples/blob/986bcc700dee6cc4d1e6d4961a316eead110fb21/statusbar-sample/src/extension.ts#L21. + * + * Other extensions typically use values between 0 and 200: + * https://github.com/search?q=createStatusBarItem(vscode.StatusBarAlignment.Right&type=code. + * + * This value is based on convention and visual preference, and can be adjusted in the future if needed. + */ +export const STATUS_BAR_PRIORITY = 100; diff --git a/client/src/extension.ts b/client/src/extension.ts index 322f840..e711e83 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,10 +1,9 @@ import { join } from 'node:path'; -import * as v from 'valibot'; +import { FileScheme } from '@vscode-adblock-syntax/shared'; import { commands, type ExtensionContext, - LogLevel, RelativePattern, StatusBarAlignment, type StatusBarItem, @@ -21,70 +20,21 @@ import { TransportKind, } from 'vscode-languageclient/node'; +import { + CLIENT_ID, + CLIENT_NAME, + CONFIG_FILE_NAMES, + DOCUMENT_SCHEME, + IGNORE_FILE_NAME, + LANGUAGE_ID, + STATUS_BAR_PRIORITY, + SUPPORTED_FILE_EXTENSIONS, +} from './constants'; +import { shouldEnableAglintDebug } from './utils/log-level'; +import { type AglintStatus, parseStatusParams } from './utils/status-parser'; import { fileInFolder, getOuterMostWorkspaceFolder } from './workspace-folders'; -/** - * Schemes for file documents. - */ -const enum FileScheme { - File = 'file', - Untitled = 'untitled', -} - const SERVER_PATH = join('server', 'out', 'server.js'); -const DOCUMENT_SCHEME = FileScheme.File; -const LANGUAGE_ID = 'adblock'; -const CLIENT_ID = 'aglint'; -const CLIENT_NAME = 'AGLint'; - -/** - * Supported file extensions. - */ -const SUPPORTED_FILE_EXTENSIONS: ReadonlySet = new Set([ - 'txt', - 'adblock', - 'ublock', - 'adguard', -]); - -/** - * Possible names of the config file. - */ -const CONFIG_FILE_NAMES: ReadonlySet = new Set([ - // aglint.config stuff - 'aglint.config.json', - 'aglint.config.yaml', - 'aglint.config.yml', - - // .aglintrc stuff - '.aglintrc', - '.aglintrc.json', - '.aglintrc.yaml', - '.aglintrc.yml', -]); - -/** - * Name of the ignore file. - */ -const IGNORE_FILE_NAME = '.aglintignore'; - -/** - * Priority for the VS Code status bar item. - * - * Higher values mean the item is placed more to the left *within its alignment group*. - * For {@link StatusBarAlignment.Right}, a higher number positions it closer - * to the center of the status bar; a lower number moves it toward the right edge. - * - * This project uses `100` as a balanced value; it is prominent but not far-left, - * following the example from `vscode-extension-samples`: - * https://github.com/microsoft/vscode-extension-samples/blob/986bcc700dee6cc4d1e6d4961a316eead110fb21/statusbar-sample/src/extension.ts#L21. - * - * Other extensions typically use values between 0 and 200: - * https://github.com/search?q=createStatusBarItem(vscode.StatusBarAlignment.Right&type=code. - * - * This value is based on convention and visual preference, and can be adjusted in the future if needed. - */ -const STATUS_BAR_PRIORITY = 100; /** * Language client instance for the default workspace folder or untitled documents. @@ -98,38 +48,12 @@ let defaultClient: LanguageClient | undefined; */ const clients = new Map(); -/** - * Convert VSCode LogLevel to a simple boolean for AGLint debug mode. - * Enable AGLint debugger only when VSCode log level is Debug or Trace. - * - * @param logLevel VSCode log level. - * - * @returns Whether AGLint debug mode should be enabled. - */ -function shouldEnableAglintDebug(logLevel: LogLevel): boolean { - // LogLevel enum: Off = 0, Trace = 1, Debug = 2, Info = 3, Warning = 4, Error = 5 - // Enable AGLint debug when log level is Trace (1) or Debug (2) - return logLevel <= LogLevel.Debug; -} - /** * Status bar item to show the AGLint status. * This is shared across all workspace folders and updates based on the active editor's folder. */ let statusBarItem: StatusBarItem; -/** - * Schema for the server notification parameters. - * Allow undefined / null payloads to act as "neutral" updates. - */ -// TODO (AG-45205): Improve notification schema -const notificationSchema = v.object({ - error: v.optional(v.unknown()), - aglintEnabled: v.optional(v.boolean()), -}); - -type AglintStatus = v.InferInput; - /** * Map of last-known status per OUTERMOST folder. * For example, if `project-1` is added to the workspace, but @@ -164,24 +88,6 @@ function renderStatus(status: AglintStatus | undefined) { : 'AGLint'; } -/** - * Parse incoming server params; tolerate undefined/null. - * - * @param params Params to parse. - * - * @returns Parsed status. - */ -function parseStatusParams(params: unknown): AglintStatus { - const schema = v.union([notificationSchema, v.undefined(), v.null()]); - const parsed = v.safeParse(schema, params); - - if (!parsed.success) { - return {}; - } - - return (parsed.output ?? {}); -} - /** * Update the status bar for a specific workspace folder. * @@ -250,29 +156,42 @@ function createClientForFolder(folder: WorkspaceFolder, serverModule: string): L outputChannel, synchronize: { + // File watchers are configured to explicitly avoid node_modules. + // VSCode's createFileSystemWatcher respects 'files.watcherExclude' by default, + // but we also structure patterns to be explicit about what we want to watch. fileEvents: [ + // Watch filter list files (but ignore changes, only watch create/delete) + // Pattern avoids node_modules by using VSCode's default exclusions Workspace.createFileSystemWatcher( new RelativePattern( folder, - `{**/*.{${Array.from(SUPPORTED_FILE_EXTENSIONS).join(',')}},!**/node_modules/**}`, - ), - false, - true, - false, - ), - Workspace.createFileSystemWatcher( - new RelativePattern( - folder, - `{**/{${Array.from(CONFIG_FILE_NAMES).join(',')}},!**/node_modules/**}`, + `**/*.{${Array.from(SUPPORTED_FILE_EXTENSIONS).join(',')}}`, ), + false, // ignoreCreateEvents + true, // ignoreChangeEvents + false, // ignoreDeleteEvents ), + // Watch AGLint config files at workspace root + ...Array.from(CONFIG_FILE_NAMES).map((configName) => Workspace.createFileSystemWatcher( + new RelativePattern(folder, configName), + )), + // Watch AGLint config files in subdirectories (VSCode excludes node_modules by default) + ...Array.from(CONFIG_FILE_NAMES).map((configName) => Workspace.createFileSystemWatcher( + new RelativePattern(folder, `*/${configName}`), + )), + // Watch .aglintignore file at workspace root + Workspace.createFileSystemWatcher(new RelativePattern(folder, IGNORE_FILE_NAME)), + // Watch .aglintignore in subdirectories + Workspace.createFileSystemWatcher(new RelativePattern(folder, `*/${IGNORE_FILE_NAME}`)), + // Watch package.json ONLY at workspace root for AGLint installation detection + Workspace.createFileSystemWatcher(new RelativePattern(folder, 'package.json')), + // Watch node_modules directory itself (creation/deletion) for package installation detection Workspace.createFileSystemWatcher( - new RelativePattern(folder, `{**/${IGNORE_FILE_NAME},!**/node_modules/**}`), + new RelativePattern(folder, 'node_modules'), + false, // ignoreCreateEvents + false, // ignoreChangeEvents + false, // ignoreDeleteEvents ), - // Watch package.json for AGLint installation changes (only root, not node_modules) - Workspace.createFileSystemWatcher(new RelativePattern(folder, 'package.json')), - // Watch node_modules directory itself for package installation/updates - Workspace.createFileSystemWatcher(new RelativePattern(folder, 'node_modules')), ], }, diff --git a/client/src/utils/log-level.ts b/client/src/utils/log-level.ts new file mode 100644 index 0000000..de61cc7 --- /dev/null +++ b/client/src/utils/log-level.ts @@ -0,0 +1,20 @@ +/** + * @file Utility functions for working with VSCode log levels. + */ + +import { LogLevel } from 'vscode'; + +/** + * Convert VSCode LogLevel to a simple boolean for AGLint debug mode. + * Enable AGLint debugger only when VSCode log level is Debug or Trace. + * + * @param logLevel VSCode log level. + * + * @returns Whether AGLint debug mode should be enabled. + */ +export function shouldEnableAglintDebug(logLevel: LogLevel): boolean { + // LogLevel enum: Off = 0, Trace = 1, Debug = 2, Info = 3, Warning = 4, Error = 5 + // Enable AGLint debug when log level is Trace (1) or Debug (2) + // Off (0) should NOT enable debug + return logLevel === LogLevel.Trace || logLevel === LogLevel.Debug; +} diff --git a/client/src/utils/status-parser.ts b/client/src/utils/status-parser.ts new file mode 100644 index 0000000..8a7e6dc --- /dev/null +++ b/client/src/utils/status-parser.ts @@ -0,0 +1,34 @@ +/** + * @file Utility functions for parsing and handling AGLint status notifications. + */ + +import * as v from 'valibot'; + +/** + * Schema for the server notification parameters. + * Allow undefined / null payloads to act as "neutral" updates. + */ +const notificationSchema = v.object({ + error: v.optional(v.unknown()), + aglintEnabled: v.optional(v.boolean()), +}); + +export type AglintStatus = v.InferInput; + +/** + * Parse incoming server params; tolerate undefined/null. + * + * @param params Params to parse. + * + * @returns Parsed status. + */ +export function parseStatusParams(params: unknown): AglintStatus { + const schema = v.union([notificationSchema, v.undefined(), v.null()]); + const parsed = v.safeParse(schema, params); + + if (!parsed.success) { + return {}; + } + + return (parsed.output ?? {}); +} diff --git a/client/tests/.eslintrc.cjs b/client/tests/.eslintrc.cjs new file mode 100644 index 0000000..97c49ed --- /dev/null +++ b/client/tests/.eslintrc.cjs @@ -0,0 +1,8 @@ +/** + * @file ESLint configuration for tests. + */ +module.exports = { + rules: { + 'import/no-extraneous-dependencies': 'off', + }, +}; diff --git a/client/tests/__mocks__/vscode.ts b/client/tests/__mocks__/vscode.ts new file mode 100644 index 0000000..57d8232 --- /dev/null +++ b/client/tests/__mocks__/vscode.ts @@ -0,0 +1,29 @@ +/** + * @file Mock of VSCode API for testing. + * + * This provides minimal mocks of VSCode types and enums needed for unit tests. + */ + +/** + * Mock LogLevel enum. + * + * Values from: https://code.visualstudio.com/api/references/vscode-api#LogLevel. + */ +export enum LogLevel { + Off = 0, + Trace = 1, + Debug = 2, + Info = 3, + Warning = 4, + Error = 5, +} + +// Export other mocks as needed for tests +export const workspace = { + workspaceFolders: [], + onDidChangeWorkspaceFolders: () => ({ dispose: () => {} }), +}; + +export const window = { + activeTextEditor: undefined, +}; diff --git a/client/tests/utils/log-level.test.ts b/client/tests/utils/log-level.test.ts new file mode 100644 index 0000000..23f987a --- /dev/null +++ b/client/tests/utils/log-level.test.ts @@ -0,0 +1,42 @@ +/** + * @file Tests for log-level utility functions. + */ + +import { describe, expect, it } from 'vitest'; +import { LogLevel } from 'vscode'; + +import { shouldEnableAglintDebug } from '../../src/utils/log-level'; + +describe('shouldEnableAglintDebug', () => { + it('should enable debug for Trace level', () => { + expect(shouldEnableAglintDebug(LogLevel.Trace)).toBe(true); + }); + + it('should enable debug for Debug level', () => { + expect(shouldEnableAglintDebug(LogLevel.Debug)).toBe(true); + }); + + it('should disable debug for Info level', () => { + expect(shouldEnableAglintDebug(LogLevel.Info)).toBe(false); + }); + + it('should disable debug for Warning level', () => { + expect(shouldEnableAglintDebug(LogLevel.Warning)).toBe(false); + }); + + it('should disable debug for Error level', () => { + expect(shouldEnableAglintDebug(LogLevel.Error)).toBe(false); + }); + + it('should disable debug for Off level', () => { + expect(shouldEnableAglintDebug(LogLevel.Off)).toBe(false); + }); + + it('should handle boundary case correctly', () => { + // LogLevel.Debug is the boundary - should be true + expect(shouldEnableAglintDebug(LogLevel.Debug)).toBe(true); + + // LogLevel.Info is just above - should be false + expect(shouldEnableAglintDebug(LogLevel.Info)).toBe(false); + }); +}); diff --git a/client/tests/utils/status-parser.test.ts b/client/tests/utils/status-parser.test.ts new file mode 100644 index 0000000..03f8e3e --- /dev/null +++ b/client/tests/utils/status-parser.test.ts @@ -0,0 +1,83 @@ +/** + * @file Tests for status parsing utilities. + */ + +import { describe, expect, it } from 'vitest'; + +import { parseStatusParams } from '../../src/utils/status-parser'; + +describe('parseStatusParams', () => { + it('should parse valid status with error', () => { + const result = parseStatusParams({ error: 'Something went wrong' }); + expect(result).toEqual({ error: 'Something went wrong' }); + }); + + it('should parse valid status with aglintEnabled', () => { + const result = parseStatusParams({ aglintEnabled: false }); + expect(result).toEqual({ aglintEnabled: false }); + }); + + it('should parse valid status with both error and aglintEnabled', () => { + const result = parseStatusParams({ + error: 'Error message', + aglintEnabled: true, + }); + expect(result).toEqual({ + error: 'Error message', + aglintEnabled: true, + }); + }); + + it('should handle undefined params', () => { + const result = parseStatusParams(undefined); + expect(result).toEqual({}); + }); + + it('should handle null params', () => { + const result = parseStatusParams(null); + expect(result).toEqual({}); + }); + + it('should handle empty object', () => { + const result = parseStatusParams({}); + expect(result).toEqual({}); + }); + + it('should return empty object for invalid params', () => { + const result = parseStatusParams('invalid string'); + expect(result).toEqual({}); + }); + + it('should return empty object for number', () => { + const result = parseStatusParams(123); + expect(result).toEqual({}); + }); + + it('should return empty object for boolean', () => { + const result = parseStatusParams(true); + expect(result).toEqual({}); + }); + + it('should handle status with only error field', () => { + const result = parseStatusParams({ error: new Error('Test error') }); + expect(result.error).toBeInstanceOf(Error); + expect((result.error as Error).message).toBe('Test error'); + }); + + it('should handle status with aglintEnabled true', () => { + const result = parseStatusParams({ aglintEnabled: true }); + expect(result).toEqual({ aglintEnabled: true }); + }); + + it('should ignore extra fields', () => { + const result = parseStatusParams({ + error: 'Error', + aglintEnabled: false, + extraField: 'should be ignored', + }); + + expect(result).toHaveProperty('error'); + expect(result).toHaveProperty('aglintEnabled'); + // Extra fields might be included depending on schema behavior + }); +}); diff --git a/client/tests/workspace-folders.test.ts b/client/tests/workspace-folders.test.ts new file mode 100644 index 0000000..c1697a3 --- /dev/null +++ b/client/tests/workspace-folders.test.ts @@ -0,0 +1,183 @@ +import { + beforeEach, + describe, + expect, + it, + vi, +} from 'vitest'; + +/** + * Minimal mock of VSCode's WorkspaceFolder type. + */ +type WorkspaceFolder = { + uri: { + fsPath: string; + }; +}; + +/** + * Hoisted stateful mock of the VS Code workspace API. + */ +const h = vi.hoisted(() => { + const state = { + folders: [] as WorkspaceFolder[], + listeners: [] as Array<(...args: any[]) => void>, + }; + + const workspace = { + get workspaceFolders() { + return state.folders; + }, + set workspaceFolders(v: WorkspaceFolder[] | undefined) { + state.folders = v ?? []; + }, + onDidChangeWorkspaceFolders(cb: (...args: any[]) => void) { + state.listeners.push(cb); + + return { + dispose() { + /* noop */ + }, + }; + }, + }; + + const api = { + setFolders(folders: WorkspaceFolder[]) { + state.folders = folders; + }, + emitChange() { + for (const cb of state.listeners) { + cb({}); + } + }, + reset() { + state.folders = []; + state.listeners = []; + }, + }; + + return { + state, + workspace, + api, + }; +}); + +vi.mock('vscode', () => ({ + workspace: h.workspace, +})); + +/** + * Helper to create a WorkspaceFolder from a path. + * Note, this is a minimal stub, only the fsPath is needed for our tests. + * + * @param p Path. + * + * @returns WorkspaceFolder. + */ +const f = (p: string): WorkspaceFolder => ({ + uri: { + fsPath: p, + }, +}); + +describe('workspace utility', () => { + beforeEach(() => { + vi.clearAllMocks(); + // ensure fresh import of the SUT each test + vi.resetModules(); + + // reset our hoisted mock state + h.api.reset(); + }); + + it('fileInFolder: handles basic POSIX paths (absolute & relative)', async () => { + const util = await import('../src/workspace-folders'); + + // absolute inside outer + expect(util.fileInFolder('/a/b/c.txt', '/a')).toBe(true); + + // exact match (implementation treats "inside" as strictly underneath, not equal) + expect(util.fileInFolder('/a/b', '/a/b')).toBe(false); + + // similar prefix but different folder + expect(util.fileInFolder('/a/b', '/a/bb')).toBe(false); + + // relative paths resolve against CWD + expect(util.fileInFolder('src/file.ts', 'src')).toBe(true); + expect(util.fileInFolder('src/file.ts', 'dist')).toBe(false); + }); + + it('fileInFolder: compares case-insensitively on Windows', async () => { + // force windows path semantics for this test + const pathWin32 = await import('node:path').then((m) => m.win32); + vi.doMock('node:path', () => pathWin32 as any); + + const originalPlatform = process.platform; + Object.defineProperty(process, 'platform', { value: 'win32' }); + + try { + const util = await import('../src/workspace-folders'); + + const file = 'C:\\Users\\Me\\Project\\src\\Index.ts'; + const folder = 'c:\\users\\me\\project'; + + expect(util.fileInFolder(file, folder)).toBe(true); + + expect(util.fileInFolder('C:\\Other\\x.ts', folder)).toBe(false); + } finally { + Object.defineProperty(process, 'platform', { value: originalPlatform }); + } + }); + + it('getSortedWorkspaceFolders: sorts by fsPath length ascending and caches', async () => { + h.api.setFolders([f('/z/very/long/path'), f('/a'), f('/a/b')]); + + const util = await import('../src/workspace-folders'); + + const first = util.getSortedWorkspaceFolders().map((w) => w.uri.fsPath); + + expect(first).toEqual(['/a', '/a/b', '/z/very/long/path']); + + // mutate backing folders but don't emit change -> cache should stick + h.api.setFolders([f('/should/not/be/seen')]); + + const second = util.getSortedWorkspaceFolders().map((w) => w.uri.fsPath); + + expect(second).toEqual(first); + }); + + it('getSortedWorkspaceFolders: cache invalidates on Workspace.onDidChangeWorkspaceFolders', async () => { + h.api.setFolders([f('/c'), f('/a/b'), f('/a')]); + + const util = await import('../src/workspace-folders'); + + const initial = util.getSortedWorkspaceFolders().map((w) => w.uri.fsPath); + + // stable sort by length: '/c'(2), '/a'(2), '/a/b'(4) -> '/c', '/a', '/a/b' + expect(initial).toEqual(['/c', '/a', '/a/b']); + + // update folders and emit change -> cache should invalidate + h.api.setFolders([f('/root'), f('/root/sub'), f('/x')]); + h.api.emitChange(); + + const after = util.getSortedWorkspaceFolders().map((w) => w.uri.fsPath); + + expect(after).toEqual(['/x', '/root', '/root/sub']); + }); + + it('getOuterMostWorkspaceFolder: returns the outer-most containing folder', async () => { + h.api.setFolders([f('/root'), f('/root/packages/app'), f('/root/packages')]); + + const util = await import('../src/workspace-folders'); + + const target = f('/root/packages/app'); + + expect(util.getOuterMostWorkspaceFolder(target as any).uri.fsPath).toBe('/root'); + + const isolated = f('/elsewhere/project'); + + expect(util.getOuterMostWorkspaceFolder(isolated as any).uri.fsPath).toBe('/elsewhere/project'); + }); +}); diff --git a/client/tsconfig.base.json b/client/tsconfig.base.json new file mode 100644 index 0000000..900ed38 --- /dev/null +++ b/client/tsconfig.base.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.base.json" +} diff --git a/client/tsconfig.build.json b/client/tsconfig.build.json new file mode 100644 index 0000000..8bff08d --- /dev/null +++ b/client/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "out", + "rootDir": "src", + "declaration": true, + "emitDeclarationOnly": true, + "noEmit": false, + "types": ["node"] + }, + "include": ["src/**/*"] +} diff --git a/client/tsconfig.json b/client/tsconfig.json index aa08902..57df16e 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,14 +1,15 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "module": "es2020", - "target": "es2020", - "lib": ["es2020"], - "moduleResolution": "bundler", - "outDir": "out", - "rootDir": "src", - "sourceMap": true, - "skipLibCheck": true + "noEmit": true }, - "include": ["src"], + "include": [ + ".eslintrc.cjs", + "rspack.config.ts", + "src/**/*.ts", + "tests/.eslintrc.cjs", + "tests/**/*.ts", + "vitest.config.ts" + ], "exclude": ["node_modules", ".vscode-test"] } diff --git a/client/vitest.config.ts b/client/vitest.config.ts new file mode 100644 index 0000000..9d24b05 --- /dev/null +++ b/client/vitest.config.ts @@ -0,0 +1,17 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + watch: false, + coverage: { + include: [ + 'src/**/*.ts', + ], + }, + alias: { + // Mock the vscode module for testing + vscode: new URL('./tests/__mocks__/vscode.ts', import.meta.url).pathname, + }, + }, +}); diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index c7cc853..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Config } from 'jest'; - -const config: Config = { - testEnvironment: 'node', - testTimeout: 30000, - testMatch: ['**/test/**/*.test.ts'], - // Speed up tests by using SWC instead of Babel - transform: { '.ts': '@swc/jest' }, -}; - -export default config; diff --git a/package.json b/package.json index 23684f5..7600662 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "adblock", "displayName": "Adblock/AdGuard/uBlock filters grammar", "description": "VS code extension that adds support for ad blocking rules syntax.", - "version": "2.0.4", + "version": "2.1.1", "publisher": "adguard", "icon": "icons/aglint_128x128.png", "main": "./client/out/extension", @@ -76,76 +76,46 @@ } }, "scripts": { - "build:grammar": "tsx tools/grammar-builder.ts", - "build:prod": "pnpm build:clean && pnpm build:grammar && pnpm test:compile && pnpm esbuild:client --minify && pnpm esbuild:server --minify && pnpm build:vsix", - "build:prerelease": "pnpm build:clean && pnpm build:grammar && pnpm test:compile && pnpm esbuild:client --minify && pnpm esbuild:server --minify && pnpm build:vsix-prerelease", - "build:txt": "tsx tools/build-txt.ts", - "build:vsix": "mkdirp out && vsce package --out out/vscode-adblock.vsix", - "build:vsix-prerelease": "mkdirp out && vsce package --out out/vscode-adblock.vsix --pre-release", - "build:clean": "rimraf ./client/out && rimraf ./server/out && rimraf ./syntaxes/out && rimraf ./out", + "build": "cross-env NODE_ENV=production pnpm --recursive build", "clean": "tsx tools/clean.ts", - "esbuild:client": "esbuild ./client/src/extension.ts --bundle --outfile=client/out/extension.js --format=cjs --platform=node --external:vscode", - "esbuild:server": "esbuild ./server/src/server.ts --bundle --outfile=server/out/server.js --format=cjs --platform=node --external:vscode", - "extract-changelog": "node -r esbuild-register tools/changelog-extractor.ts", "increment": "pnpm version patch --no-git-tag-version", - "lint": "pnpm lint:ts && pnpm lint:md", + "lint": "pnpm --recursive lint", "lint:md": "markdownlint .", - "lint:staged": "lint-staged", - "lint:ts": "eslint . --cache --ext .ts", - "prepare": "husky", - "test": "jest", - "test:compile": "tsc -p ./client --noEmit && tsc -p ./server --noEmit", - "watch:client": "pnpm esbuild:client --sourcemap --watch", - "watch:grammar": "chokidar \"syntaxes/adblock.yaml-tmlanguage\" -c \"tsx tools/grammar-builder.ts\" --silent --initial", - "watch:server": "pnpm esbuild:server --sourcemap --watch" + "lint:code": "eslint . --cache --ext .ts --ext .js", + "prepackage": "rimraf out && mkdirp out", + "package": "vsce package --out out/vscode-adblock.vsix", + "package:pre": "pnpm package --pre-release", + "prepare": "node .husky/install.mjs", + "test": "pnpm --recursive test --run", + "test:compile": "pnpm --recursive --parallel --filter='!aglint-test-project' exec tsc --noEmit" }, "devDependencies": { - "@adguard/changelog-tools": "^0.0.1", - "@swc/core": "^1.3.76", - "@swc/jest": "^0.2.28", - "@types/fs-extra": "^11.0.1", - "@types/jest": "^29.5.1", - "@types/node": "^18.11.18", - "@types/plist": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "@vscode/vsce": "^3.7.1", - "chokidar-cli": "^3.0.0", - "commander": "^11.1.0", - "concurrently": "^8.0.1", - "esbuild": "^0.17.17", - "esbuild-register": "^3.5.0", - "escape-string-regexp": "^5.0.0", - "eslint": "^8.46.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-plugin-boundaries": "^5.0.1", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-import-newlines": "^1.4.0", - "eslint-plugin-jsdoc": "^46.10.1", - "eslint-plugin-n": "^17.23.1", - "fs-extra": "^11.1.1", - "husky": "^9.0.1", - "jest": "^29.6.2", - "jsdoc": "^4.0.4", - "lint-staged": "^15.1.0", - "markdownlint": "^0.30.0", - "markdownlint-cli": "^0.35.0", - "mkdirp": "^3.0.1", - "ovsx": "^0.8.3", - "plist": "^3.0.6", - "remark-inline-links": "^7.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "rimraf": "^4.1.2", - "ts-jest": "^29.1.0", - "ts-node": "^10.9.1", - "tsx": "^4.7.0", - "typescript": "^5.9.2", - "unified": "^11.0.4", - "vscode-oniguruma": "^2.0.1", - "vscode-textmate": "^9.0.0", - "yaml": "^2.2.2" + "@adguard/changelog-tools": "catalog:", + "@types/node": "catalog:", + "@typescript-eslint/eslint-plugin": "catalog:", + "@typescript-eslint/parser": "catalog:", + "@vscode/vsce": "catalog:", + "ci-info": "catalog:", + "cross-env": "catalog:", + "eslint": "catalog:", + "eslint-config-airbnb-base": "catalog:", + "eslint-config-airbnb-typescript": "catalog:", + "eslint-plugin-boundaries": "catalog:", + "eslint-plugin-import": "catalog:", + "eslint-plugin-import-newlines": "catalog:", + "eslint-plugin-jsdoc": "catalog:", + "eslint-plugin-n": "catalog:", + "husky": "catalog:", + "jsdoc": "catalog:", + "lint-staged": "catalog:", + "markdownlint": "catalog:", + "markdownlint-cli": "catalog:", + "mkdirp": "catalog:", + "ovsx": "catalog:", + "rimraf": "catalog:", + "tsx": "catalog:", + "typescript": "catalog:", + "vscode-oniguruma": "catalog:" }, "pnpm": { "neverBuiltDependencies": [] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52044f0..33c72f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,218 +7,430 @@ settings: catalogs: default: '@adguard/aglint': - specifier: ^4.0.0-beta.1 - version: 4.0.0-beta.1 + specifier: ^4.0.0-beta.3 + version: 4.0.0-beta.3 + '@adguard/agtree': + specifier: ^2.3.0 + version: 2.3.0 + '@adguard/changelog-tools': + specifier: ^0.0.1 + version: 0.0.1 + '@rspack/cli': + specifier: ^1.6.7 + version: 1.6.7 + '@rspack/core': + specifier: ^1.1.7 + version: 1.6.7 + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + '@types/node': + specifier: ^20.19.26 + version: 20.19.26 + '@types/plist': + specifier: ^3.0.5 + version: 3.0.5 + '@types/resolve': + specifier: ^1.20.6 + version: 1.20.6 + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 + '@types/vscode': + specifier: ^1.74.0 + version: 1.99.0 + '@typescript-eslint/eslint-plugin': + specifier: ^7.5.0 + version: 7.18.0 + '@typescript-eslint/parser': + specifier: ^7.5.0 + version: 7.18.0 + '@vitest/coverage-v8': + specifier: ^4.0.15 + version: 4.0.15 + '@vitest/expect': + specifier: ^4.0.15 + version: 4.0.15 + '@vscode/vsce': + specifier: ^3.7.1 + version: 3.7.1 + chokidar: + specifier: ^5.0.0 + version: 5.0.0 + ci-info: + specifier: ^4.3.1 + version: 4.3.1 + cross-env: + specifier: ^10.1.0 + version: 10.1.0 + debounce: + specifier: ^3.0.0 + version: 3.0.0 + eslint: + specifier: 8.57.1 + version: 8.57.1 + eslint-config-airbnb-base: + specifier: ^15.0.0 + version: 15.0.0 + eslint-config-airbnb-typescript: + specifier: ^18.0.0 + version: 18.0.0 + eslint-plugin-boundaries: + specifier: ^5.3.1 + version: 5.3.1 + eslint-plugin-import: + specifier: ^2.32.0 + version: 2.32.0 + eslint-plugin-import-newlines: + specifier: ^1.4.0 + version: 1.4.0 + eslint-plugin-jsdoc: + specifier: ^61.5.0 + version: 61.5.0 + eslint-plugin-n: + specifier: ^17.23.1 + version: 17.23.1 + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 + fs-extra: + specifier: ^11.3.1 + version: 11.3.2 + husky: + specifier: ^9.1.7 + version: 9.1.7 + jsdoc: + specifier: ^4.0.5 + version: 4.0.5 + lint-staged: + specifier: ^16.2.7 + version: 16.2.7 + markdownlint: + specifier: ^0.40.0 + version: 0.40.0 + markdownlint-cli: + specifier: ^0.46.0 + version: 0.46.0 + mkdirp: + specifier: ^3.0.1 + version: 3.0.1 + ovsx: + specifier: ^0.10.7 + version: 0.10.7 + plist: + specifier: ^3.1.0 + version: 3.1.0 + preferred-pm: + specifier: ^4.1.1 + version: 4.1.1 + resolve: + specifier: ^1.22.11 + version: 1.22.11 + rimraf: + specifier: ^6.1.2 + version: 6.1.2 + semver: + specifier: ^7.7.3 + version: 7.7.3 + tsc-files: + specifier: 1.1.4 + version: 1.1.4 + tsx: + specifier: ^4.21.0 + version: 4.21.0 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + valibot: + specifier: ^1.2.0 + version: 1.2.0 + vitest: + specifier: ^4.0.15 + version: 4.0.15 + vscode-languageclient: + specifier: 10.0.0-next.15 + version: 10.0.0-next.15 + vscode-languageserver: + specifier: 10.0.0-next.13 + version: 10.0.0-next.13 + vscode-languageserver-textdocument: + specifier: ^1.0.12 + version: 1.0.12 + vscode-oniguruma: + specifier: ^2.0.1 + version: 2.0.1 + vscode-textmate: + specifier: ^9.3.0 + version: 9.3.0 + vscode-uri: + specifier: ^3.1.0 + version: 3.1.0 + yaml: + specifier: ^2.8.2 + version: 2.8.2 importers: .: devDependencies: '@adguard/changelog-tools': - specifier: ^0.0.1 + specifier: 'catalog:' version: 0.0.1 - '@swc/core': - specifier: ^1.3.76 - version: 1.11.18 - '@swc/jest': - specifier: ^0.2.28 - version: 0.2.37(@swc/core@1.11.18) - '@types/fs-extra': - specifier: ^11.0.1 - version: 11.0.4 - '@types/jest': - specifier: ^29.5.1 - version: 29.5.14 '@types/node': - specifier: ^18.11.18 - version: 18.19.86 - '@types/plist': - specifier: ^3.0.2 - version: 3.0.5 + specifier: 'catalog:' + version: 20.19.26 '@typescript-eslint/eslint-plugin': - specifier: ^6.3.0 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2) + specifier: 'catalog:' + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) '@typescript-eslint/parser': - specifier: ^6.3.0 - version: 6.21.0(eslint@8.57.1)(typescript@5.9.2) + specifier: 'catalog:' + version: 7.18.0(eslint@8.57.1)(typescript@5.9.3) '@vscode/vsce': - specifier: ^3.7.1 + specifier: 'catalog:' version: 3.7.1 - chokidar-cli: - specifier: ^3.0.0 - version: 3.0.0 - commander: - specifier: ^11.1.0 - version: 11.1.0 - concurrently: - specifier: ^8.0.1 - version: 8.2.2 - esbuild: - specifier: ^0.17.17 - version: 0.17.19 - esbuild-register: - specifier: ^3.5.0 - version: 3.6.0(esbuild@0.17.19) - escape-string-regexp: - specifier: ^5.0.0 - version: 5.0.0 + ci-info: + specifier: 'catalog:' + version: 4.3.1 + cross-env: + specifier: 'catalog:' + version: 10.1.0 eslint: - specifier: ^8.46.0 + specifier: 'catalog:' version: 8.57.1 eslint-config-airbnb-base: - specifier: ^15.0.0 - version: 15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) + specifier: 'catalog:' + version: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1) eslint-config-airbnb-typescript: - specifier: ^17.1.0 - version: 17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) + specifier: 'catalog:' + version: 18.0.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-boundaries: - specifier: ^5.0.1 - version: 5.0.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + specifier: 'catalog:' + version: 5.3.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) eslint-plugin-import: - specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + specifier: 'catalog:' + version: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) eslint-plugin-import-newlines: - specifier: ^1.4.0 + specifier: 'catalog:' version: 1.4.0(eslint@8.57.1) eslint-plugin-jsdoc: - specifier: ^46.10.1 - version: 46.10.1(eslint@8.57.1) + specifier: 'catalog:' + version: 61.5.0(eslint@8.57.1) eslint-plugin-n: - specifier: ^17.23.1 - version: 17.23.1(eslint@8.57.1)(typescript@5.9.2) - fs-extra: - specifier: ^11.1.1 - version: 11.3.0 + specifier: 'catalog:' + version: 17.23.1(eslint@8.57.1)(typescript@5.9.3) husky: - specifier: ^9.0.1 + specifier: 'catalog:' version: 9.1.7 - jest: - specifier: ^29.6.2 - version: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) jsdoc: - specifier: ^4.0.4 - version: 4.0.4 + specifier: 'catalog:' + version: 4.0.5 lint-staged: - specifier: ^15.1.0 - version: 15.5.0 + specifier: 'catalog:' + version: 16.2.7 markdownlint: - specifier: ^0.30.0 - version: 0.30.0 + specifier: 'catalog:' + version: 0.40.0 markdownlint-cli: - specifier: ^0.35.0 - version: 0.35.0 + specifier: 'catalog:' + version: 0.46.0 mkdirp: - specifier: ^3.0.1 + specifier: 'catalog:' version: 3.0.1 ovsx: - specifier: ^0.8.3 - version: 0.8.4 - plist: - specifier: ^3.0.6 - version: 3.1.0 - remark-inline-links: - specifier: ^7.0.0 - version: 7.0.0 - remark-parse: - specifier: ^11.0.0 - version: 11.0.0 - remark-stringify: - specifier: ^11.0.0 - version: 11.0.0 + specifier: 'catalog:' + version: 0.10.7 rimraf: - specifier: ^4.1.2 - version: 4.4.1 - ts-jest: - specifier: ^29.1.0 - version: 29.3.1(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(esbuild@0.17.19)(jest@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)))(typescript@5.9.2) - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2) + specifier: 'catalog:' + version: 6.1.2 tsx: - specifier: ^4.7.0 - version: 4.19.3 + specifier: 'catalog:' + version: 4.21.0 typescript: - specifier: ^5.9.2 - version: 5.9.2 - unified: - specifier: ^11.0.4 - version: 11.0.5 + specifier: 'catalog:' + version: 5.9.3 vscode-oniguruma: - specifier: ^2.0.1 + specifier: 'catalog:' version: 2.0.1 - vscode-textmate: - specifier: ^9.0.0 - version: 9.2.0 - yaml: - specifier: ^2.2.2 - version: 2.7.1 client: dependencies: + '@vscode-adblock-syntax/shared': + specifier: workspace:^ + version: link:../shared valibot: - specifier: ^1.1.0 - version: 1.1.0(typescript@5.9.2) + specifier: 'catalog:' + version: 1.2.0(typescript@5.9.3) vscode-languageclient: - specifier: 10.0.0-next.15 + specifier: 'catalog:' version: 10.0.0-next.15 devDependencies: + '@rspack/cli': + specifier: 'catalog:' + version: 1.6.7(@rspack/core@1.6.7)(@types/express@4.17.25) + '@rspack/core': + specifier: 'catalog:' + version: 1.6.7 '@types/vscode': - specifier: ^1.74.0 + specifier: 'catalog:' version: 1.99.0 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + tsc-files: + specifier: 'catalog:' + version: 1.1.4(typescript@5.9.3) + tsx: + specifier: 'catalog:' + version: 4.21.0 + vitest: + specifier: 'catalog:' + version: 4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) server: dependencies: + '@vscode-adblock-syntax/shared': + specifier: workspace:^ + version: link:../shared debounce: - specifier: ^3.0.0 + specifier: 'catalog:' version: 3.0.0 fast-glob: - specifier: ^3.3.3 + specifier: 'catalog:' version: 3.3.3 preferred-pm: - specifier: ^4.1.1 + specifier: 'catalog:' version: 4.1.1 resolve: - specifier: ^1.22.11 + specifier: 'catalog:' version: 1.22.11 + semver: + specifier: 'catalog:' + version: 7.7.3 vscode-languageserver: - specifier: 10.0.0-next.13 + specifier: 'catalog:' version: 10.0.0-next.13 vscode-languageserver-textdocument: - specifier: ^1.0.8 + specifier: 'catalog:' version: 1.0.12 vscode-uri: - specifier: ^3.1.0 + specifier: 'catalog:' version: 3.1.0 yaml: - specifier: ^2.7.1 - version: 2.7.1 + specifier: 'catalog:' + version: 2.8.2 devDependencies: '@adguard/aglint': specifier: 'catalog:' - version: 4.0.0-beta.1(@types/node@20.17.30)(typescript@5.9.2) + version: 4.0.0-beta.3(@types/node@24.10.2)(typescript@5.9.3) '@adguard/agtree': - specifier: ^2.3.0 + specifier: 'catalog:' version: 2.3.0 + '@rspack/cli': + specifier: 'catalog:' + version: 1.6.7(@rspack/core@1.6.7)(@types/express@4.17.25) + '@rspack/core': + specifier: 'catalog:' + version: 1.6.7 '@types/resolve': - specifier: ^1.20.6 + specifier: 'catalog:' version: 1.20.6 '@types/semver': - specifier: ^7.5.0 - version: 7.5.0 - semver: - specifier: ^7.5.4 - version: 7.5.4 + specifier: 'catalog:' + version: 7.7.1 + '@vitest/coverage-v8': + specifier: 'catalog:' + version: 4.0.15(vitest@4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2)) + rimraf: + specifier: 'catalog:' + version: 6.1.2 + tsc-files: + specifier: 'catalog:' + version: 1.1.4(typescript@5.9.3) + tsx: + specifier: 'catalog:' + version: 4.21.0 + vitest: + specifier: 'catalog:' + version: 4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) + + shared: + devDependencies: + '@rspack/cli': + specifier: 'catalog:' + version: 1.6.7(@rspack/core@1.6.7)(@types/express@4.17.25) + '@rspack/core': + specifier: 'catalog:' + version: 1.6.7 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + tsc-files: + specifier: 'catalog:' + version: 1.1.4(typescript@5.9.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + vitest: + specifier: 'catalog:' + version: 4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) + + syntaxes: + devDependencies: + '@types/fs-extra': + specifier: 'catalog:' + version: 11.0.4 + '@types/node': + specifier: 'catalog:' + version: 20.19.26 + '@types/plist': + specifier: 'catalog:' + version: 3.0.5 + '@vitest/expect': + specifier: 'catalog:' + version: 4.0.15 + chokidar: + specifier: 'catalog:' + version: 5.0.0 + fs-extra: + specifier: 'catalog:' + version: 11.3.2 + plist: + specifier: 'catalog:' + version: 3.1.0 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + tsc-files: + specifier: 'catalog:' + version: 1.1.4(typescript@5.9.3) + valibot: + specifier: 'catalog:' + version: 1.2.0(typescript@5.9.3) + vitest: + specifier: 'catalog:' + version: 4.0.15(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2) + vscode-oniguruma: + specifier: 'catalog:' + version: 2.0.1 + vscode-textmate: + specifier: 'catalog:' + version: 9.3.0 + yaml: + specifier: 'catalog:' + version: 2.8.2 test/static/aglint: dependencies: '@adguard/aglint': specifier: 'catalog:' - version: 4.0.0-beta.1(@types/node@20.17.30)(typescript@5.9.2) + version: 4.0.0-beta.3(@types/node@24.10.2)(typescript@5.9.3) + + tools: {} packages: - '@adguard/aglint@4.0.0-beta.1': - resolution: {integrity: sha512-PDjD3ydoHVPihpGLy56KYeT0pq/Ig5AdgpyTpWkmFjaVHXz2aEFB8vlOeK/QvGsGim4ikip52JxWsCmmJpB41g==} + '@adguard/aglint@4.0.0-beta.3': + resolution: {integrity: sha512-lGs+PNOcdl125RWmtUokwvMadGP0WgDy03yCe1QypG8Oeyxe2WMRM2Z3CAjNdTuciNgMws+0tNmxTf1l7Eel2w==} engines: {node: '>=20'} hasBin: true @@ -241,10 +453,6 @@ packages: '@adguard/ecss-tree@2.0.1': resolution: {integrity: sha512-GvVz3rLQqcZkNVpUbdowimokhPxNL6pODwmZbiWTUfa3bEAT7XI+4ydxVZmtK2WS2u7qu/IISmI69PSFXE0ucw==} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@azu/format-text@1.0.2': resolution: {integrity: sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==} @@ -303,457 +511,367 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.8': - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.10': - resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.27.0': - resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.27.0': - resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.26.5': - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.0': - resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.27.0': - resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.26.0': - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.25.9': - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + '@babel/runtime-corejs3@7.28.4': + resolution: {integrity: sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} - '@babel/plugin-syntax-typescript@7.25.9': - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@boundaries/elements@1.1.2': + resolution: {integrity: sha512-DnGHL+v36YVMoWhWZqyJYVZ9dapNm7h4N3/P0lDPirJj0CHVPkjChMCCotj74cg6LW7iPJZFGrdEfh0X0g2bmQ==} + engines: {node: '>=18.18'} - '@babel/runtime-corejs3@7.28.4': - resolution: {integrity: sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==} - engines: {node: '>=6.9.0'} + '@discoveryjs/json-ext@0.5.7': + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} - '@babel/runtime@7.27.0': - resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} - engines: {node: '>=6.9.0'} + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} - '@babel/template@7.27.0': - resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} - engines: {node: '>=6.9.0'} + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} - '@babel/traverse@7.27.0': - resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} - engines: {node: '>=6.9.0'} + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@babel/types@7.27.0': - resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} - engines: {node: '>=6.9.0'} + '@epic-web/invariant@1.0.0': + resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@es-joy/jsdoccomment@0.76.0': + resolution: {integrity: sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==} + engines: {node: '>=20.11.0'} - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + '@es-joy/resolve.exports@1.2.0': + resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} + engines: {node: '>=10'} - '@es-joy/jsdoccomment@0.41.0': - resolution: {integrity: sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==} - engines: {node: '>=16'} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] - '@esbuild/aix-ppc64@0.25.2': - resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + '@esbuild/aix-ppc64@0.27.1': + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.17.19': - resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.2': - resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + '@esbuild/android-arm64@0.27.1': + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.17.19': - resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.2': - resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + '@esbuild/android-arm@0.27.1': + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.17.19': - resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.2': - resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + '@esbuild/android-x64@0.27.1': + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.17.19': - resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.2': - resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + '@esbuild/darwin-arm64@0.27.1': + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.17.19': - resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.2': - resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + '@esbuild/darwin-x64@0.27.1': + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.17.19': - resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.2': - resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + '@esbuild/freebsd-arm64@0.27.1': + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.17.19': - resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.2': - resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + '@esbuild/freebsd-x64@0.27.1': + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.17.19': - resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.2': - resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + '@esbuild/linux-arm64@0.27.1': + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.17.19': - resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.2': - resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + '@esbuild/linux-arm@0.27.1': + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.17.19': - resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.2': - resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + '@esbuild/linux-ia32@0.27.1': + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.17.19': - resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.2': - resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + '@esbuild/linux-loong64@0.27.1': + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.17.19': - resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.2': - resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + '@esbuild/linux-mips64el@0.27.1': + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.17.19': - resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.2': - resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + '@esbuild/linux-ppc64@0.27.1': + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.17.19': - resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.2': - resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + '@esbuild/linux-riscv64@0.27.1': + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.17.19': - resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.2': - resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + '@esbuild/linux-s390x@0.27.1': + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.17.19': - resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.2': - resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + '@esbuild/linux-x64@0.27.1': + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.2': - resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.17.19': - resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} - engines: {node: '>=12'} + '@esbuild/netbsd-arm64@0.27.1': + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.2': - resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + '@esbuild/netbsd-x64@0.27.1': + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.2': - resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.17.19': - resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} - engines: {node: '>=12'} + '@esbuild/openbsd-arm64@0.27.1': + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.2': - resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + '@esbuild/openbsd-x64@0.27.1': + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.17.19': - resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} - engines: {node: '>=12'} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.27.1': + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.2': - resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + '@esbuild/sunos-x64@0.27.1': + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.17.19': - resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.2': - resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + '@esbuild/win32-arm64@0.27.1': + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.17.19': - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.2': - resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + '@esbuild/win32-ia32@0.27.1': + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.17.19': - resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.2': - resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + '@esbuild/win32-x64@0.27.1': + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -884,108 +1002,76 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsdoc/salty@0.2.9': + resolution: {integrity: sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==} + engines: {node: '>=v12.0.0'} - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/create-cache-key-function@29.7.0': - resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + tslib: '2' - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} + engines: {node: '>=10.0'} peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + tslib: '2' - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} + '@module-federation/error-codes@0.21.6': + resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} + '@module-federation/runtime-core@0.21.6': + resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@module-federation/runtime-tools@0.21.6': + resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@module-federation/runtime@0.21.6': + resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@module-federation/sdk@0.21.6': + resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} - '@jsdoc/salty@0.2.9': - resolution: {integrity: sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==} - engines: {node: '>=v12.0.0'} + '@module-federation/webpack-bundler-runtime@0.21.6': + resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} '@napi-rs/nice-android-arm-eabi@1.1.1': resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} @@ -1093,6 +1179,99 @@ packages: resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} engines: {node: '>= 10'} + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + + '@node-rs/crc32-android-arm-eabi@1.10.6': + resolution: {integrity: sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@node-rs/crc32-android-arm64@1.10.6': + resolution: {integrity: sha512-Vl/JbjCinCw/H9gEpZveWCMjxjcEChDcDBM8S4hKay5yyoRCUHJPuKr4sjVDBeOm+1nwU3oOm6Ca8dyblwp4/w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@node-rs/crc32-darwin-arm64@1.10.6': + resolution: {integrity: sha512-kARYANp5GnmsQiViA5Qu74weYQ3phOHSYQf0G+U5wB3NB5JmBHnZcOc46Ig21tTypWtdv7u63TaltJQE41noyg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@node-rs/crc32-darwin-x64@1.10.6': + resolution: {integrity: sha512-Q99bevJVMfLTISpkpKBlXgtPUItrvTWKFyiqoKH5IvscZmLV++NH4V13Pa17GTBmv9n18OwzgQY4/SRq6PQNVA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@node-rs/crc32-freebsd-x64@1.10.6': + resolution: {integrity: sha512-66hpawbNjrgnS9EDMErta/lpaqOMrL6a6ee+nlI2viduVOmRZWm9Rg9XdGTK/+c4bQLdtC6jOd+Kp4EyGRYkAg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@node-rs/crc32-linux-arm-gnueabihf@1.10.6': + resolution: {integrity: sha512-E8Z0WChH7X6ankbVm8J/Yym19Cq3otx6l4NFPS6JW/cWdjv7iw+Sps2huSug+TBprjbcEA+s4TvEwfDI1KScjg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@node-rs/crc32-linux-arm64-gnu@1.10.6': + resolution: {integrity: sha512-LmWcfDbqAvypX0bQjQVPmQGazh4dLiVklkgHxpV4P0TcQ1DT86H/SWpMBMs/ncF8DGuCQ05cNyMv1iddUDugoQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/crc32-linux-arm64-musl@1.10.6': + resolution: {integrity: sha512-k8ra/bmg0hwRrIEE8JL1p32WfaN9gDlUUpQRWsbxd1WhjqvXea7kKO6K4DwVxyxlPhBS9Gkb5Urq7Y4mXANzaw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/crc32-linux-x64-gnu@1.10.6': + resolution: {integrity: sha512-IfjtqcuFK7JrSZ9mlAFhb83xgium30PguvRjIMI45C3FJwu18bnLk1oR619IYb/zetQT82MObgmqfKOtgemEKw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/crc32-linux-x64-musl@1.10.6': + resolution: {integrity: sha512-LbFYsA5M9pNunOweSt6uhxenYQF94v3bHDAQRPTQ3rnjn+mK6IC7YTAYoBjvoJP8lVzcvk9hRj8wp4Jyh6Y80g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/crc32-wasm32-wasi@1.10.6': + resolution: {integrity: sha512-KaejdLgHMPsRaxnM+OG9L9XdWL2TabNx80HLdsCOoX9BVhEkfh39OeahBo8lBmidylKbLGMQoGfIKDjq0YMStw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@node-rs/crc32-win32-arm64-msvc@1.10.6': + resolution: {integrity: sha512-x50AXiSxn5Ccn+dCjLf1T7ZpdBiV1Sp5aC+H2ijhJO4alwznvXgWbopPRVhbp2nj0i+Gb6kkDUEyU+508KAdGQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@node-rs/crc32-win32-ia32-msvc@1.10.6': + resolution: {integrity: sha512-DpDxQLaErJF9l36aghe1Mx+cOnYLKYo6qVPqPL9ukJ5rAGLtCdU0C+Zoi3gs9ySm8zmbFgazq/LvmsZYU42aBw==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@node-rs/crc32-win32-x64-msvc@1.10.6': + resolution: {integrity: sha512-5B1vXosIIBw1m2Rcnw62IIfH7W9s9f7H7Ma0rRuhT8HR4Xh8QCgw6NJSI2S2MCngsGktYnAhyUvs81b7efTyQw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@node-rs/crc32@1.10.6': + resolution: {integrity: sha512-+llXfqt+UzgoDzT9of5vPQPGqTAVCohU74I9zIBkNo5TH6s2P31DFJOGsJQKN207f0GHnYv5pV3wh3BCY/un/A==} + engines: {node: '>= 10'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1105,9 +1284,194 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + cpu: [x64] + os: [win32] + + '@rspack/binding-darwin-arm64@1.6.7': + resolution: {integrity: sha512-QiIAP8JTAtht0j8/xZZEQTJRB9e+KrOm9c7JJm73CewVg55rDWRrwopiVfBNlTu1coem1ztUHJYdQhg2uXfqww==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.6.7': + resolution: {integrity: sha512-DpQRxxTXkMMNPmBXeJBaAB8HmWKxH2IfvHv7vU+kBhJ3xdPtXU4/xBv1W3biluoNRG11gc1WLIgjzeGgaLCxmw==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.6.7': + resolution: {integrity: sha512-211/XoBiooGGgUo/NxNpsrzGUXtH1d7g/4+UTtjYtfc8QHwu7ZMHcsqg0wss53fXzn/yyxd0DZ56vBHq52BiFw==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.6.7': + resolution: {integrity: sha512-0WnqAWz3WPDsXGvOOA++or7cHpoidVsH3FlqNaAfRu6ni6n7ig/s0/jKUB+C5FtXOgmGjAGkZHfFgNHsvZ0FWw==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.6.7': + resolution: {integrity: sha512-iMrE0Q4IuYpkE0MjpaOVaUDYbQFiCRI9D3EPoXzlXJj4kJSdNheODpHTBVRlWt8Xp7UAoWuIFXCvKFKcSMm3aQ==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.6.7': + resolution: {integrity: sha512-e7gKFxpdEQwYGk7lTC/hukTgNtaoAstBXehnZNk4k3kuU6+86WDrkn18Cd949iNqfIPtIG/wIsFNGbkHsH69hQ==} + cpu: [x64] + os: [linux] + + '@rspack/binding-wasm32-wasi@1.6.7': + resolution: {integrity: sha512-yx88EFdE9RP3hh7VhjjW6uc6wGU0KcpOcZp8T8E/a+X8L98fX0aVrtM1IDbndhmdluIMqGbfJNap2+QqOCY9Mw==} + cpu: [wasm32] + + '@rspack/binding-win32-arm64-msvc@1.6.7': + resolution: {integrity: sha512-vgxVYpFK8P5ulSXQQA+EbX78R/SUU+WIf0JIY+LoUoP89gZOsise/lKAJMAybzpeTJ1t0ndLchFznDYnzq+l4Q==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.6.7': + resolution: {integrity: sha512-bV5RTW0Va0UQKJm9HWLt7fWNBPaBBBxCJOA2pJT3nGGm6CCXKnZSyEiVbFUk4jI/uiwBfqenlLkzaGoMRbeDhA==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.6.7': + resolution: {integrity: sha512-8xlbuJQtYktlBjZupOHlO8FeZqSIhsV3ih7xBSiOYar6LI6uQzA7XiO3I5kaPSDirBMMMKv1Z4rKCxWx10a3TQ==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.6.7': + resolution: {integrity: sha512-7ICabuBN3gHc6PPN52+m1kruz3ogiJjg1C0gSWdLRk18m/4jlcM2aAy6wfXjgODJdB0Yh2ro/lIpBbj+AYWUGA==} + + '@rspack/cli@1.6.7': + resolution: {integrity: sha512-lWU4Gfw3HIysXnBuN1Ta43BeQHewoHd3MAzRlxmEYsUPxau26h6oTpL5WnLsT/Eh4G7XqnW1NJ8COujnn9EGfg==} + hasBin: true + peerDependencies: + '@rspack/core': ^1.0.0-alpha || ^1.x + + '@rspack/core@1.6.7': + resolution: {integrity: sha512-tkd4nSzTf+pDa9OAE4INi/JEa93HNszjWy5C9+trf4ZCXLLHsHxHQFbzoreuz4Vv2PlCWajgvAdiPMV1vGIkuw==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/dev-server@1.1.4': + resolution: {integrity: sha512-kGHYX2jYf3ZiHwVl0aUEPBOBEIG1aWleCDCAi+Jg32KUu3qr/zDUpCEd0wPuHfLEgk0X0xAEYCS6JMO7nBStNQ==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': '*' + + '@rspack/lite-tapable@1.1.0': + resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -1157,99 +1521,16 @@ packages: resolution: {integrity: sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==} engines: {node: '>=20.0.0'} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sindresorhus/base62@1.0.0': + resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} + engines: {node: '>=18'} '@sindresorhus/merge-streams@2.3.0': resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - - '@swc/core-darwin-arm64@1.11.18': - resolution: {integrity: sha512-K6AntdUlNMQg8aChqjeXwnVhK6d4WRZ9TgtLSTmdU0Ugll4an7QK49s9NrT7XQU91cEsVvzdr++p1bNImx0hJg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - - '@swc/core-darwin-x64@1.11.18': - resolution: {integrity: sha512-RCRvC6Q9M5BArTvj/IzUAAYGrgxYFbTTnAtf6UX7JFq2DAn+hEwYUjmC1m0gFso9HqFU0m5QZUGfZvVmACGWUw==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - - '@swc/core-linux-arm-gnueabihf@1.11.18': - resolution: {integrity: sha512-wteAKf8YKb3jOnZFm3EzuIMzzCVXMuQOLHsz1IgEOc44/gdgNXKxaYTWAowZuej7t68tf/w0cRNMc7Le414v/g==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.11.18': - resolution: {integrity: sha512-hY6jJYZ6PKHSBo5OATswfyKsUgsWu9+4nDcN8liYIRRgz3E0G9wk0VUTP4cFPivBFeHWTTAGz687/Nf2aQEIpw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-arm64-musl@1.11.18': - resolution: {integrity: sha512-slu0mlP2nucvQalttnapfpqpD/LlM9NHx9g3ofgsLzjObyMEBiX4ZysQ3y65U8Mjw71RNqtLd/ZmvxI6OmLdiQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-x64-gnu@1.11.18': - resolution: {integrity: sha512-h9a/8PA25arMCQ9t8CE8rA1s0c77z4kCZZ7dUuUkD88yEXIrARMca1IKR7of+S3slfQrf1Zlq3Ac1Fb1HVJziQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-linux-x64-musl@1.11.18': - resolution: {integrity: sha512-0sMDJj5qUGK9QEw4lrxLxkTP/4AoKciqNzXvqbk+J9XuXN2aIv4BsR1Y7z3GwAeMFGsba2lbHLOtJlDsaqIsiA==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-win32-arm64-msvc@1.11.18': - resolution: {integrity: sha512-zGv9HnfgBcKyt54MJRWdwRNu9BuYkAFM7bx+tWtKhd37Ef7ZX20QLs9xXl5wWDXCbsOdRxXIZgXs6PEL+Pzmrw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@swc/core-win32-ia32-msvc@1.11.18': - resolution: {integrity: sha512-uBKj0S1lYv/E2ZhxHZOxSiQwoegYmzbPRpjq6eHBZDv97mu7W3K27/lsnPbvAfQ6b6rnv8BI+EsmJ7VLQBAHBQ==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - - '@swc/core-win32-x64-msvc@1.11.18': - resolution: {integrity: sha512-8USTRcdgeFMNBgvVXl8tz6n4+9s9m+zHsfDeBT4jPgwnq2bnLBlTUlwnPwzDxfg9nUJr6RFD4xeKfWyZZRosZg==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@swc/core@1.11.18': - resolution: {integrity: sha512-ORZxyCKKiqYt2iHdh1C7pfVR1GBjkuFOdwqZggQzaq0vt22DpGca+2JsUtkUoWQmWcct04v5+ScwgvsHuMObxA==} - engines: {node: '>=10'} - peerDependencies: - '@swc/helpers': '*' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/jest@0.2.37': - resolution: {integrity: sha512-CR2BHhmXKGxTiFr21DYPRHQunLkX3mNIFGFkxBGji6r9uyIR5zftTOVYj1e0sFNMV2H7mf/+vpaglqaryBtqfQ==} - engines: {npm: '>= 7.0.0'} - peerDependencies: - '@swc/core': '*' - - '@swc/types@0.1.21': - resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + '@standard-schema/spec@1.0.0': + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} '@textlint/ast-node-types@15.4.0': resolution: {integrity: sha512-IqY8i7IOGuvy05wZxISB7Me1ZyrvhaQGgx6DavfQjH3cfwpPFdDbDYmMXMuSv2xLS1kDB1kYKBV7fL2Vi16lRA==} @@ -1266,50 +1547,47 @@ packages: '@textlint/types@15.4.0': resolution: {integrity: sha512-ZMwJgw/xjxJufOD+IB7I2Enl9Si4Hxo04B76RwUZ5cKBKzOPcmd6WvGe2F7jqdgmTdGnfMU+Bo/joQrjPNIWqg==} - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.20.7': - resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/fs-extra@11.0.4': - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + '@types/express-serve-static-core@4.19.7': + resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - '@types/jest@29.5.14': - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1320,6 +1598,9 @@ packages: '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/katex@0.16.7': + resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} + '@types/linkify-it@5.0.0': resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} @@ -1332,14 +1613,20 @@ packages: '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@18.19.86': - resolution: {integrity: sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ==} + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} - '@types/node@20.17.30': - resolution: {integrity: sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==} + '@types/node@20.19.26': + resolution: {integrity: sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==} + + '@types/node@24.10.2': + resolution: {integrity: sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1347,17 +1634,41 @@ packages: '@types/plist@3.0.5': resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@types/sarif@2.1.7': resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} - '@types/semver@7.5.0': - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} - '@types/stack-utils@2.0.3': - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1365,69 +1676,70 @@ packages: '@types/vscode@1.99.0': resolution: {integrity: sha512-30sjmas1hQ0gVbX68LAWlm/YYlEqUErunPJJKLpEl+xhK0mKn+jyzlCOpsdTwfkZfPy4U6CDkmygBLC3AB8W9Q==} - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.33': - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@typescript-eslint/eslint-plugin@6.21.0': - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@6.21.0': - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@6.21.0': - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/types@8.49.0': + resolution: {integrity: sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/utils@6.21.0': - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} + engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -1437,6 +1749,44 @@ packages: peerDependencies: valibot: ^1.1.0 + '@vitest/coverage-v8@4.0.15': + resolution: {integrity: sha512-FUJ+1RkpTFW7rQITdgTi93qOCWJobWhBirEPCeXh2SW2wsTlFxy51apDz5gzG+ZEYt/THvWeNmhdAoS9DTwpCw==} + peerDependencies: + '@vitest/browser': 4.0.15 + vitest: 4.0.15 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@4.0.15': + resolution: {integrity: sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==} + + '@vitest/mocker@4.0.15': + resolution: {integrity: sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.15': + resolution: {integrity: sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==} + + '@vitest/runner@4.0.15': + resolution: {integrity: sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==} + + '@vitest/snapshot@4.0.15': + resolution: {integrity: sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==} + + '@vitest/spy@4.0.15': + resolution: {integrity: sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==} + + '@vitest/utils@4.0.15': + resolution: {integrity: sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==} + '@vscode/vsce-sign-alpine-arm64@2.0.2': resolution: {integrity: sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==} cpu: [arm64] @@ -1485,11 +1835,6 @@ packages: '@vscode/vsce-sign@2.0.5': resolution: {integrity: sha512-GfYWrsT/vypTMDMgWDm75iDmAOMe7F71sZECJ+Ws6/xyIfmB3ELVnVN+LwMFAvmXY+e6eWhR2EzNGF/zAhWY3Q==} - '@vscode/vsce@2.32.0': - resolution: {integrity: sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==} - engines: {node: '>= 16'} - hasBin: true - '@vscode/vsce@3.7.1': resolution: {integrity: sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g==} engines: {node: '>= 20'} @@ -1499,6 +1844,10 @@ packages: resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} engines: {node: '>=10.0.0'} + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1508,8 +1857,8 @@ packages: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1517,6 +1866,19 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1527,36 +1889,29 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.0.0: - resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + ansi-escapes@7.2.0: + resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} engines: {node: '>=18'} - ansi-regex@4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - 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==} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} anymatch@3.1.3: @@ -1567,9 +1922,6 @@ packages: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1580,8 +1932,11 @@ packages: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} engines: {node: '>= 0.4'} array-union@2.1.0: @@ -1604,6 +1959,13 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-v8-to-istanbul@0.3.8: + resolution: {integrity: sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==} + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -1612,9 +1974,6 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -1625,31 +1984,6 @@ packages: azure-devops-node-api@12.5.0: resolution: {integrity: sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==} - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -1659,6 +1993,9 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1673,6 +2010,13 @@ packages: bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + body-parser@1.20.4: + resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -1682,45 +2026,30 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} 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 - - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1741,44 +2070,35 @@ packages: resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} engines: {node: '>=12'} - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001712: - resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} - catharsis@0.9.0: resolution: {integrity: sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==} engines: {node: '>= 10'} - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chai@6.2.1: + resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} + engines: {node: '>=18'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -1786,72 +2106,48 @@ packages: resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} engines: {node: '>=18.17'} - chokidar-cli@3.0.0: - resolution: {integrity: sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==} - engines: {node: '>= 8.10.0'} - hasBin: true - chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} engines: {node: '>=8'} - cjs-module-lexer@1.4.3: - resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} - cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + cli-truncate@5.1.1: + resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} + engines: {node: '>=20'} cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - cliui@5.0.0: - resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - cockatiel@3.2.1: resolution: {integrity: sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==} engines: {node: '>=16'} - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -1860,24 +2156,12 @@ packages: combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - commander@11.0.0: - resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==} - engines: {node: '>=16'} - - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} + engines: {node: '>= 0.8'} commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} - commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} - commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -1886,34 +2170,61 @@ packages: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - concurrently@8.2.2: - resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} - engines: {node: ^14.13.0 || >=16.0.0} - hasBin: true - confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} core-js-pure@3.46.0: resolution: {integrity: sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==} - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-env@10.1.0: + resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==} + engines: {node: '>=20'} + hasBin: true cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} @@ -1938,25 +2249,23 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} debounce@3.0.0: resolution: {integrity: sha512-64byRbF0/AirwbuHqB3/ZpMG9/nckDa6ZA0yd6UnaQNwbbemCOwvz2sL5sjXLHhZHADyiwLm0M5qMhltUUx+TA==} engines: {node: '>=20'} - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} 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'} + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -1972,25 +2281,13 @@ packages: supports-color: optional: true - decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - - decode-named-character-reference@1.1.0: - resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} + decode-named-character-reference@1.2.0: + resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2026,10 +2323,22 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-indent@7.0.2: resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} engines: {node: '>=12.20'} @@ -2038,29 +2347,24 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - detect-newline@4.0.1: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -2086,6 +2390,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2096,23 +2403,11 @@ packages: resolution: {integrity: sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==} engines: {ecmascript: '>= es5', node: '>=4'} - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-to-chromium@1.5.132: - resolution: {integrity: sha512-QgX9EBvWGmvSRa74zqfnG7+Eno0Ak0vftBll0Pt2/z5b3bEGYL6OUXLgKPtvx73dn3dvwrlyVkjPKRRlhLYTEg==} - - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - emoji-regex@7.0.3: - resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2120,6 +2415,14 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + encoding-sniffer@0.2.0: resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} @@ -2130,13 +2433,6 @@ packages: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} - entities@2.1.0: - resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} - - entities@3.0.1: - resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} - engines: {node: '>=0.12'} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -2145,11 +2441,8 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -2160,6 +2453,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + 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'} @@ -2176,28 +2472,18 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild-register@3.6.0: - resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} - peerDependencies: - esbuild: '>=0.12 <1' - - esbuild@0.17.19: - resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} - engines: {node: '>=12'} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} hasBin: true - esbuild@0.25.2: - resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + esbuild@0.27.1: + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} engines: {node: '>=18'} hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} @@ -2224,19 +2510,18 @@ packages: eslint: ^7.32.0 || ^8.2.0 eslint-plugin-import: ^2.25.2 - eslint-config-airbnb-typescript@17.1.0: - resolution: {integrity: sha512-GPxI5URre6dDpJ0CtcthSZVBAfI+Uw7un5OYNVxP2EYi3H81Jw701yFP7AU+/vCE7xBtFmjge7kfhhk4+RAiig==} + eslint-config-airbnb-typescript@18.0.0: + resolution: {integrity: sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==} peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.13.0 || ^6.0.0 - '@typescript-eslint/parser': ^5.0.0 || ^6.0.0 - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.3 + '@typescript-eslint/eslint-plugin': ^7.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-module-utils@2.12.0: - resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -2256,8 +2541,8 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-plugin-boundaries@5.0.1: - resolution: {integrity: sha512-QBw1TgoA3JnD+AQ8EHqZL8LtiFVREnFmD2BnHzVl38UKtRTds8rawIg03ZLwFs/90yKSh+DVVXRpvVK631Z/0w==} + eslint-plugin-boundaries@5.3.1: + resolution: {integrity: sha512-91StsOYtDyrna1fyRJ+1Ps5CnrfyFLbdCouPZ3E/o2cllLxJke3OoScdqjpBSl7pNEYbojhpNlurQAr30sf9Bg==} engines: {node: '>=18.18'} peerDependencies: eslint: '>=6.0.0' @@ -2275,8 +2560,8 @@ packages: peerDependencies: eslint: '>=6.0.0' - eslint-plugin-import@2.31.0: - resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -2285,9 +2570,9 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-jsdoc@46.10.1: - resolution: {integrity: sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==} - engines: {node: '>=16'} + eslint-plugin-jsdoc@61.5.0: + resolution: {integrity: sha512-PR81eOGq4S7diVnV9xzFSBE4CDENRQGP0Lckkek8AdHtbj+6Bm0cItwlFnxsLFriJHspiE3mpu8U20eODyToIg==} + engines: {node: '>=20.11.0'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -2305,12 +2590,20 @@ packages: 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.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2332,10 +2625,20 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + 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'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} @@ -2343,25 +2646,21 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} + exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + engines: {node: '>=12.0.0'} + + express@4.22.1: + resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + engines: {node: '>= 0.10.0'} extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -2388,31 +2687,38 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + find-up-simple@1.0.1: resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} engines: {node: '>=18'} - find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -2452,11 +2758,19 @@ packages: resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - fs-extra@11.3.0: - resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + fs-extra@11.3.2: + resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} engines: {node: '>=14.14'} fs.realpath@1.0.0: @@ -2477,42 +2791,18 @@ packages: 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-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + get-east-asian-width@1.4.0: + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stdin@9.0.0: - resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} - engines: {node: '>=12'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} @@ -2531,28 +2821,25 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.2.7: - resolution: {integrity: sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' glob@11.1.0: resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} hasBin: true + glob@13.0.0: + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported - glob@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -2589,14 +2876,22 @@ packages: graphemesplit@2.6.0: resolution: {integrity: sha512-rG9w2wAfkpg0DILa1pjnjNfucng3usON360shisqIMUBw/87pojcBSrHmeE4UwryAuBih7g8m1oilf5/u8EWdQ==} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -2628,33 +2923,70 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} htmlparser2@9.1.0: resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} hasBin: true + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2662,10 +2994,6 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2678,11 +3006,6 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2699,15 +3022,18 @@ packages: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - ini@3.0.1: - resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} @@ -2717,13 +3043,24 @@ packages: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} engines: {node: '>=8'} + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.3.0: + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} + engines: {node: '>= 10'} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -2740,10 +3077,6 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -2764,6 +3097,9 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2777,26 +3113,14 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} - is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -2805,6 +3129,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -2814,10 +3141,22 @@ packages: resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==} engines: {node: '>=8'} + is-it-type@5.1.3: + resolution: {integrity: sha512-AX2uU0HW+TxagTgQXOJY7+2fbFHemC7YFBwN1XqD8qQMKdtfbOC8OC3fUb4s5NU59a3662Dzwto8tWDdZYRXxg==} + engines: {node: '>=12'} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-network-error@1.3.0: + resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} + engines: {node: '>=16'} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -2830,6 +3169,10 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -2850,14 +3193,6 @@ packages: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -2883,188 +3218,45 @@ packages: engines: {node: '>= 0.4'} is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - - istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - - istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - - istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - - istextorbinary@9.5.0: - resolution: {integrity: sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==} - engines: {node: '>=4'} - - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - - jackspeak@4.1.1: - resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} - engines: {node: 20 || >=22} - - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + istextorbinary@9.5.0: + resolution: {integrity: sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==} + engines: {node: '>=4'} - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} js-base64@3.7.8: resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} @@ -3072,37 +3264,32 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true js2xmlparser@4.0.2: resolution: {integrity: sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==} - jsdoc-type-pratt-parser@4.0.0: - resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} - engines: {node: '>=12.0.0'} + jsdoc-type-pratt-parser@6.10.0: + resolution: {integrity: sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==} + engines: {node: '>=20.0.0'} - jsdoc@4.0.4: - resolution: {integrity: sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==} + jsdoc@4.0.5: + resolution: {integrity: sha512-P4C6MWP9yIlMiK8nwoZvxN84vb6MsnXcHuy7XzVOvQoCizWX5JFCBsWIIWKXBltpoRZXddUOVQmCTOZt9yDj9g==} engines: {node: '>=12.0.0'} 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-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -3121,15 +3308,16 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} - jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -3146,6 +3334,10 @@ packages: jws@4.0.0: resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + katex@0.16.27: + resolution: {integrity: sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==} + hasBin: true + keytar@7.9.0: resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} @@ -3159,9 +3351,8 @@ packages: klaw@3.0.0: resolution: {integrity: sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==} - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} + launch-editor@2.12.0: + resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==} leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} @@ -3171,39 +3362,22 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - linkify-it@3.0.3: - resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} - - linkify-it@4.0.1: - resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} - linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - lint-staged@15.5.0: - resolution: {integrity: sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg==} - engines: {node: '>=18.12.0'} + lint-staged@16.2.7: + resolution: {integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==} + engines: {node: '>=20.17'} hasBin: true - listr2@8.2.5: - resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} - engines: {node: '>=18.0.0'} + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} - locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -3212,9 +3386,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -3233,18 +3404,12 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash.throttle@4.1.1: - resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} - lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -3265,23 +3430,20 @@ packages: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} - 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'} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.1: + resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - map-obj@4.3.0: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} @@ -3292,38 +3454,22 @@ packages: '@types/markdown-it': '*' markdown-it: '*' - markdown-it@12.3.2: - resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} - hasBin: true - - markdown-it@13.0.1: - resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} - hasBin: true - markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true - markdownlint-cli@0.35.0: - resolution: {integrity: sha512-lVIIIV1MrUtjoocgDqXLxUCxlRbn7Ve8rsWppfwciUNwLlNS28AhNiyQ3PU7jjj4Qvj+rWTTvwkqg7AcdG988g==} - engines: {node: '>=16'} + markdownlint-cli@0.46.0: + resolution: {integrity: sha512-4gxTNzPjpLnY7ftrEZD4flPY0QBkQLiqezb6KURFSkV+vPHFOsYw8OMtY6fu82Yt8ghtSrWegpYdq1ix25VFLQ==} + engines: {node: '>=20'} hasBin: true - markdownlint-micromark@0.1.5: - resolution: {integrity: sha512-HvofNU4QCvfUCWnocQP1IAWaqop5wpWrB0mKB6SSh0fcpV0PdmQNS6tdUuFew1utpYlUvYYzz84oDkrD76GB9A==} - engines: {node: '>=16'} - - markdownlint-micromark@0.1.7: - resolution: {integrity: sha512-BbRPTC72fl5vlSKv37v/xIENSRDYL/7X/XoFzZ740FGEbs9vZerLrIkFRY0rv7slQKxDczToYuMmqQFN61fi4Q==} - engines: {node: '>=16'} - - markdownlint@0.29.0: - resolution: {integrity: sha512-ASAzqpODstu/Qsk0xW5BPgWnK/qjpBQ4e7IpsSvvFXcfYIjanLTdwFRJK1SIEEh0fGSMKXcJf/qhaZYHyME0wA==} - engines: {node: '>=16'} + markdownlint@0.39.0: + resolution: {integrity: sha512-Xt/oY7bAiHwukL1iru2np5LIkhwD19Y7frlsiDILK62v3jucXCD6JXlZlwMG12HZOR+roHIVuJZrfCkOhp6k3g==} + engines: {node: '>=20'} - markdownlint@0.30.0: - resolution: {integrity: sha512-nInuFvI/rEzanAOArW5490Ez4EYpB5ODqVM0mcDYCPx9DKJWCQqCgejjiCvbSeE7sjbDscVtZmwr665qpF5xGA==} - engines: {node: '>=16'} + markdownlint@0.40.0: + resolution: {integrity: sha512-UKybllYNheWac61Ia7T6fzuQNDZimFIpCg2w6hHjgV1Qu0w1TV0LlSgryUGzM0bkKQCBhy2FDhEELB73Kb0kAg==} + engines: {node: '>=20'} marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} @@ -3352,22 +3498,45 @@ packages: mdn-data@2.23.0: resolution: {integrity: sha512-786vq1+4079JSeu2XdcDjrhi/Ry7BWtjDl9WtGPWLiIHb2T66GvIVflZTBoSNZ5JqTtJGYEVMuFA/lbQlMOyDQ==} - mdurl@1.0.1: - resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@4.51.1: + resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + micromark-extension-directive@4.0.0: + resolution: {integrity: sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-math@3.1.0: + resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} + micromark-factory-destination@2.0.1: resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} @@ -3440,23 +3609,23 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -3465,6 +3634,9 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + minimatch@10.1.1: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} @@ -3472,18 +3644,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} - - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -3491,14 +3651,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - - minipass@6.0.2: - resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==} - engines: {node: '>=16 || 14 >=14.17'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -3516,9 +3668,20 @@ packages: engines: {node: '>=10'} hasBin: true + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -3530,12 +3693,32 @@ packages: resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} engines: {node: ^20.17.0 || >=22.9.0} + nano-spawn@2.0.0: + resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} + engines: {node: '>=20.17'} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + node-abi@3.74.0: resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} engines: {node: '>=10'} @@ -3543,11 +3726,9 @@ packages: node-addon-api@4.3.0: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-forge@1.3.3: + resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} + engines: {node: '>= 6.13.0'} node-sarif-builder@3.3.1: resolution: {integrity: sha512-8z5dAbhpxmk/WRQHXlv4V0h+9Y4Ugk+w08lyhV/7E/CQX9yDdBc3025/EG+RSMJU2aPFh/IQ7XDV7Ti5TLt/TA==} @@ -3561,17 +3742,12 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-deep-merge@2.0.0: + resolution: {integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -3600,19 +3776,25 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} @@ -3622,13 +3804,17 @@ packages: resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} engines: {node: '>=18'} + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - ovsx@0.8.4: - resolution: {integrity: sha512-RMtGSVNM4NWSF9uVWCUqaYiA7ID8Vqm/rSk2W37eYVrDLOI/3do2IRY7rQYkvJqb6sS6LAnALODBkD50tIM1kw==} - engines: {node: '>= 14'} + ovsx@0.10.7: + resolution: {integrity: sha512-UjBQlB5xSDD+biAylCZ8Q/k3An9K3y9FYa+hT/HTbJkzOQP+gaNHX20CaOo4lrYT1iJXdiePH9zS2uvCXdDNDA==} + engines: {node: '>= 20'} hasBin: true own-keys@1.0.1: @@ -3643,10 +3829,6 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -3659,6 +3841,10 @@ packages: resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -3673,9 +3859,11 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + + parse-imports-exports@0.2.4: + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} parse-json@8.3.0: resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} @@ -3684,6 +3872,9 @@ packages: parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} + parse-statements@1.0.11: + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} + parse5-htmlparser2-tree-adapter@7.1.0: resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} @@ -3693,9 +3884,9 @@ packages: parse5@7.2.1: resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -3709,21 +3900,16 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - 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'} - path-scurry@2.0.1: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -3732,6 +3918,9 @@ packages: resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} engines: {node: '>=18'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -3755,10 +3944,6 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - piscina@5.1.3: resolution: {integrity: sha512-0u3N7H4+hbr40KjuVn2uNhOcthu/9usKhnw5vT3J7ply79v3D3M8naI00el9Klcy16x557VsEkkUQaHCWFXC/g==} engines: {node: '>=20.x'} @@ -3782,6 +3967,10 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} @@ -3795,13 +3984,12 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -3814,9 +4002,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - qs@6.14.0: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} @@ -3828,6 +4013,14 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + rc-config-loader@4.1.3: resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} @@ -3835,9 +4028,6 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - read-pkg@9.0.1: resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} engines: {node: '>=18'} @@ -3846,6 +4036,9 @@ packages: resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} engines: {node: '>=0.8'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -3854,13 +4047,14 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - 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'} @@ -3874,44 +4068,27 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} requizzle@0.2.4: resolution: {integrity: sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==} - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} + reserved-identifiers@1.2.0: + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -3921,6 +4098,10 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -3933,29 +4114,34 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@4.4.1: - resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} - engines: {node: '>=14'} + rimraf@6.1.2: + resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + engines: {node: 20 || >=22} + hasBin: true + + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} - run-con@1.2.12: - resolution: {integrity: sha512-5257ILMYIF4RztL9uoZ7V9Q97zHtNHn5bN3NobeAnzB1P3ASLgg8qocM2u+R18ttp+VEM78N2LK8XcNVtnSRrg==} + run-con@1.3.2: + resolution: {integrity: sha512-CcfE+mYiTcKEzg0IqS08+efdnH0oJ3zV0wSUFBNrMHMuxCtXvBCLzCJHatwuXDcu/RlhjTziTo/a1ruQik6/Yg==} hasBin: true run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.2: - resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - safe-array-concat@1.1.3: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -3973,11 +4159,22 @@ packages: sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + secretlint@10.2.2: resolution: {integrity: sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==} engines: {node: '>=20.0.0'} hasBin: true + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -3986,18 +4183,26 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + send@0.19.1: + resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} + engines: {node: '>= 0.8.0'} + + serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -4011,6 +4216,12 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} + setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -4023,8 +4234,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shell-quote@1.8.2: - resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} side-channel-list@1.0.0: @@ -4043,8 +4254,8 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -4056,8 +4267,13 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + simple-invariant@2.0.1: + resolution: {integrity: sha512-1sbhsxqI+I2tqlmjbz99GXNmZtr6tKIyEgGGnJw/MKGblalqk/XoOYYFJlBzTKZCxx8kLaD3FD5s9BEEjx5Pyg==} + engines: {node: '>=10'} + + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -4071,28 +4287,25 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - - slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} + smol-toml@1.5.2: + resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==} + engines: {node: '>= 18'} + + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - spawn-command@0.0.2: - resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} - spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -4105,8 +4318,15 @@ packages: spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - spdx-license-ids@3.0.21: - resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + spdx-license-ids@3.0.22: + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -4114,9 +4334,27 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} @@ -4126,14 +4364,6 @@ packages: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - - string-width@3.1.0: - resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} - engines: {node: '>=6'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -4146,6 +4376,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.1.0: + resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==} + engines: {node: '>=20'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -4158,37 +4392,24 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -4200,18 +4421,10 @@ packages: structured-source@4.0.0: resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==} - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - 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-hyperlinks@2.3.0: resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} engines: {node: '>=8'} @@ -4247,10 +4460,6 @@ packages: resolution: {integrity: sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==} engines: {node: '>=18'} - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -4258,9 +4467,33 @@ packages: resolution: {integrity: sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==} engines: {node: '>=4'} + thingies@2.5.0: + resolution: {integrity: sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + tldts-core@5.7.112: resolution: {integrity: sha512-mutrEUgG2sp0e/MIAnv9TbSLR0IPbvmAImpzqul5O/HJ2XM1/I1sajchQ/fbj0fPdA31IiuWde8EUhfwyldY1Q==} @@ -4272,16 +4505,27 @@ packages: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true + to-valid-identifier@1.0.0: + resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} + engines: {node: '>=20'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} @@ -4297,43 +4541,11 @@ packages: peerDependencies: typescript: '>=4.0.0' - ts-jest@29.3.1: - resolution: {integrity: sha512-FT2PIRtZABwl6+ZCry8IY7JZ3xMuppsEV9qFVHOVe8jDzggwUZ9TsM4chyJxL9yi6LvkqcZYU3LmapEE454zBQ==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + tsc-files@1.1.4: + resolution: {integrity: sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==} hasBin: true peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + typescript: '>=3' tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -4341,8 +4553,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.19.3: - resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} hasBin: true @@ -4357,10 +4569,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -4377,6 +4585,10 @@ packages: resolution: {integrity: sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==} engines: {node: '>=16'} + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -4396,17 +4608,19 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true - uc.micro@1.0.6: - resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} - uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -4414,11 +4628,11 @@ packages: underscore@1.13.7: resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} undici@6.21.2: resolution: {integrity: sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==} @@ -4454,11 +4668,9 @@ packages: 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' + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -4469,19 +4681,16 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - - valibot@1.1.0: - resolution: {integrity: sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw==} + valibot@1.2.0: + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -4491,6 +4700,10 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + version-range@4.15.0: resolution: {integrity: sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==} engines: {node: '>=4'} @@ -4501,6 +4714,80 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + vite@7.2.6: + resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + 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@4.0.15: + resolution: {integrity: sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.15 + '@vitest/browser-preview': 4.0.15 + '@vitest/browser-webdriverio': 4.0.15 + '@vitest/ui': 4.0.15 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vscode-jsonrpc@9.0.0-next.8: resolution: {integrity: sha512-pN6L5eiNBvUpNFBJvudaZ83klir0T/wLFCDpYhpOEsKXyhsWyYsNMzoG7BK6zJoZLHGSSsaTJDjCcPwnLgUyPQ==} engines: {node: '>=14.0.0'} @@ -4525,14 +4812,49 @@ packages: vscode-oniguruma@2.0.1: resolution: {integrity: sha512-poJU8iHIWnC3vgphJnrLZyI3YdqRlR27xzqDmpPXYzA93R4Gk8z7T6oqDzDoHjoikA2aS82crdXFkjELCdJsjQ==} - vscode-textmate@9.2.0: - resolution: {integrity: sha512-rkvG4SraZQaPSN/5XjwKswdU0OP9MF28QjrYzUBbhb8QyG3ljB1Ky996m++jiI7KdiAP2CkBiQZd9pqEDTClqA==} + vscode-textmate@9.3.0: + resolution: {integrity: sha512-zHiZZOdb9xqj5/X1C4a29sbgT2HngdWxPLSl3PyHRQF+5visI4uNM020OHiLJjsMxUssyk/pGVAg/9LCIobrVg==} vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + + webpack-bundle-analyzer@4.10.2: + resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==} + engines: {node: '>= 10.13.0'} + hasBin: true + + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.2.2: + resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + engines: {node: '>= 18.12.0'} + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} @@ -4554,9 +4876,6 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-pm@3.0.1: resolution: {integrity: sha512-v2JrMq0waAI4ju1xU5x3blsxBBMgdgZve580iYMN5frDaLGjbA24fok7wKCsya8KLVO19Ju4XDc5+zTZCJkQfg==} engines: {node: '>=18.12'} @@ -4570,13 +4889,17 @@ packages: 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@5.1.0: - resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} - engines: {node: '>=6'} + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} @@ -4590,10 +4913,6 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} - wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -4601,9 +4920,29 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + 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 xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} @@ -4623,42 +4962,17 @@ packages: xregexp@5.1.2: resolution: {integrity: sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==} - y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.7.1: - resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} - engines: {node: '>= 14'} - hasBin: true - - yaml@2.8.1: - resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} hasBin: true - yargs-parser@13.1.2: - resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@13.3.2: - resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yauzl-promise@4.0.0: + resolution: {integrity: sha512-/HCXpyHXJQQHvFq9noqrjfa/WpQC2XYs3vI7tBiAi4QiIU1knvYhZGaO1QPjwIVMdqflxbmwgMXtYeaRiAE0CA==} + engines: {node: '>=16'} yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} @@ -4666,10 +4980,6 @@ packages: yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -4689,14 +4999,14 @@ packages: snapshots: - '@adguard/aglint@4.0.0-beta.1(@types/node@20.17.30)(typescript@5.9.2)': + '@adguard/aglint@4.0.0-beta.3(@types/node@24.10.2)(typescript@5.9.3)': dependencies: '@adguard/agtree': 3.4.1 '@adguard/ecss-tree': 2.0.1 - '@inquirer/checkbox': 4.3.0(@types/node@20.17.30) - '@inquirer/confirm': 6.0.1(@types/node@20.17.30) - '@inquirer/select': 4.4.0(@types/node@20.17.30) - '@valibot/to-json-schema': 1.3.0(valibot@1.1.0(typescript@5.9.2)) + '@inquirer/checkbox': 4.3.0(@types/node@24.10.2) + '@inquirer/confirm': 6.0.1(@types/node@24.10.2) + '@inquirer/select': 4.4.0(@types/node@24.10.2) + '@valibot/to-json-schema': 1.3.0(valibot@1.2.0(typescript@5.9.3)) chalk: 5.6.2 clone-deep: 4.0.1 commander: 14.0.2 @@ -4711,13 +5021,14 @@ snapshots: inflection: 2.0.1 is-glob: 4.0.3 micromustache: 8.0.3 + object-inspect: 1.13.4 ohash: 2.0.11 piscina: 5.1.3 strip-ansi: 6.0.1 terminal-link: 2.1.1 text-table: 0.2.0 - valibot: 1.1.0(typescript@5.9.2) - yaml: 2.8.1 + valibot: 1.2.0(typescript@5.9.3) + yaml: 2.8.2 transitivePeerDependencies: - '@types/node' - typescript @@ -4728,7 +5039,7 @@ snapshots: clone-deep: 4.0.1 is-ip: 3.1.0 json5: 2.2.3 - semver: 7.7.1 + semver: 7.7.3 sprintf-js: 1.1.3 tldts: 5.7.112 zod: 3.21.4 @@ -4763,11 +5074,6 @@ snapshots: '@adguard/css-tokenizer': 1.2.0 '@eslint/css-tree': 3.6.6 - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - '@azu/format-text@1.0.2': {} '@azu/style-format@1.0.1': @@ -4857,348 +5163,227 @@ snapshots: '@babel/code-frame@7.26.2': dependencies: - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.8': {} + '@babel/helper-string-parser@7.27.1': {} - '@babel/core@7.26.10': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.27.0 - '@babel/helper-compilation-targets': 7.27.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) - '@babel/helpers': 7.27.0 - '@babel/parser': 7.27.0 - '@babel/template': 7.27.0 - '@babel/traverse': 7.27.0 - '@babel/types': 7.27.0 - 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/helper-validator-identifier@7.28.5': {} - '@babel/generator@7.27.0': + '@babel/parser@7.28.5': dependencies: - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.1.0 + '@babel/types': 7.28.5 - '@babel/helper-compilation-targets@7.27.0': + '@babel/runtime-corejs3@7.28.4': dependencies: - '@babel/compat-data': 7.26.8 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.4 - lru-cache: 5.1.1 - semver: 6.3.1 + core-js-pure: 3.46.0 - '@babel/helper-module-imports@7.25.9': + '@babel/types@7.28.5': dependencies: - '@babel/traverse': 7.27.0 - '@babel/types': 7.27.0 - transitivePeerDependencies: - - supports-color + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bcoe/v8-coverage@1.0.2': {} - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': + '@boundaries/elements@1.1.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.27.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + handlebars: 4.7.8 + is-core-module: 2.16.1 + micromatch: 4.0.8 transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack - supports-color - '@babel/helper-plugin-utils@7.26.5': {} - - '@babel/helper-string-parser@7.25.9': {} - - '@babel/helper-validator-identifier@7.25.9': {} - - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.27.0': - dependencies: - '@babel/template': 7.27.0 - '@babel/types': 7.27.0 - - '@babel/parser@7.27.0': - dependencies: - '@babel/types': 7.27.0 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + '@discoveryjs/json-ext@0.5.7': {} - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.10)': + '@emnapi/core@1.7.1': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.10)': + '@emnapi/runtime@1.7.1': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + tslib: 2.8.1 + optional: true - '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': + '@emnapi/wasi-threads@1.1.0': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + tslib: 2.8.1 + optional: true - '@babel/runtime-corejs3@7.28.4': - dependencies: - core-js-pure: 3.46.0 + '@epic-web/invariant@1.0.0': {} - '@babel/runtime@7.27.0': + '@es-joy/jsdoccomment@0.76.0': dependencies: - regenerator-runtime: 0.14.1 + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.49.0 + comment-parser: 1.4.1 + esquery: 1.6.0 + jsdoc-type-pratt-parser: 6.10.0 - '@babel/template@7.27.0': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 + '@es-joy/resolve.exports@1.2.0': {} - '@babel/traverse@7.27.0': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.27.0 - '@babel/parser': 7.27.0 - '@babel/template': 7.27.0 - '@babel/types': 7.27.0 - debug: 4.4.0 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color + '@esbuild/aix-ppc64@0.25.12': + optional: true - '@babel/types@7.27.0': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 + '@esbuild/aix-ppc64@0.27.1': + optional: true - '@bcoe/v8-coverage@0.2.3': {} + '@esbuild/android-arm64@0.25.12': + optional: true - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 + '@esbuild/android-arm64@0.27.1': + optional: true - '@es-joy/jsdoccomment@0.41.0': - dependencies: - comment-parser: 1.4.1 - esquery: 1.6.0 - jsdoc-type-pratt-parser: 4.0.0 + '@esbuild/android-arm@0.25.12': + optional: true - '@esbuild/aix-ppc64@0.25.2': + '@esbuild/android-arm@0.27.1': optional: true - '@esbuild/android-arm64@0.17.19': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.2': + '@esbuild/android-x64@0.27.1': optional: true - '@esbuild/android-arm@0.17.19': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.25.2': + '@esbuild/darwin-arm64@0.27.1': optional: true - '@esbuild/android-x64@0.17.19': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/android-x64@0.25.2': + '@esbuild/darwin-x64@0.27.1': optional: true - '@esbuild/darwin-arm64@0.17.19': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.25.2': + '@esbuild/freebsd-arm64@0.27.1': optional: true - '@esbuild/darwin-x64@0.17.19': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.25.2': + '@esbuild/freebsd-x64@0.27.1': optional: true - '@esbuild/freebsd-arm64@0.17.19': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.25.2': + '@esbuild/linux-arm64@0.27.1': optional: true - '@esbuild/freebsd-x64@0.17.19': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/freebsd-x64@0.25.2': + '@esbuild/linux-arm@0.27.1': optional: true - '@esbuild/linux-arm64@0.17.19': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-arm64@0.25.2': + '@esbuild/linux-ia32@0.27.1': optional: true - '@esbuild/linux-arm@0.17.19': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-arm@0.25.2': + '@esbuild/linux-loong64@0.27.1': optional: true - '@esbuild/linux-ia32@0.17.19': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ia32@0.25.2': + '@esbuild/linux-mips64el@0.27.1': optional: true - '@esbuild/linux-loong64@0.17.19': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-loong64@0.25.2': + '@esbuild/linux-ppc64@0.27.1': optional: true - '@esbuild/linux-mips64el@0.17.19': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.25.2': + '@esbuild/linux-riscv64@0.27.1': optional: true - '@esbuild/linux-ppc64@0.17.19': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-ppc64@0.25.2': + '@esbuild/linux-s390x@0.27.1': optional: true - '@esbuild/linux-riscv64@0.17.19': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.25.2': + '@esbuild/linux-x64@0.27.1': optional: true - '@esbuild/linux-s390x@0.17.19': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/linux-s390x@0.25.2': + '@esbuild/netbsd-arm64@0.27.1': optional: true - '@esbuild/linux-x64@0.17.19': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.25.2': + '@esbuild/netbsd-x64@0.27.1': optional: true - '@esbuild/netbsd-arm64@0.25.2': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.17.19': + '@esbuild/openbsd-arm64@0.27.1': optional: true - '@esbuild/netbsd-x64@0.25.2': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.2': + '@esbuild/openbsd-x64@0.27.1': optional: true - '@esbuild/openbsd-x64@0.17.19': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.25.2': + '@esbuild/openharmony-arm64@0.27.1': optional: true - '@esbuild/sunos-x64@0.17.19': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.25.2': + '@esbuild/sunos-x64@0.27.1': optional: true - '@esbuild/win32-arm64@0.17.19': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.25.2': + '@esbuild/win32-arm64@0.27.1': optional: true - '@esbuild/win32-ia32@0.17.19': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-ia32@0.25.2': + '@esbuild/win32-ia32@0.27.1': optional: true - '@esbuild/win32-x64@0.17.19': + '@esbuild/win32-x64@0.25.12': optional: true - '@esbuild/win32-x64@0.25.2': + '@esbuild/win32-x64@0.27.1': optional: true '@eslint-community/eslint-utils@4.5.1(eslint@8.57.1)': @@ -5216,12 +5401,12 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.3 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -5232,7 +5417,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.0 + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -5245,69 +5430,69 @@ snapshots: '@inquirer/ansi@2.0.1': {} - '@inquirer/checkbox@4.3.0(@types/node@20.17.30)': + '@inquirer/checkbox@4.3.0(@types/node@24.10.2)': dependencies: '@inquirer/ansi': 1.0.1 - '@inquirer/core': 10.3.0(@types/node@20.17.30) + '@inquirer/core': 10.3.0(@types/node@24.10.2) '@inquirer/figures': 1.0.14 - '@inquirer/type': 3.0.9(@types/node@20.17.30) + '@inquirer/type': 3.0.9(@types/node@24.10.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 - '@inquirer/confirm@6.0.1(@types/node@20.17.30)': + '@inquirer/confirm@6.0.1(@types/node@24.10.2)': dependencies: - '@inquirer/core': 11.0.1(@types/node@20.17.30) - '@inquirer/type': 4.0.1(@types/node@20.17.30) + '@inquirer/core': 11.0.1(@types/node@24.10.2) + '@inquirer/type': 4.0.1(@types/node@24.10.2) optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 - '@inquirer/core@10.3.0(@types/node@20.17.30)': + '@inquirer/core@10.3.0(@types/node@24.10.2)': dependencies: '@inquirer/ansi': 1.0.1 '@inquirer/figures': 1.0.14 - '@inquirer/type': 3.0.9(@types/node@20.17.30) + '@inquirer/type': 3.0.9(@types/node@24.10.2) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 - '@inquirer/core@11.0.1(@types/node@20.17.30)': + '@inquirer/core@11.0.1(@types/node@24.10.2)': dependencies: '@inquirer/ansi': 2.0.1 '@inquirer/figures': 2.0.1 - '@inquirer/type': 4.0.1(@types/node@20.17.30) + '@inquirer/type': 4.0.1(@types/node@24.10.2) cli-width: 4.1.0 mute-stream: 3.0.0 signal-exit: 4.1.0 wrap-ansi: 9.0.2 optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 '@inquirer/figures@1.0.14': {} '@inquirer/figures@2.0.1': {} - '@inquirer/select@4.4.0(@types/node@20.17.30)': + '@inquirer/select@4.4.0(@types/node@24.10.2)': dependencies: '@inquirer/ansi': 1.0.1 - '@inquirer/core': 10.3.0(@types/node@20.17.30) + '@inquirer/core': 10.3.0(@types/node@24.10.2) '@inquirer/figures': 1.0.14 - '@inquirer/type': 3.0.9(@types/node@20.17.30) + '@inquirer/type': 3.0.9(@types/node@24.10.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 - '@inquirer/type@3.0.9(@types/node@20.17.30)': + '@inquirer/type@3.0.9(@types/node@24.10.2)': optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 - '@inquirer/type@4.0.1(@types/node@20.17.30)': + '@inquirer/type@4.0.1(@types/node@24.10.2)': optionalDependencies: - '@types/node': 20.17.30 + '@types/node': 24.10.2 '@isaacs/balanced-match@4.0.1': {} @@ -5319,212 +5504,86 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - - '@istanbuljs/schema@0.1.3': {} - - '@jest/console@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/create-cache-key-function@29.7.0': - dependencies: - '@jest/types': 29.6.3 - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.19.86 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 18.19.86 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color + '@jridgewell/resolve-uri@3.1.2': {} - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 + '@jridgewell/sourcemap-codec@1.5.5': {} - '@jest/source-map@29.6.3': + '@jridgewell/trace-mapping@0.3.31': dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - '@jest/test-result@29.7.0': + '@jsdoc/salty@0.2.9': dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 + lodash: 4.17.21 - '@jest/test-sequencer@29.7.0': + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 + tslib: 2.8.1 - '@jest/transform@29.7.0': + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': dependencies: - '@babel/core': 7.26.10 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.7 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color + tslib: 2.8.1 - '@jest/types@29.6.3': + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 18.19.86 - '@types/yargs': 17.0.33 - chalk: 4.1.2 + tslib: 2.8.1 - '@jridgewell/gen-mapping@0.3.8': + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.5.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 - '@jridgewell/resolve-uri@3.1.2': {} + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 - '@jridgewell/set-array@1.2.1': {} + '@leichtgewicht/ip-codec@2.0.5': {} - '@jridgewell/sourcemap-codec@1.5.0': {} + '@module-federation/error-codes@0.21.6': {} - '@jridgewell/trace-mapping@0.3.25': + '@module-federation/runtime-core@0.21.6': dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@module-federation/error-codes': 0.21.6 + '@module-federation/sdk': 0.21.6 - '@jridgewell/trace-mapping@0.3.9': + '@module-federation/runtime-tools@0.21.6': dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@module-federation/runtime': 0.21.6 + '@module-federation/webpack-bundler-runtime': 0.21.6 - '@jsdoc/salty@0.2.9': + '@module-federation/runtime@0.21.6': dependencies: - lodash: 4.17.21 + '@module-federation/error-codes': 0.21.6 + '@module-federation/runtime-core': 0.21.6 + '@module-federation/sdk': 0.21.6 + + '@module-federation/sdk@0.21.6': {} + + '@module-federation/webpack-bundler-runtime@0.21.6': + dependencies: + '@module-federation/runtime': 0.21.6 + '@module-federation/sdk': 0.21.6 '@napi-rs/nice-android-arm-eabi@1.1.1': optional: true @@ -5598,6 +5657,81 @@ snapshots: '@napi-rs/nice-win32-x64-msvc': 1.1.1 optional: true + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@napi-rs/wasm-runtime@1.0.7': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@node-rs/crc32-android-arm-eabi@1.10.6': + optional: true + + '@node-rs/crc32-android-arm64@1.10.6': + optional: true + + '@node-rs/crc32-darwin-arm64@1.10.6': + optional: true + + '@node-rs/crc32-darwin-x64@1.10.6': + optional: true + + '@node-rs/crc32-freebsd-x64@1.10.6': + optional: true + + '@node-rs/crc32-linux-arm-gnueabihf@1.10.6': + optional: true + + '@node-rs/crc32-linux-arm64-gnu@1.10.6': + optional: true + + '@node-rs/crc32-linux-arm64-musl@1.10.6': + optional: true + + '@node-rs/crc32-linux-x64-gnu@1.10.6': + optional: true + + '@node-rs/crc32-linux-x64-musl@1.10.6': + optional: true + + '@node-rs/crc32-wasm32-wasi@1.10.6': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@node-rs/crc32-win32-arm64-msvc@1.10.6': + optional: true + + '@node-rs/crc32-win32-ia32-msvc@1.10.6': + optional: true + + '@node-rs/crc32-win32-x64-msvc@1.10.6': + optional: true + + '@node-rs/crc32@1.10.6': + optionalDependencies: + '@node-rs/crc32-android-arm-eabi': 1.10.6 + '@node-rs/crc32-android-arm64': 1.10.6 + '@node-rs/crc32-darwin-arm64': 1.10.6 + '@node-rs/crc32-darwin-x64': 1.10.6 + '@node-rs/crc32-freebsd-x64': 1.10.6 + '@node-rs/crc32-linux-arm-gnueabihf': 1.10.6 + '@node-rs/crc32-linux-arm64-gnu': 1.10.6 + '@node-rs/crc32-linux-arm64-musl': 1.10.6 + '@node-rs/crc32-linux-x64-gnu': 1.10.6 + '@node-rs/crc32-linux-x64-musl': 1.10.6 + '@node-rs/crc32-wasm32-wasi': 1.10.6 + '@node-rs/crc32-win32-arm64-msvc': 1.10.6 + '@node-rs/crc32-win32-ia32-msvc': 1.10.6 + '@node-rs/crc32-win32-x64-msvc': 1.10.6 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5610,9 +5744,160 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@pkgjs/parseargs@0.11.0': + '@polka/url@1.0.0-next.29': {} + + '@rollup/rollup-android-arm-eabi@4.53.3': + optional: true + + '@rollup/rollup-android-arm64@4.53.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.53.3': + optional: true + + '@rollup/rollup-darwin-x64@4.53.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.53.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.53.3': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.53.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.53.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.53.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.53.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.53.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.53.3': + optional: true + + '@rspack/binding-darwin-arm64@1.6.7': + optional: true + + '@rspack/binding-darwin-x64@1.6.7': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.6.7': + optional: true + + '@rspack/binding-linux-arm64-musl@1.6.7': + optional: true + + '@rspack/binding-linux-x64-gnu@1.6.7': + optional: true + + '@rspack/binding-linux-x64-musl@1.6.7': + optional: true + + '@rspack/binding-wasm32-wasi@1.6.7': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rspack/binding-win32-arm64-msvc@1.6.7': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.6.7': + optional: true + + '@rspack/binding-win32-x64-msvc@1.6.7': + optional: true + + '@rspack/binding@1.6.7': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.6.7 + '@rspack/binding-darwin-x64': 1.6.7 + '@rspack/binding-linux-arm64-gnu': 1.6.7 + '@rspack/binding-linux-arm64-musl': 1.6.7 + '@rspack/binding-linux-x64-gnu': 1.6.7 + '@rspack/binding-linux-x64-musl': 1.6.7 + '@rspack/binding-wasm32-wasi': 1.6.7 + '@rspack/binding-win32-arm64-msvc': 1.6.7 + '@rspack/binding-win32-ia32-msvc': 1.6.7 + '@rspack/binding-win32-x64-msvc': 1.6.7 + + '@rspack/cli@1.6.7(@rspack/core@1.6.7)(@types/express@4.17.25)': + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@rspack/core': 1.6.7 + '@rspack/dev-server': 1.1.4(@rspack/core@1.6.7)(@types/express@4.17.25) + exit-hook: 4.0.0 + webpack-bundle-analyzer: 4.10.2 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + + '@rspack/core@1.6.7': + dependencies: + '@module-federation/runtime-tools': 0.21.6 + '@rspack/binding': 1.6.7 + '@rspack/lite-tapable': 1.1.0 + + '@rspack/dev-server@1.1.4(@rspack/core@1.6.7)(@types/express@4.17.25)': + dependencies: + '@rspack/core': 1.6.7 + chokidar: 3.6.0 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + p-retry: 6.2.1 + webpack-dev-server: 5.2.2 + ws: 8.18.3 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + + '@rspack/lite-tapable@1.1.0': {} + '@rtsao/scc@1.1.0': {} '@secretlint/config-creator@10.2.2': @@ -5646,10 +5931,10 @@ snapshots: '@textlint/linter-formatter': 15.4.0 '@textlint/module-interop': 15.4.0 '@textlint/types': 15.4.0 - chalk: 5.4.1 + chalk: 5.6.2 debug: 4.4.3 pluralize: 8.0.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 table: 6.9.0 terminal-link: 4.0.0 transitivePeerDependencies: @@ -5689,76 +5974,11 @@ snapshots: '@secretlint/types@10.2.2': {} - '@sinclair/typebox@0.27.8': {} + '@sindresorhus/base62@1.0.0': {} '@sindresorhus/merge-streams@2.3.0': {} - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 - - '@swc/core-darwin-arm64@1.11.18': - optional: true - - '@swc/core-darwin-x64@1.11.18': - optional: true - - '@swc/core-linux-arm-gnueabihf@1.11.18': - optional: true - - '@swc/core-linux-arm64-gnu@1.11.18': - optional: true - - '@swc/core-linux-arm64-musl@1.11.18': - optional: true - - '@swc/core-linux-x64-gnu@1.11.18': - optional: true - - '@swc/core-linux-x64-musl@1.11.18': - optional: true - - '@swc/core-win32-arm64-msvc@1.11.18': - optional: true - - '@swc/core-win32-ia32-msvc@1.11.18': - optional: true - - '@swc/core-win32-x64-msvc@1.11.18': - optional: true - - '@swc/core@1.11.18': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.21 - optionalDependencies: - '@swc/core-darwin-arm64': 1.11.18 - '@swc/core-darwin-x64': 1.11.18 - '@swc/core-linux-arm-gnueabihf': 1.11.18 - '@swc/core-linux-arm64-gnu': 1.11.18 - '@swc/core-linux-arm64-musl': 1.11.18 - '@swc/core-linux-x64-gnu': 1.11.18 - '@swc/core-linux-x64-musl': 1.11.18 - '@swc/core-win32-arm64-msvc': 1.11.18 - '@swc/core-win32-ia32-msvc': 1.11.18 - '@swc/core-win32-x64-msvc': 1.11.18 - - '@swc/counter@0.1.3': {} - - '@swc/jest@0.2.37(@swc/core@1.11.18)': - dependencies: - '@jest/create-cache-key-function': 29.7.0 - '@swc/core': 1.11.18 - '@swc/counter': 0.1.3 - jsonc-parser: 3.3.1 - - '@swc/types@0.1.21': - dependencies: - '@swc/counter': 0.1.3 + '@standard-schema/spec@1.0.0': {} '@textlint/ast-node-types@15.4.0': {} @@ -5771,7 +5991,7 @@ snapshots: '@textlint/types': 15.4.0 chalk: 4.1.2 debug: 4.4.3 - js-yaml: 3.14.1 + js-yaml: 3.14.2 lodash: 4.17.21 pluralize: 2.0.0 string-width: 4.2.3 @@ -5789,62 +6009,66 @@ snapshots: dependencies: '@textlint/ast-node-types': 15.4.0 - '@tsconfig/node10@1.0.11': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true - '@tsconfig/node16@1.0.4': {} + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 24.10.2 - '@types/babel__core@7.20.5': + '@types/bonjour@3.5.13': dependencies: - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.7 + '@types/node': 24.10.2 - '@types/babel__generator@7.27.0': + '@types/chai@5.2.3': dependencies: - '@babel/types': 7.27.0 + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 - '@types/babel__template@7.4.4': + '@types/connect-history-api-fallback@1.5.4': dependencies: - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 + '@types/express-serve-static-core': 4.19.7 + '@types/node': 24.10.2 - '@types/babel__traverse@7.20.7': + '@types/connect@3.4.38': dependencies: - '@babel/types': 7.27.0 + '@types/node': 24.10.2 '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 18.19.86 + '@types/deep-eql@4.0.2': {} - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 18.19.86 + '@types/estree@1.0.8': {} - '@types/istanbul-lib-coverage@2.0.6': {} + '@types/express-serve-static-core@4.19.7': + dependencies: + '@types/node': 24.10.2 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 - '@types/istanbul-lib-report@3.0.3': + '@types/express@4.17.25': dependencies: - '@types/istanbul-lib-coverage': 2.0.6 + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.7 + '@types/qs': 6.14.0 + '@types/serve-static': 1.15.10 - '@types/istanbul-reports@3.0.4': + '@types/fs-extra@11.0.4': dependencies: - '@types/istanbul-lib-report': 3.0.3 + '@types/jsonfile': 6.1.4 + '@types/node': 20.19.26 - '@types/jest@29.5.14': + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 + '@types/node': 24.10.2 '@types/json-schema@7.0.15': {} @@ -5852,7 +6076,9 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 18.19.86 + '@types/node': 20.19.26 + + '@types/katex@0.16.7': {} '@types/linkify-it@5.0.0': {} @@ -5867,133 +6093,226 @@ snapshots: '@types/mdurl@2.0.0': {} + '@types/mime@1.3.5': {} + '@types/ms@2.1.0': {} - '@types/node@18.19.86': + '@types/node-forge@1.3.14': dependencies: - undici-types: 5.26.5 + '@types/node': 24.10.2 - '@types/node@20.17.30': + '@types/node@20.19.26': dependencies: - undici-types: 6.19.8 - optional: true + undici-types: 6.21.0 + + '@types/node@24.10.2': + dependencies: + undici-types: 7.16.0 '@types/normalize-package-data@2.4.4': {} '@types/plist@3.0.5': dependencies: - '@types/node': 18.19.86 + '@types/node': 20.19.26 xmlbuilder: 15.1.1 + '@types/qs@6.14.0': {} + + '@types/range-parser@1.2.7': {} + '@types/resolve@1.20.6': {} + '@types/retry@0.12.2': {} + '@types/sarif@2.1.7': {} - '@types/semver@7.5.0': {} + '@types/semver@7.7.1': {} + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 24.10.2 + + '@types/send@1.2.1': + dependencies: + '@types/node': 24.10.2 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.25 + + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 24.10.2 + '@types/send': 0.17.6 + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 24.10.2 - '@types/stack-utils@2.0.3': {} + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} '@types/vscode@1.99.0': {} - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.33': + '@types/ws@8.18.1': dependencies: - '@types/yargs-parser': 21.0.3 + '@types/node': 24.10.2 - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.2) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.9.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 7.18.0 eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - semver: 7.7.1 - ts-api-utils: 1.4.3(typescript@5.9.2) + ts-api-utils: 1.4.3(typescript@5.9.3) optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3 eslint: 8.57.1 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@6.21.0': + '@typescript-eslint/scope-manager@7.18.0': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.9.2)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.9.2) - debug: 4.4.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.9.3) + debug: 4.4.3 eslint: 8.57.1 - ts-api-utils: 1.4.3(typescript@5.9.2) + ts-api-utils: 1.4.3(typescript@5.9.3) optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@6.21.0': {} + '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.9.2)': + '@typescript-eslint/types@8.49.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.4.3(typescript@5.9.2) + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 1.4.3(typescript@5.9.3) optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.9.2)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.1) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.2) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) eslint: 8.57.1 - semver: 7.7.1 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@6.21.0': + '@typescript-eslint/visitor-keys@7.18.0': dependencies: - '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.3.0': {} - '@valibot/to-json-schema@1.3.0(valibot@1.1.0(typescript@5.9.2))': + '@valibot/to-json-schema@1.3.0(valibot@1.2.0(typescript@5.9.3))': + dependencies: + valibot: 1.2.0(typescript@5.9.3) + + '@vitest/coverage-v8@4.0.15(vitest@4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.0.15 + ast-v8-to-istanbul: 0.3.8 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magicast: 0.5.1 + obug: 2.1.1 + std-env: 3.10.0 + tinyrainbow: 3.0.3 + vitest: 4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@4.0.15': dependencies: - valibot: 1.1.0(typescript@5.9.2) + '@standard-schema/spec': 1.0.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.15 + '@vitest/utils': 4.0.15 + chai: 6.2.1 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.15(vite@7.2.6(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.0.15 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.2.6(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2) + + '@vitest/mocker@4.0.15(vite@7.2.6(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.0.15 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.2.6(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) + + '@vitest/pretty-format@4.0.15': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.15': + dependencies: + '@vitest/utils': 4.0.15 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.15': + dependencies: + '@vitest/pretty-format': 4.0.15 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.15': {} + + '@vitest/utils@4.0.15': + dependencies: + '@vitest/pretty-format': 4.0.15 + tinyrainbow: 3.0.3 '@vscode/vsce-sign-alpine-arm64@2.0.2': optional: true @@ -6027,43 +6346,12 @@ snapshots: '@vscode/vsce-sign-alpine-arm64': 2.0.2 '@vscode/vsce-sign-alpine-x64': 2.0.2 '@vscode/vsce-sign-darwin-arm64': 2.0.2 - '@vscode/vsce-sign-darwin-x64': 2.0.2 - '@vscode/vsce-sign-linux-arm': 2.0.2 - '@vscode/vsce-sign-linux-arm64': 2.0.2 - '@vscode/vsce-sign-linux-x64': 2.0.2 - '@vscode/vsce-sign-win32-arm64': 2.0.2 - '@vscode/vsce-sign-win32-x64': 2.0.2 - - '@vscode/vsce@2.32.0': - dependencies: - '@azure/identity': 4.8.0 - '@vscode/vsce-sign': 2.0.5 - azure-devops-node-api: 12.5.0 - chalk: 2.4.2 - cheerio: 1.0.0 - cockatiel: 3.2.1 - commander: 6.2.1 - form-data: 4.0.2 - glob: 7.2.3 - hosted-git-info: 4.1.0 - jsonc-parser: 3.3.1 - leven: 3.1.0 - markdown-it: 12.3.2 - mime: 1.6.0 - minimatch: 3.1.2 - parse-semver: 1.1.1 - read: 1.0.7 - semver: 7.7.1 - tmp: 0.2.3 - typed-rest-client: 1.8.11 - url-join: 4.0.1 - xml2js: 0.5.0 - yauzl: 2.10.0 - yazl: 2.5.1 - optionalDependencies: - keytar: 7.9.0 - transitivePeerDependencies: - - supports-color + '@vscode/vsce-sign-darwin-x64': 2.0.2 + '@vscode/vsce-sign-linux-arm': 2.0.2 + '@vscode/vsce-sign-linux-arm64': 2.0.2 + '@vscode/vsce-sign-linux-x64': 2.0.2 + '@vscode/vsce-sign-win32-arm64': 2.0.2 + '@vscode/vsce-sign-win32-x64': 2.0.2 '@vscode/vsce@3.7.1': dependencies: @@ -6089,7 +6377,7 @@ snapshots: parse-semver: 1.1.1 read: 1.0.7 secretlint: 10.2.2 - semver: 7.7.1 + semver: 7.7.3 tmp: 0.2.3 typed-rest-client: 1.8.11 url-join: 4.0.1 @@ -6103,18 +6391,32 @@ snapshots: '@xmldom/xmldom@0.8.10': {} - acorn-jsx@5.3.2(acorn@8.14.1): + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.1 + acorn: 8.15.0 acorn-walk@8.3.4: dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn@8.14.1: {} + acorn@8.15.0: {} agent-base@7.1.3: {} + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -6133,27 +6435,21 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@7.0.0: + ansi-escapes@7.2.0: dependencies: environment: 1.1.0 - ansi-regex@4.1.1: {} + ansi-html-community@0.0.8: {} ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 + ansi-regex@6.2.2: {} ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - ansi-styles@5.2.0: {} - - ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} anymatch@3.1.3: dependencies: @@ -6162,8 +6458,6 @@ snapshots: are-docs-informative@0.0.2: {} - arg@4.1.3: {} - argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -6175,14 +6469,18 @@ snapshots: call-bound: 1.0.4 is-array-buffer: 3.0.5 - array-includes@3.1.8: + array-flatten@1.1.1: {} + + array-includes@3.1.9: dependencies: call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 + math-intrinsics: 1.1.0 array-union@2.1.0: {} @@ -6191,7 +6489,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -6200,14 +6498,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: @@ -6215,17 +6513,23 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + assertion-error@2.0.1: {} + + ast-v8-to-istanbul@0.3.8: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 9.0.1 + astral-regex@2.0.0: {} async-function@1.0.0: {} - async@3.2.6: {} - asynckit@0.4.0: {} available-typed-arrays@1.0.7: @@ -6237,67 +6541,14 @@ snapshots: tunnel: 0.0.6 typed-rest-client: 1.8.11 - babel-jest@29.7.0(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.10) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-istanbul@6.1.1: - dependencies: - '@babel/helper-plugin-utils': 7.26.5 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.27.0 - '@babel/types': 7.27.0 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.7 - - babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.10) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.10) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.10) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.10) - - babel-preset-jest@29.6.3(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) - bail@2.0.2: {} balanced-match@1.0.2: {} base64-js@1.5.1: {} + batch@0.6.1: {} + binary-extensions@2.3.0: {} binaryextensions@6.11.0: @@ -6313,6 +6564,28 @@ snapshots: bluebird@3.7.2: {} + body-parser@1.20.4: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + boolbase@1.0.0: {} boundary@2.0.0: {} @@ -6322,7 +6595,7 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -6330,39 +6603,22 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.4: - dependencies: - caniuse-lite: 1.0.30001712 - electron-to-chromium: 1.5.132 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.4) - - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - buffer-crc32@0.2.13: {} buffer-equal-constant-time@1.0.1: {} - buffer-from@1.1.2: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 optional: true - builtin-modules@3.3.0: {} - bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 + bytes@3.1.2: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -6389,35 +6645,27 @@ snapshots: quick-lru: 5.1.1 type-fest: 1.4.0 - camelcase@5.3.1: {} - camelcase@6.3.0: {} - caniuse-lite@1.0.30001712: {} - catharsis@0.9.0: dependencies: lodash: 4.17.21 - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 + chai@6.2.1: {} chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.4.1: {} - chalk@5.6.2: {} - char-regex@1.0.2: {} + character-entities-legacy@3.0.0: {} character-entities@2.0.2: {} + character-reference-invalid@2.0.1: {} + cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -6441,13 +6689,6 @@ snapshots: undici: 6.21.2 whatwg-mimetype: 4.0.0 - chokidar-cli@3.0.0: - dependencies: - chokidar: 3.6.0 - lodash.debounce: 4.0.8 - lodash.throttle: 4.1.1 - yargs: 13.3.2 - chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -6460,60 +6701,40 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + chownr@1.1.4: optional: true ci-info@2.0.0: {} - ci-info@3.9.0: {} - - cjs-module-lexer@1.4.3: {} + ci-info@4.3.1: {} cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 - cli-truncate@4.0.0: + cli-truncate@5.1.1: dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 + slice-ansi: 7.1.2 + string-width: 8.1.0 cli-width@4.1.0: {} - cliui@5.0.0: - dependencies: - string-width: 3.1.0 - strip-ansi: 5.2.0 - wrap-ansi: 5.1.0 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clone-deep@4.0.1: dependencies: is-plain-object: 2.0.4 kind-of: 6.0.3 shallow-clone: 3.0.1 - co@4.6.0: {} - cockatiel@3.2.1: {} - collect-v8-coverage@1.0.2: {} - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - color-convert@2.0.1: dependencies: color-name: 1.1.4 - color-name@1.1.3: {} - color-name@1.1.4: {} colorette@2.0.20: {} @@ -6522,56 +6743,58 @@ snapshots: dependencies: delayed-stream: 1.0.0 - commander@11.0.0: {} - - commander@11.1.0: {} - commander@12.1.0: {} - commander@13.1.0: {} - commander@14.0.2: {} commander@6.2.1: {} + commander@7.2.0: {} + + commander@8.3.0: {} + comment-parser@1.4.1: {} - concat-map@0.0.1: {} + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 - concurrently@8.2.2: + compression@1.8.1: dependencies: - chalk: 4.1.2 - date-fns: 2.30.0 - lodash: 4.17.21 - rxjs: 7.8.2 - shell-quote: 1.8.2 - spawn-command: 0.0.2 - supports-color: 8.1.1 - tree-kill: 1.2.2 - yargs: 17.7.2 + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} confusing-browser-globals@1.0.11: {} - convert-source-map@2.0.0: {} + connect-history-api-fallback@2.0.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.2: {} core-js-pure@3.46.0: {} - create-jest@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node + core-util-is@1.0.3: {} - create-require@1.1.1: {} + cross-env@10.1.0: + dependencies: + '@epic-web/invariant': 1.0.0 + cross-spawn: 7.0.6 cross-spawn@7.0.6: dependencies: @@ -6607,17 +6830,15 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - date-fns@2.30.0: - dependencies: - '@babel/runtime': 7.27.0 + debounce@1.2.1: {} debounce@3.0.0: {} - debug@3.2.7: + debug@2.6.9: dependencies: - ms: 2.1.3 + ms: 2.0.0 - debug@4.4.0: + debug@3.2.7: dependencies: ms: 2.1.3 @@ -6625,9 +6846,7 @@ snapshots: dependencies: ms: 2.1.3 - decamelize@1.2.0: {} - - decode-named-character-reference@1.1.0: + decode-named-character-reference@1.2.0: dependencies: character-entities: 2.0.2 @@ -6636,8 +6855,6 @@ snapshots: mimic-response: 3.1.0 optional: true - dedent@1.5.3: {} - deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -6667,29 +6884,35 @@ snapshots: delayed-stream@1.0.0: {} + depd@1.1.2: {} + + depd@2.0.0: {} + dequal@2.0.3: {} + destroy@1.2.0: {} + detect-indent@7.0.2: {} detect-libc@2.0.3: optional: true - detect-newline@3.1.0: {} - detect-newline@4.0.1: {} + detect-node@2.1.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 - diff-sequences@29.6.3: {} - - diff@4.0.2: {} - dir-glob@3.0.1: dependencies: path-type: 4.0.0 + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -6722,6 +6945,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer@0.1.2: {} + eastasianwidth@0.2.0: {} ecdsa-sig-formatter@1.0.11: @@ -6732,22 +6957,18 @@ snapshots: dependencies: version-range: 4.15.0 - ejs@3.1.10: - dependencies: - jake: 10.9.2 - - electron-to-chromium@1.5.132: {} - - emittery@0.13.1: {} + ee-first@1.1.1: {} - emoji-regex@10.4.0: {} - - emoji-regex@7.0.3: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + encoding-sniffer@0.2.0: dependencies: iconv-lite: 0.6.3 @@ -6763,19 +6984,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.3 - entities@2.1.0: {} - - entities@3.0.1: {} - entities@4.5.0: {} environment@1.1.0: {} - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - es-abstract@1.23.9: + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -6804,7 +7017,9 @@ snapshots: is-array-buffer: 3.0.5 is-callable: 1.2.7 is-data-view: 1.0.2 + is-negative-zero: 2.0.3 is-regex: 1.2.1 + is-set: 2.0.3 is-shared-array-buffer: 1.0.4 is-string: 1.1.1 is-typed-array: 1.1.15 @@ -6819,6 +7034,7 @@ snapshots: safe-push-apply: 1.0.0 safe-regex-test: 1.1.0 set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 string.prototype.trim: 1.2.10 string.prototype.trimend: 1.0.9 string.prototype.trimstart: 1.0.8 @@ -6833,6 +7049,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -6854,69 +7072,65 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild-register@3.6.0(esbuild@0.17.19): - dependencies: - debug: 4.4.0 - esbuild: 0.17.19 - transitivePeerDependencies: - - supports-color - - esbuild@0.17.19: + esbuild@0.25.12: optionalDependencies: - '@esbuild/android-arm': 0.17.19 - '@esbuild/android-arm64': 0.17.19 - '@esbuild/android-x64': 0.17.19 - '@esbuild/darwin-arm64': 0.17.19 - '@esbuild/darwin-x64': 0.17.19 - '@esbuild/freebsd-arm64': 0.17.19 - '@esbuild/freebsd-x64': 0.17.19 - '@esbuild/linux-arm': 0.17.19 - '@esbuild/linux-arm64': 0.17.19 - '@esbuild/linux-ia32': 0.17.19 - '@esbuild/linux-loong64': 0.17.19 - '@esbuild/linux-mips64el': 0.17.19 - '@esbuild/linux-ppc64': 0.17.19 - '@esbuild/linux-riscv64': 0.17.19 - '@esbuild/linux-s390x': 0.17.19 - '@esbuild/linux-x64': 0.17.19 - '@esbuild/netbsd-x64': 0.17.19 - '@esbuild/openbsd-x64': 0.17.19 - '@esbuild/sunos-x64': 0.17.19 - '@esbuild/win32-arm64': 0.17.19 - '@esbuild/win32-ia32': 0.17.19 - '@esbuild/win32-x64': 0.17.19 - - esbuild@0.25.2: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.27.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.2 - '@esbuild/android-arm': 0.25.2 - '@esbuild/android-arm64': 0.25.2 - '@esbuild/android-x64': 0.25.2 - '@esbuild/darwin-arm64': 0.25.2 - '@esbuild/darwin-x64': 0.25.2 - '@esbuild/freebsd-arm64': 0.25.2 - '@esbuild/freebsd-x64': 0.25.2 - '@esbuild/linux-arm': 0.25.2 - '@esbuild/linux-arm64': 0.25.2 - '@esbuild/linux-ia32': 0.25.2 - '@esbuild/linux-loong64': 0.25.2 - '@esbuild/linux-mips64el': 0.25.2 - '@esbuild/linux-ppc64': 0.25.2 - '@esbuild/linux-riscv64': 0.25.2 - '@esbuild/linux-s390x': 0.25.2 - '@esbuild/linux-x64': 0.25.2 - '@esbuild/netbsd-arm64': 0.25.2 - '@esbuild/netbsd-x64': 0.25.2 - '@esbuild/openbsd-arm64': 0.25.2 - '@esbuild/openbsd-x64': 0.25.2 - '@esbuild/sunos-x64': 0.25.2 - '@esbuild/win32-arm64': 0.25.2 - '@esbuild/win32-ia32': 0.25.2 - '@esbuild/win32-x64': 0.25.2 - - escalade@3.2.0: {} - - escape-string-regexp@1.0.5: {} + '@esbuild/aix-ppc64': 0.27.1 + '@esbuild/android-arm': 0.27.1 + '@esbuild/android-arm64': 0.27.1 + '@esbuild/android-x64': 0.27.1 + '@esbuild/darwin-arm64': 0.27.1 + '@esbuild/darwin-x64': 0.27.1 + '@esbuild/freebsd-arm64': 0.27.1 + '@esbuild/freebsd-x64': 0.27.1 + '@esbuild/linux-arm': 0.27.1 + '@esbuild/linux-arm64': 0.27.1 + '@esbuild/linux-ia32': 0.27.1 + '@esbuild/linux-loong64': 0.27.1 + '@esbuild/linux-mips64el': 0.27.1 + '@esbuild/linux-ppc64': 0.27.1 + '@esbuild/linux-riscv64': 0.27.1 + '@esbuild/linux-s390x': 0.27.1 + '@esbuild/linux-x64': 0.27.1 + '@esbuild/netbsd-arm64': 0.27.1 + '@esbuild/netbsd-x64': 0.27.1 + '@esbuild/openbsd-arm64': 0.27.1 + '@esbuild/openbsd-x64': 0.27.1 + '@esbuild/openharmony-arm64': 0.27.1 + '@esbuild/sunos-x64': 0.27.1 + '@esbuild/win32-arm64': 0.27.1 + '@esbuild/win32-ia32': 0.27.1 + '@esbuild/win32-x64': 0.27.1 + + escape-html@1.0.3: {} escape-string-regexp@2.0.0: {} @@ -6927,49 +7141,51 @@ snapshots: eslint-compat-utils@0.5.1(eslint@8.57.1): dependencies: eslint: 8.57.1 - semver: 7.7.1 + semver: 7.7.3 - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1): + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: confusing-browser-globals: 1.0.11 eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) object.assign: 4.1.7 object.entries: 1.1.9 semver: 6.3.1 - eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1): + eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1)(typescript@5.9.2) - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1) + transitivePeerDependencies: + - eslint-plugin-import eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 is-core-module: 2.16.1 - resolve: 1.22.10 + resolve: 1.22.11 transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-boundaries@5.0.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1): + eslint-plugin-boundaries@5.3.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1): dependencies: + '@boundaries/elements': 1.1.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) chalk: 4.1.2 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) micromatch: 4.0.8 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -6988,10 +7204,10 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 - array-includes: 3.1.8 + array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 @@ -6999,7 +7215,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -7011,28 +7227,33 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@46.10.1(eslint@8.57.1): + eslint-plugin-jsdoc@61.5.0(eslint@8.57.1): dependencies: - '@es-joy/jsdoccomment': 0.41.0 + '@es-joy/jsdoccomment': 0.76.0 + '@es-joy/resolve.exports': 1.2.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.0 + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint: 8.57.1 + espree: 10.4.0 esquery: 1.6.0 - is-builtin-module: 3.2.1 - semver: 7.7.1 + html-entities: 2.6.0 + object-deep-merge: 2.0.0 + parse-imports-exports: 0.2.4 + semver: 7.7.3 spdx-expression-parse: 4.0.0 + to-valid-identifier: 1.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-n@17.23.1(eslint@8.57.1)(typescript@5.9.2): + eslint-plugin-n@17.23.1(eslint@8.57.1)(typescript@5.9.3): dependencies: '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.1) enhanced-resolve: 5.18.3 @@ -7042,8 +7263,8 @@ snapshots: globals: 15.15.0 globrex: 0.1.2 ignore: 5.3.2 - semver: 7.7.1 - ts-declaration-location: 1.0.7(typescript@5.9.2) + semver: 7.7.3 + ts-declaration-location: 1.0.7(typescript@5.9.3) transitivePeerDependencies: - typescript @@ -7054,6 +7275,8 @@ snapshots: eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.2.1: {} + eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.1) @@ -7067,7 +7290,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0 + debug: 4.4.3 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -7085,7 +7308,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 + js-yaml: 4.1.1 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -7097,10 +7320,16 @@ snapshots: transitivePeerDependencies: - supports-color + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + espree@9.6.1: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -7115,48 +7344,62 @@ snapshots: estraverse@5.3.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} - eventemitter3@5.0.1: {} + etag@1.8.1: {} - events@3.3.0: {} + eventemitter3@4.0.7: {} - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 + eventemitter3@5.0.1: {} - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 + events@3.3.0: {} - exit@0.1.2: {} + exit-hook@4.0.0: {} expand-template@2.0.3: optional: true - expect@29.7.0: - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + expect-type@1.2.2: {} + + express@4.22.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.4 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.1 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color extend@3.0.2: {} @@ -7184,31 +7427,39 @@ snapshots: dependencies: reusify: 1.1.0 - fb-watchman@2.0.2: + faye-websocket@0.11.4: dependencies: - bser: 2.1.1 + websocket-driver: 0.7.4 fd-slicer@1.1.0: dependencies: pend: 1.2.0 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - find-up-simple@1.0.1: {} - - find-up@3.0.0: + finalhandler@1.3.2: dependencies: - locate-path: 3.0.0 + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up-simple@1.0.1: {} find-up@4.1.0: dependencies: @@ -7251,10 +7502,14 @@ snapshots: es-set-tostringtag: 2.1.0 mime-types: 2.1.35 + forwarded@0.2.0: {} + + fresh@0.5.2: {} + fs-constants@1.0.0: optional: true - fs-extra@11.3.0: + fs-extra@11.3.2: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 @@ -7278,11 +7533,7 @@ snapshots: functions-have-names@1.2.3: {} - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.3.0: {} + get-east-asian-width@1.4.0: {} get-intrinsic@1.3.0: dependencies: @@ -7297,19 +7548,11 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 - get-package-type@0.1.0: {} - get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stdin@9.0.0: {} - - get-stream@6.0.1: {} - - get-stream@8.0.1: {} - get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -7331,13 +7574,9 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.2.7: + glob-to-regex.js@1.2.0(tslib@2.8.1): dependencies: - foreground-child: 3.3.1 - jackspeak: 2.3.6 - minimatch: 9.0.5 - minipass: 6.0.2 - path-scurry: 1.11.1 + tslib: 2.8.1 glob@11.1.0: dependencies: @@ -7348,6 +7587,12 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.1 + glob@13.0.0: + dependencies: + minimatch: 10.1.1 + minipass: 7.1.2 + path-scurry: 2.0.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -7357,15 +7602,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - glob@9.3.5: - dependencies: - fs.realpath: 1.0.0 - minimatch: 8.0.4 - minipass: 4.2.8 - path-scurry: 1.11.1 - - globals@11.12.0: {} - globals@13.24.0: dependencies: type-fest: 0.20.2 @@ -7408,9 +7644,22 @@ snapshots: js-base64: 3.7.8 unicode-trie: 2.0.0 - has-bigints@1.1.0: {} + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handle-thing@2.0.1: {} + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 - has-flag@3.0.0: {} + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -7440,6 +7689,15 @@ snapshots: dependencies: lru-cache: 10.4.3 + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-entities@2.6.0: {} + html-escaper@2.0.2: {} htmlparser2@9.1.0: @@ -7449,25 +7707,74 @@ snapshots: domutils: 3.2.2 entities: 4.5.0 + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color + http-proxy-middleware@2.0.9(@types/express@4.17.25): + dependencies: + '@types/http-proxy': 1.17.17 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.25 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color - human-signals@2.1.0: {} + husky@9.1.7: {} - human-signals@5.0.0: {} + hyperdyperid@1.2.0: {} - husky@9.1.7: {} + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 iconv-lite@0.6.3: dependencies: @@ -7476,8 +7783,6 @@ snapshots: ieee754@1.2.1: optional: true - ignore@5.2.4: {} - ignore@5.3.2: {} ignore@7.0.5: {} @@ -7487,11 +7792,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - imurmurhash@0.1.4: {} index-to-position@1.2.0: {} @@ -7503,12 +7803,14 @@ snapshots: once: 1.4.0 wrappy: 1.0.2 + inherits@2.0.3: {} + inherits@2.0.4: {} ini@1.3.8: optional: true - ini@3.0.1: {} + ini@4.1.3: {} internal-slot@1.1.0: dependencies: @@ -7518,14 +7820,23 @@ snapshots: ip-regex@4.3.0: {} + ipaddr.js@1.9.1: {} + + ipaddr.js@2.3.0: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 get-intrinsic: 1.3.0 - is-arrayish@0.2.1: {} - is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -7547,10 +7858,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-callable@1.2.7: {} is-ci@2.0.0: @@ -7572,6 +7879,8 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-decimal@2.0.1: {} + is-docker@3.0.0: {} is-extglob@2.1.1: {} @@ -7580,17 +7889,11 @@ snapshots: dependencies: call-bound: 1.0.4 - is-fullwidth-code-point@2.0.0: {} - is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@4.0.0: {} - - is-fullwidth-code-point@5.0.0: + is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.3.0 - - is-generator-fn@2.1.0: {} + get-east-asian-width: 1.4.0 is-generator-function@1.1.0: dependencies: @@ -7603,6 +7906,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hexadecimal@2.0.1: {} + is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 @@ -7611,8 +7916,16 @@ snapshots: dependencies: ip-regex: 4.3.0 + is-it-type@5.1.3: + dependencies: + globalthis: 1.0.4 + is-map@2.0.3: {} + is-negative-zero@2.0.3: {} + + is-network-error@1.3.0: {} + is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -7622,6 +7935,8 @@ snapshots: is-path-inside@3.0.3: {} + is-plain-obj@3.0.0: {} + is-plain-obj@4.1.0: {} is-plain-object@2.0.4: @@ -7641,10 +7956,6 @@ snapshots: dependencies: call-bound: 1.0.4 - is-stream@2.0.1: {} - - is-stream@3.0.0: {} - is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -7675,6 +7986,8 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -7683,41 +7996,21 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.26.10 - '@babel/parser': 7.27.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.26.10 - '@babel/parser': 7.27.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.1 - transitivePeerDependencies: - - supports-color - istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: + istanbul-lib-source-maps@5.0.6: dependencies: - debug: 4.4.0 + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 transitivePeerDependencies: - supports-color - istanbul-reports@3.1.7: + istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 @@ -7728,342 +8021,22 @@ snapshots: editions: 6.22.0 textextensions: 6.11.0 - jackspeak@2.3.6: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - jackspeak@4.1.1: dependencies: '@isaacs/cliui': 8.0.2 - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)): - dependencies: - '@babel/core': 7.26.10 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.10) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 18.19.86 - ts-node: 10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - jest-get-type@29.6.3: {} - - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 18.19.86 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - jest-util: 29.7.0 - - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - - jest-regex-util@29.6.3: {} - - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.10 - resolve.exports: 2.0.3 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - chalk: 4.1.2 - cjs-module-lexer: 1.4.3 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.26.10 - '@babel/generator': 7.27.0 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) - '@babel/types': 7.27.0 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.7.1 - transitivePeerDependencies: - - supports-color - - jest-util@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.86 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - jest-worker@29.7.0: - dependencies: - '@types/node': 18.19.86 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - js-base64@3.7.8: {} js-tokens@4.0.0: {} - js-yaml@3.14.1: + js-tokens@9.0.1: {} + + js-yaml@3.14.2: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -8071,11 +8044,11 @@ snapshots: dependencies: xmlcreate: 2.0.4 - jsdoc-type-pratt-parser@4.0.0: {} + jsdoc-type-pratt-parser@6.10.0: {} - jsdoc@4.0.4: + jsdoc@4.0.5: dependencies: - '@babel/parser': 7.27.0 + '@babel/parser': 7.28.5 '@jsdoc/salty': 0.2.9 '@types/markdown-it': 14.1.2 bluebird: 3.7.2 @@ -8091,12 +8064,8 @@ snapshots: strip-json-comments: 3.1.1 underscore: 1.13.7 - jsesc@3.1.0: {} - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -8109,8 +8078,6 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.1: {} - jsonc-parser@3.3.1: {} jsonfile@6.1.0: @@ -8119,6 +8086,8 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonpointer@5.0.1: {} + jsonwebtoken@9.0.2: dependencies: jws: 3.2.2 @@ -8130,7 +8099,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.1 + semver: 7.7.3 jwa@1.4.1: dependencies: @@ -8154,6 +8123,10 @@ snapshots: jwa: 2.0.0 safe-buffer: 5.2.1 + katex@0.16.27: + dependencies: + commander: 8.3.0 + keytar@7.9.0: dependencies: node-addon-api: 4.3.0 @@ -8170,7 +8143,10 @@ snapshots: dependencies: graceful-fs: 4.2.11 - kleur@3.0.3: {} + launch-editor@2.12.0: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.3 leven@3.1.0: {} @@ -8179,58 +8155,36 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.1.3: {} - - lines-and-columns@1.2.4: {} - - linkify-it@3.0.3: - dependencies: - uc.micro: 1.0.6 - - linkify-it@4.0.1: - dependencies: - uc.micro: 1.0.6 - linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 - lint-staged@15.5.0: + lint-staged@16.2.7: dependencies: - chalk: 5.4.1 - commander: 13.1.0 - debug: 4.4.0 - execa: 8.0.1 - lilconfig: 3.1.3 - listr2: 8.2.5 + commander: 14.0.2 + listr2: 9.0.5 micromatch: 4.0.8 + nano-spawn: 2.0.0 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.7.1 - transitivePeerDependencies: - - supports-color + yaml: 2.8.2 - listr2@8.2.5: + listr2@9.0.5: dependencies: - cli-truncate: 4.0.0 + cli-truncate: 5.1.1 colorette: 2.0.20 eventemitter3: 5.0.1 log-update: 6.1.0 rfdc: 1.4.1 - wrap-ansi: 9.0.0 + wrap-ansi: 9.0.2 load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.11 - js-yaml: 3.14.1 + js-yaml: 3.14.2 pify: 4.0.1 strip-bom: 3.0.0 - locate-path@3.0.0: - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -8239,8 +8193,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.debounce@4.0.8: {} - lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -8253,25 +8205,21 @@ snapshots: lodash.isstring@4.0.1: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.once@4.1.1: {} - lodash.throttle@4.1.1: {} - lodash.truncate@4.4.2: {} lodash@4.17.21: {} log-update@6.1.0: dependencies: - ansi-escapes: 7.0.0 + ansi-escapes: 7.2.0 cli-cursor: 5.0.0 - slice-ansi: 7.1.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 longest-streak@3.1.0: {} @@ -8279,23 +8227,23 @@ snapshots: lru-cache@11.2.2: {} - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - lru-cache@6.0.0: dependencies: yallist: 4.0.0 - make-dir@4.0.0: + magic-string@0.30.21: dependencies: - semver: 7.7.1 + '@jridgewell/sourcemap-codec': 1.5.5 - make-error@1.3.6: {} + magicast@0.5.1: + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + source-map-js: 1.2.1 - makeerror@1.0.12: + make-dir@4.0.0: dependencies: - tmpl: 1.0.5 + semver: 7.7.3 map-obj@4.3.0: {} @@ -8304,22 +8252,6 @@ snapshots: '@types/markdown-it': 14.1.2 markdown-it: 14.1.0 - markdown-it@12.3.2: - dependencies: - argparse: 2.0.1 - entities: 2.1.0 - linkify-it: 3.0.3 - mdurl: 1.0.1 - uc.micro: 1.0.6 - - markdown-it@13.0.1: - dependencies: - argparse: 2.0.1 - entities: 3.0.1 - linkify-it: 4.0.1 - mdurl: 1.0.1 - uc.micro: 1.0.6 - markdown-it@14.1.0: dependencies: argparse: 2.0.1 @@ -8329,31 +8261,49 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - markdownlint-cli@0.35.0: + markdownlint-cli@0.46.0: dependencies: - commander: 11.0.0 - get-stdin: 9.0.0 - glob: 10.2.7 - ignore: 5.2.4 - js-yaml: 4.1.0 - jsonc-parser: 3.2.1 - markdownlint: 0.29.0 - minimatch: 9.0.5 - run-con: 1.2.12 - - markdownlint-micromark@0.1.5: {} - - markdownlint-micromark@0.1.7: {} + commander: 14.0.2 + deep-extend: 0.6.0 + ignore: 7.0.5 + js-yaml: 4.1.1 + jsonc-parser: 3.3.1 + jsonpointer: 5.0.1 + markdown-it: 14.1.0 + markdownlint: 0.39.0 + minimatch: 10.1.1 + run-con: 1.3.2 + smol-toml: 1.5.2 + tinyglobby: 0.2.15 + transitivePeerDependencies: + - supports-color - markdownlint@0.29.0: + markdownlint@0.39.0: dependencies: - markdown-it: 13.0.1 - markdownlint-micromark: 0.1.5 + micromark: 4.0.2 + micromark-core-commonmark: 2.0.3 + micromark-extension-directive: 4.0.0 + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-math: 3.1.0 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color - markdownlint@0.30.0: + markdownlint@0.40.0: dependencies: - markdown-it: 13.0.1 - markdownlint-micromark: 0.1.7 + micromark: 4.0.2 + micromark-core-commonmark: 2.0.3 + micromark-extension-directive: 4.0.0 + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-math: 3.1.0 + micromark-util-types: 2.0.2 + string-width: 8.1.0 + transitivePeerDependencies: + - supports-color marked@4.3.0: {} @@ -8369,7 +8319,7 @@ snapshots: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 micromark: 4.0.2 @@ -8405,17 +8355,28 @@ snapshots: mdn-data@2.23.0: {} - mdurl@1.0.1: {} - mdurl@2.0.0: {} - merge-stream@2.0.0: {} + media-typer@0.3.0: {} + + memfs@4.51.1: + dependencies: + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + merge-descriptors@1.0.3: {} merge2@1.4.1: {} + methods@1.1.2: {} + micromark-core-commonmark@2.0.3: dependencies: - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-factory-destination: 2.0.1 micromark-factory-label: 2.0.1 @@ -8432,6 +8393,52 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 + micromark-extension-directive@4.0.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-math@3.1.0: + dependencies: + '@types/katex': 0.16.7 + devlop: 1.1.0 + katex: 0.16.27 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-factory-destination@2.0.1: dependencies: micromark-util-character: 2.1.1 @@ -8490,7 +8497,7 @@ snapshots: micromark-util-decode-string@2.0.1: dependencies: - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 micromark-util-character: 2.1.1 micromark-util-decode-numeric-character-reference: 2.0.2 micromark-util-symbol: 2.0.1 @@ -8527,8 +8534,8 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0 - decode-named-character-reference: 1.1.0 + debug: 4.4.3 + decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 micromark-factory-space: 2.0.1 @@ -8555,21 +8562,25 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - mime@1.6.0: {} - - mimic-fn@2.1.0: {} + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 - mimic-fn@4.0.0: {} + mime@1.6.0: {} mimic-function@5.0.1: {} mimic-response@3.1.0: optional: true + minimalistic-assert@1.0.1: {} + minimatch@10.1.1: dependencies: '@isaacs/brace-expansion': 5.0.0 @@ -8578,28 +8589,12 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.1 - - minimatch@8.0.4: - dependencies: - brace-expansion: 2.0.1 - - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.1 - minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} - minipass@4.2.8: {} - - minipass@6.0.2: {} - minipass@7.1.2: {} mkdirp-classic@0.5.3: @@ -8609,56 +8604,67 @@ snapshots: mkdirp@3.0.1: {} + mrmime@2.0.1: {} + + ms@2.0.0: {} + ms@2.1.3: {} + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + mute-stream@0.0.8: {} mute-stream@2.0.0: {} mute-stream@3.0.0: {} + nano-spawn@2.0.0: {} + + nanoid@3.3.11: {} + napi-build-utils@2.0.0: optional: true natural-compare@1.4.0: {} + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + node-abi@3.74.0: dependencies: - semver: 7.7.1 + semver: 7.7.3 optional: true node-addon-api@4.3.0: optional: true - node-int64@0.4.0: {} - - node-releases@2.0.19: {} + node-forge@1.3.3: {} node-sarif-builder@3.3.1: dependencies: '@types/sarif': 2.1.7 - fs-extra: 11.3.0 + fs-extra: 11.3.2 normalize-package-data@6.0.2: dependencies: hosted-git-info: 7.0.2 - semver: 7.7.1 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 + object-deep-merge@2.0.0: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} @@ -8683,14 +8689,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 object.values@1.2.1: dependencies: @@ -8699,19 +8705,21 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + obuf@1.1.2: {} + + obug@2.1.1: {} + ohash@2.0.11: {} - once@1.4.0: + on-finished@2.4.1: dependencies: - wrappy: 1.0.2 + ee-first: 1.1.1 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 + on-headers@1.1.0: {} - onetime@6.0.0: + once@1.4.0: dependencies: - mimic-fn: 4.0.0 + wrappy: 1.0.2 onetime@7.0.0: dependencies: @@ -8724,6 +8732,8 @@ snapshots: is-inside-container: 1.0.0 is-wsl: 3.1.0 + opener@1.5.2: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -8733,15 +8743,16 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - ovsx@0.8.4: + ovsx@0.10.7: dependencies: - '@vscode/vsce': 2.32.0 + '@vscode/vsce': 3.7.1 commander: 6.2.1 follow-redirects: 1.15.9 is-ci: 2.0.0 leven: 3.1.0 - semver: 7.7.1 + semver: 7.7.3 tmp: 0.2.3 + yauzl-promise: 4.0.0 transitivePeerDependencies: - debug - supports-color @@ -8760,10 +8771,6 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-locate@3.0.0: - dependencies: - p-limit: 2.3.0 - p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -8774,6 +8781,12 @@ snapshots: p-map@7.0.4: {} + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.0 + retry: 0.13.1 + p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -8784,12 +8797,19 @@ snapshots: dependencies: callsites: 3.1.0 - parse-json@5.2.0: + parse-entities@4.0.2: dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.2.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-imports-exports@0.2.4: + dependencies: + parse-statements: 1.0.11 parse-json@8.3.0: dependencies: @@ -8801,6 +8821,8 @@ snapshots: dependencies: semver: 5.7.2 + parse-statements@1.0.11: {} + parse5-htmlparser2-tree-adapter@7.1.0: dependencies: domhandler: 5.0.3 @@ -8814,7 +8836,7 @@ snapshots: dependencies: entities: 4.5.0 - path-exists@3.0.0: {} + parseurl@1.3.3: {} path-exists@4.0.0: {} @@ -8822,24 +8844,21 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - path-scurry@2.0.1: dependencies: lru-cache: 11.2.2 minipass: 7.1.2 + path-to-regexp@0.1.12: {} + path-type@4.0.0: {} path-type@6.0.0: {} + pathe@2.0.3: {} + pend@1.2.0: {} picocolors@1.1.1: {} @@ -8852,8 +8871,6 @@ snapshots: pify@4.0.1: {} - pirates@4.0.7: {} - piscina@5.1.3: optionalDependencies: '@napi-rs/nice': 1.1.1 @@ -8874,6 +8891,12 @@ snapshots: possible-typed-array-names@1.1.0: {} + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prebuild-install@7.1.3: dependencies: detect-libc: 2.0.3 @@ -8898,16 +8921,12 @@ snapshots: prelude-ls@1.2.1: {} - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 + process-nextick-args@2.0.1: {} - prompts@2.4.2: + proxy-addr@2.0.7: dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 + forwarded: 0.2.0 + ipaddr.js: 1.9.1 pump@3.0.2: dependencies: @@ -8919,8 +8938,6 @@ snapshots: punycode@2.3.1: {} - pure-rand@6.1.0: {} - qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -8929,10 +8946,19 @@ snapshots: quick-lru@5.1.1: {} + range-parser@1.2.1: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + rc-config-loader@4.1.3: dependencies: debug: 4.4.3 - js-yaml: 4.1.0 + js-yaml: 4.1.1 json5: 2.2.3 require-from-string: 2.0.2 transitivePeerDependencies: @@ -8946,8 +8972,6 @@ snapshots: strip-json-comments: 2.0.1 optional: true - react-is@18.3.1: {} - read-pkg@9.0.1: dependencies: '@types/normalize-package-data': 2.4.4 @@ -8960,30 +8984,39 @@ snapshots: dependencies: mute-stream: 0.0.8 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - optional: true readdirp@3.6.0: dependencies: picomatch: 2.3.1 + readdirp@5.0.0: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerator-runtime@0.14.1: {} - regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.8 @@ -9014,34 +9047,20 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 - require-directory@2.1.1: {} - require-from-string@2.0.2: {} - require-main-filename@2.0.0: {} + requires-port@1.0.0: {} requizzle@0.2.4: dependencies: lodash: 4.17.21 - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 + reserved-identifiers@1.2.0: {} resolve-from@4.0.0: {} - resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} - resolve.exports@2.0.3: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -9053,6 +9072,8 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + retry@0.13.1: {} + reusify@1.1.0: {} rfdc@1.4.1: {} @@ -9061,16 +9082,45 @@ snapshots: dependencies: glob: 7.2.3 - rimraf@4.4.1: + rimraf@6.1.2: + dependencies: + glob: 13.0.0 + package-json-from-dist: 1.0.1 + + rollup@4.53.3: dependencies: - glob: 9.3.5 + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.53.3 + '@rollup/rollup-android-arm64': 4.53.3 + '@rollup/rollup-darwin-arm64': 4.53.3 + '@rollup/rollup-darwin-x64': 4.53.3 + '@rollup/rollup-freebsd-arm64': 4.53.3 + '@rollup/rollup-freebsd-x64': 4.53.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 + '@rollup/rollup-linux-arm64-musl': 4.53.3 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 + '@rollup/rollup-linux-x64-gnu': 4.53.3 + '@rollup/rollup-linux-x64-musl': 4.53.3 + '@rollup/rollup-openharmony-arm64': 4.53.3 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 + '@rollup/rollup-win32-x64-gnu': 4.53.3 + '@rollup/rollup-win32-x64-msvc': 4.53.3 + fsevents: 2.3.3 run-applescript@7.0.0: {} - run-con@1.2.12: + run-con@1.3.2: dependencies: deep-extend: 0.6.0 - ini: 3.0.1 + ini: 4.1.3 minimist: 1.2.8 strip-json-comments: 3.1.1 @@ -9078,10 +9128,6 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 @@ -9090,6 +9136,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-push-apply@1.0.0: @@ -9107,6 +9155,13 @@ snapshots: sax@1.4.1: {} + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + secretlint@10.2.2: dependencies: '@secretlint/config-creator': 10.2.2 @@ -9119,17 +9174,75 @@ snapshots: transitivePeerDependencies: - supports-color + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.14 + node-forge: 1.3.3 + semver@5.7.2: {} semver@6.3.1: {} - semver@7.5.4: + semver@7.7.3: {} + + send@0.19.0: dependencies: - lru-cache: 6.0.0 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + send@0.19.1: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color - semver@7.7.1: {} + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color - set-blocking@2.0.0: {} + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color set-function-length@1.2.2: dependencies: @@ -9153,6 +9266,10 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 + setprototypeof@1.1.0: {} + + setprototypeof@1.2.0: {} + shallow-clone@3.0.1: dependencies: kind-of: 6.0.3 @@ -9163,7 +9280,7 @@ snapshots: shebang-regex@3.0.0: {} - shell-quote@1.8.2: {} + shell-quote@1.8.3: {} side-channel-list@1.0.0: dependencies: @@ -9193,7 +9310,7 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - signal-exit@3.0.7: {} + siginfo@2.0.0: {} signal-exit@4.1.0: {} @@ -9207,7 +9324,13 @@ snapshots: simple-concat: 1.0.1 optional: true - sisteransi@1.0.5: {} + simple-invariant@2.0.1: {} + + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 slash@3.0.0: {} @@ -9219,68 +9342,85 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - slice-ansi@5.0.0: + slice-ansi@7.1.2: dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + smol-toml@1.5.2: {} - slice-ansi@7.1.0: + sockjs@0.3.24: dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 source-map-js@1.2.1: {} - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - source-map@0.6.1: {} - spawn-command@0.0.2: {} - spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.21 + spdx-license-ids: 3.0.22 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.21 + spdx-license-ids: 3.0.22 spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.21 + spdx-license-ids: 3.0.22 + + spdx-license-ids@3.0.22: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.3 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color - spdx-license-ids@3.0.21: {} + spdy@4.0.2: + dependencies: + debug: 4.4.3 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color sprintf-js@1.0.3: {} sprintf-js@1.1.3: {} - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 + stackback@0.0.2: {} - stoppable@1.1.0: {} + statuses@1.5.0: {} - string-argv@0.3.2: {} + statuses@2.0.1: {} - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 + statuses@2.0.2: {} - string-width@3.1.0: + std-env@3.10.0: {} + + stop-iteration-iterator@1.1.0: dependencies: - emoji-regex: 7.0.3 - is-fullwidth-code-point: 2.0.0 - strip-ansi: 5.2.0 + es-errors: 1.3.0 + internal-slot: 1.1.0 + + stoppable@1.1.0: {} + + string-argv@0.3.2: {} string-width@4.2.3: dependencies: @@ -9292,13 +9432,18 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string-width@7.2.0: dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 - strip-ansi: 7.1.0 + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + string-width@8.1.0: + dependencies: + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 string.prototype.trim@1.2.10: dependencies: @@ -9306,7 +9451,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -9323,31 +9468,24 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - string_decoder@1.3.0: + string_decoder@1.1.1: dependencies: - safe-buffer: 5.2.1 - optional: true + safe-buffer: 5.1.2 - strip-ansi@5.2.0: + string_decoder@1.3.0: dependencies: - ansi-regex: 4.1.1 + safe-buffer: 5.2.1 strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: + strip-ansi@7.1.2: dependencies: - ansi-regex: 6.1.0 + ansi-regex: 6.2.2 strip-bom@3.0.0: {} - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - strip-json-comments@2.0.1: optional: true @@ -9357,18 +9495,10 @@ snapshots: dependencies: boundary: 2.0.0 - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - supports-hyperlinks@2.3.0: dependencies: has-flag: 4.0.0 @@ -9415,23 +9545,34 @@ snapshots: terminal-link@4.0.0: dependencies: - ansi-escapes: 7.0.0 + ansi-escapes: 7.2.0 supports-hyperlinks: 3.2.0 - test-exclude@6.0.0: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - text-table@0.2.0: {} textextensions@6.11.0: dependencies: editions: 6.22.0 + thingies@2.5.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + thunky@1.1.0: {} + tiny-inflate@1.0.3: {} + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinyrainbow@3.0.3: {} + tldts-core@5.7.112: {} tldts@5.7.112: @@ -9440,65 +9581,37 @@ snapshots: tmp@0.2.3: {} - tmpl@1.0.5: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - tree-kill@1.2.2: {} + to-valid-identifier@1.0.0: + dependencies: + '@sindresorhus/base62': 1.0.0 + reserved-identifiers: 1.2.0 + + toidentifier@1.0.1: {} + + totalist@3.0.1: {} + + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 trough@2.2.0: {} - ts-api-utils@1.4.3(typescript@5.9.2): + ts-api-utils@1.4.3(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 - ts-declaration-location@1.0.7(typescript@5.9.2): + ts-declaration-location@1.0.7(typescript@5.9.3): dependencies: picomatch: 4.0.3 - typescript: 5.9.2 + typescript: 5.9.3 - ts-jest@29.3.1(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(esbuild@0.17.19)(jest@29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)))(typescript@5.9.2): + tsc-files@1.1.4(typescript@5.9.3): dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.86)(ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2)) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.1 - type-fest: 4.39.1 - typescript: 5.9.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.26.10 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.10) - esbuild: 0.17.19 - - ts-node@10.9.2(@swc/core@1.11.18)(@types/node@18.19.86)(typescript@5.9.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.86 - acorn: 8.14.1 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.9.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optionalDependencies: - '@swc/core': 1.11.18 + typescript: 5.9.3 tsconfig-paths@3.15.0: dependencies: @@ -9509,9 +9622,9 @@ snapshots: tslib@2.8.1: {} - tsx@4.19.3: + tsx@4.21.0: dependencies: - esbuild: 0.25.2 + esbuild: 0.27.1 get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 @@ -9527,8 +9640,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} - type-fest@0.20.2: {} type-fest@0.21.3: {} @@ -9537,6 +9648,11 @@ snapshots: type-fest@4.39.1: {} + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -9576,12 +9692,13 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.7 - typescript@5.9.2: {} - - uc.micro@1.0.6: {} + typescript@5.9.3: {} uc.micro@2.1.0: {} + uglify-js@3.19.3: + optional: true + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -9591,10 +9708,9 @@ snapshots: underscore@1.13.7: {} - undici-types@5.26.5: {} + undici-types@6.21.0: {} - undici-types@6.19.8: - optional: true + undici-types@7.16.0: {} undici@6.21.2: {} @@ -9638,11 +9754,7 @@ snapshots: 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 + unpipe@1.0.0: {} uri-js@4.4.1: dependencies: @@ -9650,28 +9762,23 @@ snapshots: url-join@4.0.1: {} - util-deprecate@1.0.2: - optional: true - - uuid@8.3.2: {} + util-deprecate@1.0.2: {} - v8-compile-cache-lib@3.0.1: {} + utils-merge@1.0.1: {} - v8-to-istanbul@9.3.0: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 + uuid@8.3.2: {} - valibot@1.1.0(typescript@5.9.2): + valibot@1.2.0(typescript@5.9.3): optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + vary@1.1.2: {} + version-range@4.15.0: {} vfile-message@4.0.2: @@ -9684,12 +9791,114 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 + vite@7.2.6(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.3 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 20.19.26 + fsevents: 2.3.3 + tsx: 4.21.0 + yaml: 2.8.2 + + vite@7.2.6(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.3 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.2 + fsevents: 2.3.3 + tsx: 4.21.0 + yaml: 2.8.2 + + vitest@4.0.15(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + '@vitest/expect': 4.0.15 + '@vitest/mocker': 4.0.15(vite@7.2.6(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/pretty-format': 4.0.15 + '@vitest/runner': 4.0.15 + '@vitest/snapshot': 4.0.15 + '@vitest/spy': 4.0.15 + '@vitest/utils': 4.0.15 + es-module-lexer: 1.7.0 + expect-type: 1.2.2 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.2.6(@types/node@20.19.26)(tsx@4.21.0)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.19.26 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + vitest@4.0.15(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + '@vitest/expect': 4.0.15 + '@vitest/mocker': 4.0.15(vite@7.2.6(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/pretty-format': 4.0.15 + '@vitest/runner': 4.0.15 + '@vitest/snapshot': 4.0.15 + '@vitest/spy': 4.0.15 + '@vitest/utils': 4.0.15 + es-module-lexer: 1.7.0 + expect-type: 1.2.2 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.2.6(@types/node@24.10.2)(tsx@4.21.0)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.10.2 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + vscode-jsonrpc@9.0.0-next.8: {} vscode-languageclient@10.0.0-next.15: dependencies: minimatch: 10.1.1 - semver: 7.7.1 + semver: 7.7.3 vscode-languageserver-protocol: 3.17.6-next.13 vscode-languageserver-protocol@3.17.6-next.13: @@ -9707,13 +9916,84 @@ snapshots: vscode-oniguruma@2.0.1: {} - vscode-textmate@9.2.0: {} + vscode-textmate@9.3.0: {} vscode-uri@3.1.0: {} - walker@1.0.8: + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + webpack-bundle-analyzer@4.10.2: + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.15.0 + acorn-walk: 8.3.4 + commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 + gzip-size: 6.0.0 + html-escaper: 2.0.2 + opener: 1.5.2 + picocolors: 1.1.1 + sirv: 2.0.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + webpack-dev-middleware@7.4.5: + dependencies: + colorette: 2.0.20 + memfs: 4.51.1 + mime-types: 3.0.2 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.3 + + webpack-dev-server@5.2.2: + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.7 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + express: 4.22.1 + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + ipaddr.js: 2.3.0 + launch-editor: 2.12.0 + open: 10.1.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.5 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + websocket-driver@0.7.4: dependencies: - makeerror: 1.0.12 + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} whatwg-encoding@3.1.1: dependencies: @@ -9752,8 +10032,6 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-module@2.0.1: {} - which-pm@3.0.1: dependencies: load-yaml-file: 0.2.0 @@ -9772,13 +10050,14 @@ snapshots: 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@5.1.0: - dependencies: - ansi-styles: 3.2.1 - string-width: 3.1.0 - strip-ansi: 5.2.0 + wordwrap@1.0.0: {} wrap-ansi@6.2.0: dependencies: @@ -9794,28 +10073,21 @@ snapshots: wrap-ansi@8.1.0: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.0 - - wrap-ansi@9.0.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrap-ansi@9.0.2: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrappy@1.0.2: {} - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 + ws@7.5.10: {} + + ws@8.18.3: {} xml2js@0.5.0: dependencies: @@ -9832,47 +10104,15 @@ snapshots: dependencies: '@babel/runtime-corejs3': 7.28.4 - y18n@4.0.3: {} - - y18n@5.0.8: {} - - yallist@3.1.1: {} - yallist@4.0.0: {} - yaml@2.7.1: {} + yaml@2.8.2: {} - yaml@2.8.1: {} - - yargs-parser@13.1.2: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - - yargs-parser@21.1.1: {} - - yargs@13.3.2: + yauzl-promise@4.0.0: dependencies: - cliui: 5.0.0 - find-up: 3.0.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 3.1.0 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 13.1.2 - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 + '@node-rs/crc32': 1.10.6 + is-it-type: 5.1.3 + simple-invariant: 2.0.1 yauzl@2.10.0: dependencies: @@ -9883,8 +10123,6 @@ snapshots: dependencies: buffer-crc32: 0.2.13 - yn@3.1.1: {} - yocto-queue@0.1.0: {} yoctocolors-cjs@2.1.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2715c16..6d11720 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,63 @@ packages: - - server - client + - server + - shared + - syntaxes + - tools - test/static/aglint catalog: - '@adguard/aglint': ^4.0.0-beta.1 + '@adguard/aglint': ^4.0.0-beta.3 + '@adguard/agtree': ^2.3.0 + '@adguard/changelog-tools': ^0.0.1 + '@rspack/cli': ^1.6.7 + '@rspack/core': ^1.1.7 + '@types/fs-extra': ^11.0.4 + '@types/node': ^20.19.26 + '@types/plist': ^3.0.5 + '@types/resolve': ^1.20.6 + '@types/semver': ^7.7.1 + '@types/vscode': ^1.74.0 + '@typescript-eslint/eslint-plugin': ^7.5.0 + '@typescript-eslint/parser': ^7.5.0 + '@vitest/coverage-v8': ^4.0.15 + '@vitest/expect': ^4.0.15 + '@vscode/vsce': ^3.7.1 + chokidar: ^5.0.0 + ci-info: ^4.3.1 + cross-env: ^10.1.0 + debounce: ^3.0.0 + eslint: 8.57.1 + eslint-config-airbnb-base: ^15.0.0 + eslint-config-airbnb-typescript: ^18.0.0 + eslint-plugin-boundaries: ^5.3.1 + eslint-plugin-import: ^2.32.0 + eslint-plugin-import-newlines: ^1.4.0 + eslint-plugin-jsdoc: ^61.5.0 + eslint-plugin-n: ^17.23.1 + fast-glob: ^3.3.3 + fs-extra: ^11.3.1 + husky: ^9.1.7 + jsdoc: ^4.0.5 + lint-staged: ^16.2.7 + markdownlint: ^0.40.0 + markdownlint-cli: ^0.46.0 + mkdirp: ^3.0.1 + ovsx: ^0.10.7 + plist: ^3.1.0 + preferred-pm: ^4.1.1 + resolve: ^1.22.11 + rimraf: ^6.1.2 + semver: ^7.7.3 + tsc-files: 1.1.4 + tsx: ^4.21.0 + typescript: ^5.9.3 + valibot: ^1.2.0 + vitest: ^4.0.15 + vscode-languageclient: 10.0.0-next.15 + vscode-languageserver: 10.0.0-next.13 + vscode-languageserver-textdocument: ^1.0.12 + vscode-oniguruma: ^2.0.1 + vscode-textmate: ^9.3.0 + vscode-uri: ^3.1.0 + yaml: ^2.8.2 diff --git a/server/.eslintrc.cjs b/server/.eslintrc.cjs index 42068cc..9846311 100644 --- a/server/.eslintrc.cjs +++ b/server/.eslintrc.cjs @@ -1,7 +1,15 @@ +const path = require('node:path'); + module.exports = { extends: '../.eslintrc.cjs', + parserOptions: { + tsconfigRootDir: path.join(__dirname), + project: 'tsconfig.json', + }, rules: { + // Disable the base rule to avoid conflicts 'no-restricted-imports': 'off', + // Only allow type imports from aglint (server-specific rule) '@typescript-eslint/no-restricted-imports': [ 'error', { diff --git a/server/.lintstagedrc.js b/server/.lintstagedrc.js new file mode 100644 index 0000000..a589197 --- /dev/null +++ b/server/.lintstagedrc.js @@ -0,0 +1,33 @@ +/** @type {import('lint-staged').Configuration} */ +const path = require('node:path'); + +/** + * Make file path relative to the current working directory + * + * @param {string} file File path + * + * @returns {string} Relative path + */ +const makeRelative = (file) => path.relative(process.cwd(), file); + +module.exports = { + '**/*.md': 'markdownlint', + '**/*.js': 'eslint --cache', + '**/*.ts': [ + // Type-check only the staged TS files while still honoring tsconfig + // Exclude config files that import build tools (they're checked by tsconfig.json) + (files) => { + const filesToCheck = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return filesToCheck.length > 0 ? `tsc-files --noEmit ${filesToCheck.join(' ')}` : 'echo "No files to type-check"'; + }, + + // Run tests that are related to those changed files + (files) => { + const testableFiles = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return testableFiles.length > 0 ? `vitest related --run ${testableFiles.map(makeRelative).join(' ')}` : 'echo "No test files"'; + }, + + // Lint the staged TS files + 'eslint --cache', + ], +}; diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..1adc9ee --- /dev/null +++ b/server/README.md @@ -0,0 +1,10 @@ +# @vscode-adblock-syntax/server + +Language server for Adblock/AdGuard/uBlock filters syntax. + +This package implements the Language Server Protocol (LSP) server that provides: + +- AGLint integration for real-time linting +- Diagnostics and error reporting +- Auto-discovery of AGLint installations +- Configuration file management diff --git a/server/package.json b/server/package.json index 16cea9e..b341ee7 100644 --- a/server/package.json +++ b/server/package.json @@ -1,27 +1,44 @@ { - "name": "aglint-server", + "name": "@vscode-adblock-syntax/server", + "description": "Language server for Adblock/AdGuard/uBlock filters syntax.", "version": "2.0.0", "license": "MIT", "author": "AdGuard Software Ltd.", "private": true, "engines": { - "node": ">=16" + "node": ">=20.0.0" + }, + "scripts": { + "prebuild": "rimraf out", + "build": "rspack", + "test": "vitest", + "lint:code": "eslint . --cache --ext .ts --ext .js --ext .cjs", + "lint:md": "markdownlint . --ignore-path ../.markdownlintignore", + "lint": "pnpm run lint:code && pnpm run lint:md" }, "dependencies": { - "debounce": "^3.0.0", - "fast-glob": "^3.3.3", - "preferred-pm": "^4.1.1", - "resolve": "^1.22.11", - "vscode-languageserver": "10.0.0-next.13", - "vscode-languageserver-textdocument": "^1.0.8", - "vscode-uri": "^3.1.0", - "yaml": "^2.7.1" + "@vscode-adblock-syntax/shared": "workspace:^", + "debounce": "catalog:", + "fast-glob": "catalog:", + "preferred-pm": "catalog:", + "resolve": "catalog:", + "semver": "catalog:", + "vscode-languageserver": "catalog:", + "vscode-languageserver-textdocument": "catalog:", + "vscode-uri": "catalog:", + "yaml": "catalog:" }, "devDependencies": { "@adguard/aglint": "catalog:", - "@adguard/agtree": "^2.3.0", - "@types/resolve": "^1.20.6", - "@types/semver": "^7.5.0", - "semver": "^7.5.4" + "@adguard/agtree": "catalog:", + "@rspack/cli": "catalog:", + "@rspack/core": "catalog:", + "@types/resolve": "catalog:", + "@types/semver": "catalog:", + "@vitest/coverage-v8": "catalog:", + "rimraf": "catalog:", + "tsc-files": "catalog:", + "tsx": "catalog:", + "vitest": "catalog:" } } diff --git a/server/rspack.config.ts b/server/rspack.config.ts new file mode 100644 index 0000000..4515732 --- /dev/null +++ b/server/rspack.config.ts @@ -0,0 +1,122 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { resolve } from 'node:path'; + +import { defineConfig } from '@rspack/cli'; + +const isProduction = process.env.NODE_ENV === 'production'; + +export default defineConfig({ + target: 'node', + mode: isProduction ? 'production' : 'development', + + stats: 'normal', + + entry: { + server: './src/server.ts', + }, + + output: { + path: resolve(__dirname, 'out'), + filename: '[name].js', // -> server.js + chunkFilename: '[name].[contenthash:8].js', // -> vendors.abc12345.js, agtree-compatibility.def67890.js + libraryTarget: 'commonjs2', + clean: true, + }, + + resolve: { + extensions: ['.ts', '.js'], + }, + + module: { + rules: [ + { + test: /\.ts$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + }, + target: 'es2020', + }, + }, + }, + exclude: /node_modules/, + }, + ], + }, + + externals: { + vscode: 'commonjs vscode', + }, + + optimization: { + minimize: isProduction, + splitChunks: { + chunks: 'all', + minSize: 20000, + cacheGroups: { + // Manually split agtree compatibility tables (important to separate) + agtreeCompatibilityTablesData: { + test: /[\\/]node_modules[\\/]@adguard[\\/]agtree[\\/]dist[\\/]compatibility-table-data\.js/, + name: 'vendors/agtree-compatibility-tables-data', + chunks: 'all', + priority: 40, + reuseExistingChunk: true, + enforce: true, + }, + // Manually split agtree (important package) + agtreeVendor: { + test: /[\\/]node_modules[\\/]@adguard[\\/]agtree[\\/]/, + name: 'vendors/agtree', + chunks: 'all', + priority: 35, + reuseExistingChunk: true, + }, + // Automatically split all other vendors by package name + defaultVendors: { + test: /[\\/]node_modules[\\/]/, + name(module: any) { + const { context } = module; + + // Handle pnpm's .pnpm directory structure + // pnpm creates these paths: + // - node_modules/.pnpm/@/node_modules/ + // - node_modules/.pnpm/@scope+package@/node_modules/@scope/package + // - node_modules/.pnpm/node_modules/ (edge case) + const pnpmMatch = context.match( + /[\\/]\.pnpm[\\/](?:@?[^@/\\]+@[^/\\]+[\\/])?node_modules[\\/]((?:@[^/\\]+[\\/])?[^/\\]+)/, + ); + if (pnpmMatch) { + const packageName = pnpmMatch[1] + .replace('@', '') + .replace(/\//g, '-'); + return `vendors/${packageName}`; + } + + // Standard node_modules structure (npm/yarn) + // - node_modules/ + // - node_modules/@scope/package + const packageNameMatch = context.match( + /[\\/]node_modules[\\/]((?:@[^/\\]+[\\/])?[^/\\]+)/, + ); + if (packageNameMatch) { + const packageName = packageNameMatch[1] + .replace('@', '') + .replace(/\//g, '-'); + return `vendors/${packageName}`; + } + + return 'vendors/vendor'; + }, + chunks: 'all', + priority: 10, + reuseExistingChunk: true, + }, + }, + }, + }, + + devtool: isProduction ? false : 'source-map', +}); diff --git a/server/src/code-actions/disable-rule.ts b/server/src/code-actions/disable-rule.ts new file mode 100644 index 0000000..aebead8 --- /dev/null +++ b/server/src/code-actions/disable-rule.ts @@ -0,0 +1,261 @@ +/** + * @file Code actions for disabling AGLint rules. + */ + +import { ConfigCommentRuleParser } from '@adguard/agtree'; +import { + CodeAction, + CodeActionKind, + Position, + Range, + TextDocumentEdit, + TextEdit, +} from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import { LF, SPACE } from '../common/constants'; +import type { ServerContext } from '../context/server-context'; + +import { getPreviousLineText, parseConfigCommentTolerant } from './utils'; + +/** + * Create code action to disable AGLint for a line (no specific rule). + * + * @param textDocument Text document. + * @param line Line number (0-based). + * @param context Server context. + * + * @returns Code action to disable AGLint for the line. + */ +export function createDisableAglintAction( + textDocument: TextDocument, + line: number, + context: ServerContext, +): CodeAction { + const action = CodeAction.create('Disable AGLint for this line', CodeActionKind.QuickFix); + + // Make '! aglint-disable-next-line' prefix + const configCommentType = context.aglintContext?.aglint.linter.LinterConfigCommentType; + const disableNextLineType = configCommentType?.DisableNextLine ?? 'aglint-disable-next-line'; + const aglintDisableNextLinePrefix = `!${SPACE}${disableNextLineType}`; + + if (line === 0) { + // If there are no previous lines, just insert the comment before the problematic line + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${LF}`, + )], + ), + ], + }; + return action; + } + + // If we have previous lines, check if there's already a disable comment + const prevLine = getPreviousLineText(textDocument, line); + if (!prevLine) { + // Shouldn't happen, but handle gracefully + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${LF}`, + )], + ), + ], + }; + return action; + } + + const commentNode = parseConfigCommentTolerant( + prevLine.trim(), + (msg) => context.connection.console.debug(`[lsp] ${msg}`), + ); + const previousLine = line - 1; + + // If the previous line is '! aglint-disable-next-line some-rule-name', replace it + // to '! aglint-disable-next-line' - disable AGLint completely for the line + if ( + commentNode + && disableNextLineType + && commentNode.command.value === disableNextLineType + && commentNode.params + ) { + delete commentNode.params; + + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.replace( + Range.create( + Position.create(previousLine, 0), + Position.create(previousLine, prevLine.length), + ), + ConfigCommentRuleParser.generate(commentNode), + )], + ), + ], + }; + return action; + } + + // Otherwise just insert the comment before the problematic line + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${LF}`, + )], + ), + ], + }; + + return action; +} + +/** + * Create code action to disable a specific AGLint rule for a line. + * + * @param textDocument Text document. + * @param line Line number (0-based). + * @param ruleCode Rule code to disable. + * @param context Server context. + * + * @returns Code action to disable the specific rule. + */ +export function createDisableRuleAction( + textDocument: TextDocument, + line: number, + ruleCode: string | number, + context: ServerContext, +): CodeAction { + const action = CodeAction.create( + `Disable AGLint rule '${ruleCode}' for this line`, + CodeActionKind.QuickFix, + ); + + // Make '! aglint-disable-next-line' prefix + const disableNextLineType = context.aglintContext?.aglint.linter + .LinterConfigCommentType.DisableNextLine ?? 'aglint-disable-next-line'; + const aglintDisableNextLinePrefix = `!${SPACE}${disableNextLineType}`; + + if (line === 0) { + // If there are no previous lines, just insert the comment before the problematic line + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${SPACE}${ruleCode}${LF}`, + )], + ), + ], + }; + return action; + } + + // If we have previous lines, check if there's already a disable comment + const prevLine = getPreviousLineText(textDocument, line); + if (!prevLine) { + // Shouldn't happen, but handle gracefully + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${SPACE}${ruleCode}${LF}`, + )], + ), + ], + }; + return action; + } + + const commentNode = parseConfigCommentTolerant( + prevLine.trim(), + (msg) => context.connection.console.debug(`[lsp] ${msg}`), + ); + const previousLine = line - 1; + + // If the previous line is '! aglint-disable-next-line some-rule-name', add the new rule + if ( + commentNode + && disableNextLineType + && commentNode.command.value === disableNextLineType + && commentNode.params + && commentNode.params.type === 'ParameterList' + ) { + commentNode.params.children.push({ + type: 'Value', + value: String(ruleCode), + }); + + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.replace( + Range.create( + Position.create(previousLine, 0), + Position.create(previousLine, prevLine.length), + ), + ConfigCommentRuleParser.generate(commentNode), + )], + ), + ], + }; + return action; + } + + // Otherwise just insert the comment before the problematic line + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.insert( + Position.create(line, 0), + `${aglintDisableNextLinePrefix}${SPACE}${ruleCode}${LF}`, + )], + ), + ], + }; + + return action; +} + +/** + * Create code action to remove a problematic rule entirely. + * + * @param textDocument Text document. + * @param line Line number (0-based). + * + * @returns Code action to remove the rule. + */ +export function createRemoveRuleAction(textDocument: TextDocument, line: number): CodeAction { + const action = CodeAction.create('Remove this rule', CodeActionKind.QuickFix); + + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [TextEdit.del(Range.create( + Position.create(line, 0), + Position.create(line + 1, 0), + ))], + ), + ], + }; + + return action; +} diff --git a/server/src/code-actions/fix-actions.ts b/server/src/code-actions/fix-actions.ts new file mode 100644 index 0000000..5b980f5 --- /dev/null +++ b/server/src/code-actions/fix-actions.ts @@ -0,0 +1,90 @@ +/** + * @file Code actions for AGLint fixes and suggestions. + */ + +import { CodeAction, CodeActionKind, TextDocumentEdit } from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import type { ServerContext } from '../context/server-context'; + +import { convertAglintFixToVscodeTextEdit } from './utils'; + +/** + * Create code action to apply an AGLint fix. + * + * @param textDocument Text document. + * @param ruleCode Rule code. + * @param fix Fix command from AGLint. + * @param context Server context. + * + * @returns Code action to apply the fix. + */ +export function createFixAction( + textDocument: TextDocument, + ruleCode: string | number, + fix: unknown, + context: ServerContext, +): CodeAction | null { + if (!context.aglintContext?.aglint.linter.isLinterFixCommand(fix)) { + return null; + } + + const action = CodeAction.create( + `Fix AGLint rule '${ruleCode}'`, + CodeActionKind.QuickFix, + ); + + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [convertAglintFixToVscodeTextEdit(textDocument, fix)], + ), + ], + }; + + return action; +} + +/** + * Create code actions for AGLint suggestions. + * + * @param textDocument Text document. + * @param ruleCode Rule code. + * @param suggestions Suggestions from AGLint. + * @param context Server context. + * + * @returns Array of code actions for suggestions. + */ +export function createSuggestionActions( + textDocument: TextDocument, + ruleCode: string | number, + suggestions: unknown, + context: ServerContext, +): CodeAction[] { + const actions: CodeAction[] = []; + + if (!context.aglintContext?.aglint.linter.isLinterSuggestions(suggestions)) { + return actions; + } + + for (const suggestion of suggestions) { + const action = CodeAction.create( + `Apply suggestion '${suggestion.message}' from AGLint rule '${ruleCode}'`, + CodeActionKind.QuickFix, + ); + + action.edit = { + documentChanges: [ + TextDocumentEdit.create( + { uri: textDocument.uri, version: textDocument.version }, + [convertAglintFixToVscodeTextEdit(textDocument, suggestion.fix)], + ), + ], + }; + + actions.push(action); + } + + return actions; +} diff --git a/server/src/code-actions/index.ts b/server/src/code-actions/index.ts new file mode 100644 index 0000000..b510dd8 --- /dev/null +++ b/server/src/code-actions/index.ts @@ -0,0 +1,64 @@ +/** + * @file Code action handler - provides quick fixes for AGLint diagnostics. + */ + +import type { CodeAction, CodeActionParams } from 'vscode-languageserver/node'; + +import type { ServerContext } from '../context/server-context'; + +import { createDisableAglintAction, createDisableRuleAction, createRemoveRuleAction } from './disable-rule'; +import { createFixAction, createSuggestionActions } from './fix-actions'; + +/** + * Handle code action request from the client. + * + * @param params Code action parameters. + * @param context Server context. + * + * @returns Array of code actions. + */ +export function handleCodeAction(params: CodeActionParams, context: ServerContext): CodeAction[] | undefined { + const textDocument = context.documents.get(params.textDocument.uri); + if (textDocument === undefined) { + return undefined; + } + + const { diagnostics } = params.context; + const actions: CodeAction[] = []; + + for (const diagnostic of diagnostics) { + const { code, range } = diagnostic; + const { line } = range.start; + + // If no code, it's likely a parsing error - offer to disable AGLint or remove the rule + if (!code) { + actions.push(createDisableAglintAction(textDocument, line, context)); + actions.push(createRemoveRuleAction(textDocument, line)); + continue; + } + + // If there's a fix available, offer to apply it + if (diagnostic.data?.fix) { + const fixAction = createFixAction(textDocument, code, diagnostic.data.fix, context); + if (fixAction) { + actions.push(fixAction); + } + } + + // If there are suggestions, offer to apply them + if (diagnostic.data?.suggestions) { + const suggestionActions = createSuggestionActions( + textDocument, + code, + diagnostic.data.suggestions, + context, + ); + actions.push(...suggestionActions); + } + + // Always offer to disable the specific rule + actions.push(createDisableRuleAction(textDocument, line, code, context)); + } + + return actions; +} diff --git a/server/src/code-actions/utils.ts b/server/src/code-actions/utils.ts new file mode 100644 index 0000000..db5bbc9 --- /dev/null +++ b/server/src/code-actions/utils.ts @@ -0,0 +1,94 @@ +/** + * @file Shared utilities for code actions. + */ + +import type { LinterFixCommand, LinterOffsetRange } from '@adguard/aglint/linter'; +import type { ConfigCommentRule } from '@adguard/agtree'; +import { ConfigCommentRuleParser } from '@adguard/agtree'; +import { + Position, + Range, + TextEdit, + uinteger, +} from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import { getErrorMessage } from '../utils/error'; + +/** + * Parse AGLint config comment rule in a tolerant way (does not throw on parsing error). + * + * @param rule Rule to parse. + * @param logError Optional error logging function. + * + * @returns AGLint config comment rule node or null if parsing failed. + */ +export function parseConfigCommentTolerant( + rule: string, + logError?: (message: string) => void, +): ConfigCommentRule | null { + try { + return ConfigCommentRuleParser.parse(rule); + } catch (error: unknown) { + if (logError) { + logError(`'${rule}' is not a valid AGLint config comment rule: ${getErrorMessage(error)}`); + } + return null; + } +} + +/** + * Convert AGLint offset range to VSCode range. + * + * @param textDocument Text document. + * @param range AGLint offset range. + * + * @returns VSCode range. + */ +export function convertAglintOffsetRangeToVscodeRange( + textDocument: TextDocument, + range: LinterOffsetRange, +): Range { + const [startOffset, endOffset] = range; + const start = textDocument.positionAt(startOffset); + const end = textDocument.positionAt(endOffset); + return Range.create(start, end); +} + +/** + * Convert AGLint fix to VSCode text edit. + * + * @param textDocument Text document. + * @param fix AGLint fix. + * + * @returns VSCode text edit. + */ +export function convertAglintFixToVscodeTextEdit(textDocument: TextDocument, fix: LinterFixCommand): TextEdit { + return TextEdit.replace( + convertAglintOffsetRangeToVscodeRange(textDocument, fix.range), + fix.text, + ); +} + +/** + * Get previous line text from document. + * + * @param textDocument Text document. + * @param line Line number (0-based). + * + * @returns Previous line text or undefined if line is 0. + */ +export function getPreviousLineText(textDocument: TextDocument, line: number): string | undefined { + if (line === 0) { + return undefined; + } + + const previousLine = line - 1; + return textDocument.getText( + Range.create( + Position.create(previousLine, 0), + // Note: we do not know the length of the previous line, so we use the max value + Position.create(previousLine, uinteger.MAX_VALUE), + ), + ); +} diff --git a/server/src/context/aglint-context.ts b/server/src/context/aglint-context.ts index 68dd7b2..cddcee7 100644 --- a/server/src/context/aglint-context.ts +++ b/server/src/context/aglint-context.ts @@ -8,8 +8,8 @@ import type { Connection, TextDocuments } from 'vscode-languageserver/node'; import type { TextDocument } from 'vscode-languageserver-textdocument'; import { LSPFileSystemAdapter } from '../adapters/fs'; -import type { LoadedAglint } from '../utils/aglint-loader'; -import { loadAglintModule } from '../utils/aglint-loader'; +import type { LoadedAglint } from '../loaders/aglint'; +import { loadAglintModule } from '../loaders/aglint'; /** * Encapsulates all AGLint-related state and dependencies. diff --git a/server/src/context/server-context.ts b/server/src/context/server-context.ts new file mode 100644 index 0000000..ef233eb --- /dev/null +++ b/server/src/context/server-context.ts @@ -0,0 +1,156 @@ +/** + * @file Server context - centralized state management for the language server. + */ + +import type { Connection, TextDocuments } from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import { LintingCache } from '../linting/cache'; +import type { ExtensionSettings } from '../settings'; +import { defaultSettings } from '../settings'; + +import type { AglintContext } from './aglint-context'; + +/** + * Centralized server context holding all shared state. + */ +export class ServerContext { + /** + * Language server connection. + */ + public connection: Connection; + + /** + * Text document manager. + */ + public documents: TextDocuments; + + /** + * Whether the client supports workspace/configuration request. + */ + public hasConfigurationCapability = false; + + /** + * Whether the client supports workspace/workspaceFolders request. + */ + public hasWorkspaceFolderCapability = false; + + /** + * Root folder of the VSCode workspace. + */ + public workspaceRoot: string | undefined; + + /** + * Current extension settings. + */ + public settings: ExtensionSettings = defaultSettings; + + /** + * Initial debug mode from VSCode log level. + */ + public initialDebugMode = false; + + /** + * AGLint context instance, if initialized. + */ + public aglintContext: AglintContext | undefined; + + /** + * Flag to track if AGLint loading has failed. + */ + public aglintLoadingFailed = false; + + /** + * Flag to track if AGLint loading is currently in progress. + */ + public aglintLoading = false; + + /** + * Cache for linting results. + */ + public lintingCache: LintingCache; + + /** + * Creates a new server context. + * + * @param connection Language server connection. + * @param documents Text document manager. + */ + constructor(connection: Connection, documents: TextDocuments) { + this.connection = connection; + this.documents = documents; + this.lintingCache = new LintingCache(); + } + + /** + * Update the extension settings. + * + * @param settings New settings to apply. + */ + public updateSettings(settings: ExtensionSettings): void { + this.settings = settings; + } + + /** + * Update the initial debug mode flag. + * + * @param enabled Whether debug mode is enabled. + */ + public updateInitialDebugMode(enabled: boolean): void { + this.initialDebugMode = enabled; + } + + /** + * Update the AGLint context. + * + * @param context New AGLint context or undefined to clear. + */ + public updateAglintContext(context: AglintContext | undefined): void { + this.aglintContext = context; + } + + /** + * Set the AGLint loading state. + * + * @param loading Whether AGLint is currently loading. + */ + public setAglintLoading(loading: boolean): void { + this.aglintLoading = loading; + } + + /** + * Set the AGLint loading failed state. + * + * @param failed Whether AGLint loading has failed. + */ + public setAglintLoadingFailed(failed: boolean): void { + this.aglintLoadingFailed = failed; + } + + /** + * Set the workspace root path. + * + * @param root Workspace root path or undefined. + */ + public setWorkspaceRoot(root: string | undefined): void { + this.workspaceRoot = root; + } + + /** + * Set whether the client supports configuration capability. + * + * @param hasCapability Whether the capability is supported. + */ + public setConfigurationCapability(hasCapability: boolean): void { + this.hasConfigurationCapability = hasCapability; + } + + /** + * Set whether the client supports workspace folder capability. + * + * @param hasCapability Whether the capability is supported. + */ + public setWorkspaceFolderCapability(hasCapability: boolean): void { + this.hasWorkspaceFolderCapability = hasCapability; + } +} diff --git a/server/src/handlers/configuration.ts b/server/src/handlers/configuration.ts new file mode 100644 index 0000000..cbcafb8 --- /dev/null +++ b/server/src/handlers/configuration.ts @@ -0,0 +1,216 @@ +/** + * @file Settings operations - configuration and settings management for the language server. + */ + +import { pathToFileURL } from 'node:url'; + +import debounce from 'debounce'; +import type { Connection } from 'vscode-languageserver/node'; + +import { AglintContext } from '../context/aglint-context'; +import type { ServerContext } from '../context/server-context'; +import { refreshLinter, removeAllDiagnostics } from '../linting/orchestration'; +import { defaultSettings } from '../settings'; + +/** + * Fetch settings from the workspace configuration. + * + * @param serverContext Server context. + * @param connection Language server connection. + */ +async function fetchSettings(serverContext: ServerContext, connection: Connection): Promise { + if (serverContext.hasConfigurationCapability) { + const scopeUri = serverContext.workspaceRoot + ? pathToFileURL(serverContext.workspaceRoot).toString() + : undefined; + const receivedSettings = await connection.workspace.getConfiguration({ scopeUri, section: 'adblock' }); + + // Update the settings. No need to validate them, VSCode does this for us based on the schema + // specified in the package.json + // If we didn't receive any settings, use the default ones + serverContext.updateSettings(receivedSettings || defaultSettings); + } else { + serverContext.updateSettings(defaultSettings); + } +} + +/** + * Handle cache management when cache setting changes. + * + * @param serverContext Server context. + * @param connection Language server connection. + * @param previousEnableCache Previous cache enable state. + */ +function handleCacheChanges( + serverContext: ServerContext, + connection: Connection, + previousEnableCache: boolean, +): void { + // Clear cache if caching was disabled + if (previousEnableCache && !serverContext.settings.enableInMemoryAglintCache) { + serverContext.lintingCache.clear(); + connection.console.info('[lsp] AGLint cache cleared (caching disabled)'); + } + + // Log cache setting changes at the end + if (previousEnableCache !== serverContext.settings.enableInMemoryAglintCache) { + if (serverContext.settings.enableInMemoryAglintCache) { + connection.console.info('[lsp] In-memory linting cache enabled'); + } else { + connection.console.info('[lsp] In-memory linting cache disabled'); + serverContext.lintingCache.clear(); + connection.console.debug('[lsp] Cache cleared'); + } + } +} + +/** + * Check if settings have changed and warrant a full refresh. + * + * @param serverContext Server context. + * @param previousEnableAglint Previous AGLint enable state. + * @param previousEnableCache Previous cache enable state. + * + * @returns True if settings changed and need processing. + */ +function shouldProcessSettings( + serverContext: ServerContext, + previousEnableAglint: boolean, + previousEnableCache: boolean, +): boolean { + // If nothing changed and AGLint is already initialized OR loading failed, skip heavy work + if ( + (serverContext.aglintContext || serverContext.aglintLoadingFailed) + && previousEnableAglint === serverContext.settings.enableAglint + && previousEnableCache === serverContext.settings.enableInMemoryAglintCache + ) { + return false; + } + return true; +} + +/** + * Initialize AGLint context if needed. + * + * @param serverContext Server context. + * @param connection Language server connection. + * + * @returns True if initialization succeeded or was not needed, false if failed. + */ +async function ensureAglintContext( + serverContext: ServerContext, + connection: Connection, +): Promise { + // Check if initialization is needed + if ( + serverContext.aglintContext + || serverContext.aglintLoadingFailed + || serverContext.aglintLoading + ) { + return true; + } + + if (!serverContext.workspaceRoot) { + connection.console.error('[lsp] Workspace root is not defined'); + removeAllDiagnostics(serverContext.documents, connection); + return false; + } + + // Set loading flag to prevent concurrent initialization + serverContext.setAglintLoading(true); + + try { + const context = await AglintContext.create( + connection, + serverContext.documents, + serverContext.workspaceRoot, + serverContext.initialDebugMode, + ); + + serverContext.updateAglintContext(context); + + if (!serverContext.aglintContext) { + serverContext.setAglintLoadingFailed(true); + connection.console.info( + '[lsp] AGLint loading failed. Will retry when package.json or node_modules changes.', + ); + removeAllDiagnostics(serverContext.documents, connection); + return false; + } + + return true; + } finally { + // Always clear loading flag + serverContext.setAglintLoading(false); + } +} + +/** + * Pull the settings from VSCode and update the settings variable. It also + * re-builts the cached paths and revalidates any open text documents. + * + * "In this model the clients simply sends an empty change event to signal that the settings have + * changed and must be reread". + * + * @see https://github.com/microsoft/vscode-languageserver-node/issues/380#issuecomment-414691493 + * + * @param serverContext Server context. + * @param connection Language server connection. + */ +export async function pullSettings(serverContext: ServerContext, connection: Connection): Promise { + const previousEnableAglint = serverContext.settings.enableAglint; + const previousEnableCache = serverContext.settings.enableInMemoryAglintCache; + + // Fetch updated settings + await fetchSettings(serverContext, connection); + + // Check if we need to process settings changes + if (!shouldProcessSettings(serverContext, previousEnableAglint, previousEnableCache)) { + return; + } + + // Handle cache changes + handleCacheChanges(serverContext, connection, previousEnableCache); + + // Send status notification about AGLint being enabled/disabled + connection.sendNotification('aglint/status', { aglintEnabled: serverContext.settings.enableAglint }); + + // If AGLint is disabled, clean up and return early + if (!serverContext.settings.enableAglint) { + removeAllDiagnostics(serverContext.documents, connection); + connection.console.debug('[lsp] AGLint is disabled'); + return; + } + + connection.console.debug('[lsp] AGLint integration is enabled'); + + // Initialize AGLint context if needed + const contextReady = await ensureAglintContext(serverContext, connection); + if (!contextReady) { + return; + } + + await refreshLinter(serverContext, connection); +} + +/** + * Create a debounced function to retry AGLint loading after package.json or node_modules changes. + * Waits 2 seconds for file system operations to settle before attempting reload. + * + * @param serverContext Server context. + * @param connection Language server connection. + * + * @returns Debounced retry function. + */ +export function createRetryAglintLoading( + serverContext: ServerContext, + connection: Connection, +): ReturnType Promise>> { + return debounce(async () => { + if (serverContext.aglintLoadingFailed && !serverContext.aglintLoading) { + connection.console.info('[lsp] Retrying AGLint loading after package changes settled'); + serverContext.setAglintLoadingFailed(false); + await pullSettings(serverContext, connection); + } + }, 2000); +} diff --git a/server/src/handlers/event-handlers.ts b/server/src/handlers/event-handlers.ts new file mode 100644 index 0000000..fa9baea --- /dev/null +++ b/server/src/handlers/event-handlers.ts @@ -0,0 +1,176 @@ +/** + * @file Event handlers - registration and handling of language server events. + */ + +import { fileURLToPath } from 'node:url'; + +import type { Connection, TextDocuments } from 'vscode-languageserver/node'; +import { DidChangeConfigurationNotification } from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import { handleCodeAction } from '../code-actions'; +import type { ServerContext } from '../context/server-context'; +import { createDebouncedLintFile, refreshLinter, removeAllDiagnostics } from '../linting/orchestration'; + +import { createRetryAglintLoading, pullSettings } from './configuration'; + +/** + * Register all event handlers for the language server. + * + * @param connection Language server connection. + * @param documents Text document manager. + * @param serverContext Server context. + */ +export function registerEventHandlers( + connection: Connection, + documents: TextDocuments, + serverContext: ServerContext, +): void { + // Create debounced lintFile function + const lintFileDebounced = createDebouncedLintFile(serverContext, connection); + + // Create retry AGLint loading function + const retryAglintLoading = createRetryAglintLoading(serverContext, connection); + + // Code action handler + connection.onCodeAction((params) => handleCodeAction(params, serverContext)); + + // Configuration change handler + connection.onDidChangeConfiguration(async () => { + await pullSettings(serverContext, connection); + }); + + // Log level change handler + connection.onNotification('client/logLevelChanged', (params: { enableAglintDebug: boolean }) => { + const requestedDebugMode = params.enableAglintDebug; + + // If AGLint context exists, check current state and update if needed + if (serverContext.aglintContext) { + const currentDebugMode = serverContext.aglintContext.debuggerInstance.isEnabled(); + + // If debug state didn't change, nothing to do + if (currentDebugMode === requestedDebugMode) { + return; + } + + const status = requestedDebugMode ? 'enabled' : 'disabled'; + connection.console.info(`[lsp] AGLint debug mode ${status} (log level changed)`); + + if (requestedDebugMode) { + serverContext.aglintContext.debuggerInstance.enable(); + } else { + serverContext.aglintContext.debuggerInstance.disable(); + } + } else { + // AGLint not initialized yet, just store the initial state for when it is created + serverContext.updateInitialDebugMode(requestedDebugMode); + } + }); + + // Watched files change handler + connection.onDidChangeWatchedFiles(async (events) => { + const { changes } = events; + let shouldRetryAglint = false; + let hasConfigChanges = false; + + connection.console.debug(`[lsp] Watched files changed: ${changes.length} file(s)`); + + for (const change of changes) { + const filePath = fileURLToPath(change.uri); + connection.console.info(`[lsp] File changed: ${filePath} (type: ${change.type})`); + + // Check if package.json or node_modules changed (for AGLint installation detection) + if (filePath.endsWith('package.json') || filePath.endsWith('node_modules')) { + shouldRetryAglint = true; + } + + // Check if it's a config file change + const isConfigFile = filePath.includes('.aglintrc') || filePath.includes('aglint.config'); + if (isConfigFile) { + hasConfigChanges = true; + connection.console.debug(`[lsp] Config file detected: ${filePath}`); + } + + // Notify AGLint's linter tree about the change + if (serverContext.aglintContext) { + try { + // eslint-disable-next-line no-await-in-loop + await serverContext.aglintContext.linterTree.changed(filePath); + connection.console.debug(`[lsp] Notified linterTree about change: ${filePath}`); + } catch (error) { + connection.console.error(`[lsp] Error notifying linterTree: ${String(error)}`); + } + } else { + connection.console.warn('[lsp] AGLint context not initialized, skipping linterTree notification'); + } + } + + // If package.json or node_modules changed and loading previously failed, schedule a retry + // Use debounce to wait for file system operations to settle (e.g., during npm install) + if (shouldRetryAglint && serverContext.aglintLoadingFailed && !serverContext.aglintLoading) { + connection.console.info( + '[lsp] package.json or node_modules changed, will retry AGLint loading after settle', + ); + retryAglintLoading(); + } + + // If config files changed, refresh all diagnostics + if (hasConfigChanges) { + connection.console.info('[lsp] Config file changed, refreshing linter'); + // Reset current file diagnostics + removeAllDiagnostics(documents, connection); + + // Note: No need to clear cache here - cache keys include config hash, + // so config changes are handled automatically + await refreshLinter(serverContext, connection); + } + }); + + // Document content change handler + documents.onDidChangeContent((change) => { + lintFileDebounced(change.document); + }); + + // Initialized handler + connection.onInitialized(async () => { + if (serverContext.hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register(DidChangeConfigurationNotification.type, undefined); + } + + if (serverContext.hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders(() => { + connection.console.warn('[lsp] Workspace folder change event received.'); + }); + } + + if (!serverContext.workspaceRoot) { + connection.console.error('[lsp] Could not determine the workspace root of the VSCode instance'); + } else { + // Pull the settings from VSCode + await pullSettings(serverContext, connection); + + connection.console.info( + `[lsp] AGLint Language Server initialized in workspace: ${serverContext.workspaceRoot}`, + ); + } + }); +} + +/** + * Setup workspace folder capability handler. + * + * @param connection Language server connection. + * @param serverContext Server context. + */ +export function setupWorkspaceFolderHandler(connection: Connection, serverContext: ServerContext): void { + // Since we start a new server instance for each workspace folder, + // we do not need to handle workspace folder changes. + if (serverContext.hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders(() => { + connection.console.warn( + '[lsp] Workspace folder change event received (ignored by per-folder server instance).', + ); + }); + } +} diff --git a/server/src/handlers/initialization.ts b/server/src/handlers/initialization.ts new file mode 100644 index 0000000..a6b5be5 --- /dev/null +++ b/server/src/handlers/initialization.ts @@ -0,0 +1,65 @@ +/** + * @file Initialization operations - server initialization logic. + */ + +import type { InitializeParams, InitializeResult } from 'vscode-languageserver/node'; +import { TextDocumentSyncKind } from 'vscode-languageserver/node'; + +import type { ServerContext } from '../context/server-context'; +import { extractWorkspaceRootUri, getWorkspaceRootFromRootUri } from '../utils/workspace'; + +/** + * Handle the server initialization request. + * + * @param params Initialization parameters from the client. + * @param serverContext Server context. + * + * @returns Initialization result with server capabilities. + */ +export function handleInitialize( + params: InitializeParams, + serverContext: ServerContext, +): InitializeResult { + const { capabilities, initializationOptions } = params; + + // Get initial debug state from client (based on VSCode's log level) + if (initializationOptions && typeof initializationOptions.enableAglintDebug === 'boolean') { + serverContext.updateInitialDebugMode(initializationOptions.enableAglintDebug); + } + + // Determine workspace root using helper functions + const workspaceRootUri = extractWorkspaceRootUri(params); + const rootFromUri = getWorkspaceRootFromRootUri(workspaceRootUri); + serverContext.setWorkspaceRoot(rootFromUri !== undefined ? rootFromUri : (params.rootPath ?? undefined)); + + let message = 'AGLint Language Server initialized '; + if (serverContext.workspaceRoot) { + message += `with workspace root: ${serverContext.workspaceRoot}`; + } else { + message += 'without workspace root'; + } + serverContext.connection.console.debug(`[lsp] ${message}`); + + // Does the client support the `workspace/configuration` request? + // If not, we fall back using global settings. + serverContext.setConfigurationCapability(!!( + capabilities.workspace && !!capabilities.workspace.configuration + )); + + serverContext.setWorkspaceFolderCapability(!!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + )); + + // Define the capabilities of the language server here + const result: InitializeResult = { + capabilities: { + codeActionProvider: true, + textDocumentSync: { + openClose: true, + change: TextDocumentSyncKind.Incremental, + }, + }, + }; + + return result; +} diff --git a/server/src/linting/cache.ts b/server/src/linting/cache.ts new file mode 100644 index 0000000..6d3af94 --- /dev/null +++ b/server/src/linting/cache.ts @@ -0,0 +1,74 @@ +/** + * @file Linting cache management. + */ + +import { type Diagnostic, LRUCache } from 'vscode-languageserver/node'; + +/** + * Maximum number of entries in the LRU cache. + */ +const CACHE_MAX_ENTRIES = 100; + +/** + * Create a cache key for linting results. + * + * @param uri Document URI. + * @param aglintVersion AGLint version. + * @param documentVersion Document version (incremented on each change). + * @param configHash Hash of the linter config. + * + * @returns Cache key. + */ +export function createLintCacheKey( + uri: string, + aglintVersion: string, + documentVersion: number, + configHash: string, +): string { + return `${uri}:${aglintVersion}:${documentVersion}:${configHash}`; +} + +/** + * Cache for linting results using LRU eviction strategy. + */ +export class LintingCache { + /** + * Internal LRU cache. + */ + private cache: LRUCache; + + /** + * Creates a new linting cache. + */ + constructor() { + this.cache = new LRUCache(CACHE_MAX_ENTRIES); + } + + /** + * Get cached diagnostics. + * + * @param key Cache key. + * + * @returns Cached diagnostics or undefined. + */ + public get(key: string): Diagnostic[] | undefined { + return this.cache.get(key); + } + + /** + * Set cached diagnostics. + * + * @param key Cache key. + * @param diagnostics Diagnostics to cache. + */ + public set(key: string, diagnostics: Diagnostic[]): void { + this.cache.set(key, diagnostics); + } + + /** + * Clear the cache. + */ + public clear(): void { + this.cache.clear(); + } +} diff --git a/server/src/linting/diagnostics.ts b/server/src/linting/diagnostics.ts new file mode 100644 index 0000000..1ef4e8a --- /dev/null +++ b/server/src/linting/diagnostics.ts @@ -0,0 +1,100 @@ +/** + * @file Diagnostic conversion utilities - converts AGLint results to VSCode diagnostics. + */ + +import type { LinterPositionRange, LinterResult } from '@adguard/aglint/linter'; +import { + type Diagnostic, + DiagnosticSeverity, + Position, + Range, +} from 'vscode-languageserver/node'; + +import type { AglintContext } from '../context/aglint-context'; + +/** + * Convert AGLint position range to VSCode range. + * + * @param range AGLint position range. + * + * @returns VSCode range. + */ +export function convertAglintPositionToVscodeRange(range: LinterPositionRange): Range { + // Note: AGLint uses 1-based line numbers, but VSCode uses 0-based line numbers + return Range.create( + Position.create(range.start.line - 1, range.start.column), + Position.create(range.end.line - 1, range.end.column), + ); +} + +/** + * Get the rule documentation URL from the linter result. + * + * @param ruleId Rule ID. + * @param linterResult Linter result. + * + * @returns Rule documentation URL or undefined if not found. + */ +function getRuleDocumentationUrl(ruleId: string, linterResult: LinterResult): string | undefined { + if (!linterResult.metadata) { + return undefined; + } + + return linterResult.metadata[ruleId]?.docs?.url; +} + +/** + * Convert AGLint result to VSCode diagnostics. + * + * @param linterResult Linter result. + * @param aglintContext AGLint context. + * + * @returns VSCode diagnostics. + */ +export function convertLinterResultToDiagnostics( + linterResult: LinterResult, + aglintContext: AglintContext, +): Diagnostic[] { + const diagnostics: Diagnostic[] = []; + + for (const problem of linterResult.problems) { + const severity = problem.severity === aglintContext.aglint.linter.LinterRuleSeverity.Warning + ? DiagnosticSeverity.Warning + : DiagnosticSeverity.Error; + + const diagnostic: Diagnostic = { + severity, + range: convertAglintPositionToVscodeRange(problem.position), + message: problem.message, + source: 'aglint', + }; + + // Add permalink to the rule documentation + if (problem.ruleId) { + diagnostic.code = problem.ruleId; + const href = getRuleDocumentationUrl(problem.ruleId, linterResult); + if (href) { + diagnostic.codeDescription = { + href, + }; + } + } + + // Attach fix and suggestions data for code actions + if (problem.fix || problem.suggestions) { + diagnostic.data = {}; + + if (problem.fix) { + diagnostic.data.fix = problem.fix; + } + + if (problem.suggestions) { + diagnostic.data.suggestions = problem.suggestions; + } + } + + diagnostics.push(diagnostic); + } + + return diagnostics; +} diff --git a/server/src/linting/helpers.ts b/server/src/linting/helpers.ts new file mode 100644 index 0000000..b296302 --- /dev/null +++ b/server/src/linting/helpers.ts @@ -0,0 +1,140 @@ +/** + * @file Internal helpers for linting operations. + */ + +import { fileURLToPath } from 'node:url'; + +import type { LinterConfig, LinterRunOptions } from '@adguard/aglint/linter'; +import type { Connection } from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import type { ServerContext } from '../context/server-context'; +import { isFileUri } from '../utils/uri'; + +import { createLintCacheKey } from './cache'; +import { convertLinterResultToDiagnostics } from './diagnostics'; + +/** + * Debounce delay for linting files. + * It is used to avoid too frequent linting when the user modifies the file. + */ +export const LINT_FILE_DEBOUNCE_DELAY = 100; + +/** + * Check if a document should be linted. + * + * @param textDocument Document to check. + * @param serverContext Server context. + * + * @returns True if document should be linted. + */ +export async function shouldLintDocument( + textDocument: TextDocument, + serverContext: ServerContext, +): Promise { + if ( + !isFileUri(textDocument.uri) + || !serverContext.workspaceRoot + || !serverContext.settings.enableAglint + || !serverContext.aglintContext + ) { + return false; + } + + const documentPath = fileURLToPath(textDocument.uri); + const isIgnored = await serverContext.aglintContext.linterTree.isIgnored(documentPath); + return !isIgnored; +} + +/** + * Try to get diagnostics from cache. + * + * @param textDocument Document to lint. + * @param serverContext Server context. + * @param connection Language server connection. + * @param config Linter config. + * + * @returns Cached diagnostics if found, undefined otherwise. + */ +export function tryGetCachedDiagnostics( + textDocument: TextDocument, + serverContext: ServerContext, + connection: Connection, + config: LinterConfig, +): ReturnType | undefined { + if (!serverContext.settings.enableInMemoryAglintCache) { + return undefined; + } + + const configHash = serverContext.aglintContext!.aglint.cli.getLinterConfigHash(config); + const cacheKey = createLintCacheKey( + textDocument.uri, + serverContext.aglintContext!.aglint.version, + textDocument.version, + configHash, + ); + + const cachedDiagnostics = serverContext.lintingCache.get(cacheKey); + if (cachedDiagnostics) { + connection.console.debug( + `[lsp] Linting completed for: ${fileURLToPath(textDocument.uri)} (from cache)`, + ); + } + + return cachedDiagnostics; +} + +/** + * Perform actual linting of the document. + * + * @param textDocument Document to lint. + * @param serverContext Server context. + * @param connection Language server connection. + * @param config Linter config. + * + * @returns Diagnostics from linting. + */ +export async function performLinting( + textDocument: TextDocument, + serverContext: ServerContext, + connection: Connection, + config: LinterConfig, +): Promise> { + const documentPath = fileURLToPath(textDocument.uri); + const text = textDocument.getText(); + + connection.console.debug(`[lsp] Linting file: ${documentPath}`); + + const linterRunOptions: LinterRunOptions = { + fileProps: { + filePath: documentPath, + content: text, + cwd: serverContext.workspaceRoot!, + }, + config, + subParsers: serverContext.aglintContext!.aglint.linter.defaultSubParsers, + loadRule: serverContext.aglintContext!.aglint.loadRule, + // Need to include metadata to get the rule documentation + includeMetadata: true, + debug: serverContext.aglintContext!.debuggerInstance.module('linter-core'), + }; + + const linterResult = await serverContext.aglintContext!.aglint.linter.lint(linterRunOptions); + const diagnostics = convertLinterResultToDiagnostics(linterResult, serverContext.aglintContext!); + + // Store result in cache if caching is enabled + if (serverContext.settings.enableInMemoryAglintCache) { + const configHash = serverContext.aglintContext!.aglint.cli.getLinterConfigHash(config); + const cacheKey = createLintCacheKey( + textDocument.uri, + serverContext.aglintContext!.aglint.version, + textDocument.version, + configHash, + ); + serverContext.lintingCache.set(cacheKey, diagnostics); + } + + connection.console.debug(`[lsp] Linting completed for: ${documentPath}`); + + return diagnostics; +} diff --git a/server/src/linting/orchestration.ts b/server/src/linting/orchestration.ts new file mode 100644 index 0000000..3b35d3e --- /dev/null +++ b/server/src/linting/orchestration.ts @@ -0,0 +1,162 @@ +/** + * @file Linting orchestration - public APIs for linting operations. + */ + +import { fileURLToPath } from 'node:url'; + +import type { LinterConfigFile } from '@adguard/aglint/cli'; +import type { LinterConfig } from '@adguard/aglint/linter'; +import debounce from 'debounce'; +import type { Connection, TextDocuments } from 'vscode-languageserver/node'; +import type { TextDocument } from 'vscode-languageserver-textdocument'; + +import type { ServerContext } from '../context/server-context'; +import { getErrorMessage, getErrorStack } from '../utils/error'; +import { isFileUri } from '../utils/uri'; + +import { + LINT_FILE_DEBOUNCE_DELAY, + performLinting, + shouldLintDocument, + tryGetCachedDiagnostics, +} from './helpers'; + +/** + * Get the linter config for the given document. + * + * @param textDocument Document to get the linter config for. + * @param serverContext Server context. + * + * @returns Linter config for the document or undefined if the document is not lintable. + */ +export async function getLinterConfig( + textDocument: TextDocument, + serverContext: ServerContext, +): Promise { + // e.g. new unsaved documents + if (!isFileUri(textDocument.uri) || !serverContext.workspaceRoot || !serverContext.aglintContext) { + return undefined; + } + + const config = await serverContext.aglintContext.linterTree.getResolvedConfig(fileURLToPath(textDocument.uri)); + + return config; +} + +/** + * Lint the document and send the diagnostics to VSCode. + * + * @param textDocument Document to lint. + * @param serverContext Server context. + * @param connection Language server connection. + */ +export async function lintFile( + textDocument: TextDocument, + serverContext: ServerContext, + connection: Connection, +): Promise { + // Check if document should be linted + if (!(await shouldLintDocument(textDocument, serverContext))) { + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); + return; + } + + try { + // Get linter config + const config = await getLinterConfig(textDocument, serverContext); + if (!config) { + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); + return; + } + + // Normalize config for linting + const normalizedConfig: LinterConfig = { + platforms: config.platforms, + rules: config.rules ?? {}, + allowInlineConfig: true, + }; + + // Try to get from cache first + const cachedDiagnostics = tryGetCachedDiagnostics( + textDocument, + serverContext, + connection, + normalizedConfig, + ); + + if (cachedDiagnostics) { + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: cachedDiagnostics }); + return; + } + + // Perform actual linting + const diagnostics = await performLinting( + textDocument, + serverContext, + connection, + normalizedConfig, + ); + + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); + } catch (error: unknown) { + let message = `AGLint failed to lint the document: ${textDocument.uri}, got error: ${getErrorMessage(error)}`; + const stack = getErrorStack(error); + if (stack) { + message += `, ${stack}`; + } + connection.console.error(`[lsp] ${message}`); + + // Reset the diagnostics for the document + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); + + // Notify the client that the linting failed + await connection.sendNotification('aglint/status', { error }); + } +} + +/** + * Create a debounced version of lintFile. + * + * @param serverContext Server context. + * @param connection Language server connection. + * + * @returns Debounced lintFile function. + */ +export function createDebouncedLintFile( + serverContext: ServerContext, + connection: Connection, +): (textDocument: TextDocument) => void { + return debounce((textDocument: TextDocument) => { + lintFile(textDocument, serverContext, connection); + }, LINT_FILE_DEBOUNCE_DELAY); +} + +/** + * Remove all diagnostics from all open text documents. + * + * @param documents Text document manager. + * @param connection Language server connection. + */ +export function removeAllDiagnostics(documents: TextDocuments, connection: Connection): void { + documents.all().forEach((document) => { + connection.sendDiagnostics({ uri: document.uri, diagnostics: [] }); + }); +} + +/** + * Rebuild the cached paths and revalidate any open text documents. + * + * @param serverContext Server context. + * @param connection Language server connection. + */ +export async function refreshLinter(serverContext: ServerContext, connection: Connection): Promise { + if (!serverContext.settings.enableAglint || !serverContext.workspaceRoot) { + removeAllDiagnostics(serverContext.documents, connection); + return; + } + + // Revalidate any open text documents + // Note: No need to clear cache here - cache keys include AGLint version, + // so version changes are handled automatically + serverContext.documents.all().forEach((doc) => lintFile(doc, serverContext, connection)); +} diff --git a/server/src/utils/aglint-loader.ts b/server/src/loaders/aglint.ts similarity index 56% rename from server/src/utils/aglint-loader.ts rename to server/src/loaders/aglint.ts index e0cf22a..a1eefb4 100644 --- a/server/src/utils/aglint-loader.ts +++ b/server/src/loaders/aglint.ts @@ -12,12 +12,11 @@ import { satisfies } from 'semver'; import { type Connection } from 'vscode-languageserver'; import { AGLINT_PACKAGE_NAME } from '../common/constants'; - -import { getErrorMessage } from './error'; -import { fileExists } from './file-exists'; -import { importModule } from './import'; -import { resolveModulePath } from './module-resolver'; -import { findGlobalPathForPackageManager, NPM, type PackageManager } from './package-managers'; +import { getErrorMessage } from '../utils/error'; +import { fileExists } from '../utils/file-exists'; +import { importModule } from '../utils/import'; +import { resolveModulePath } from '../utils/module-resolver'; +import { findGlobalPathForPackageManager, NPM, type PackageManager } from '../utils/package-managers'; /** * Minimum version of the external AGLint module that is supported by the VSCode extension. @@ -205,6 +204,166 @@ export class LoadedAglint { }; } +/** + * Diagnose why AGLint package couldn't be loaded. + * + * @param connection Language server connection. + * @param localPackageJsonPath Path to the local package.json. + */ +async function diagnoseLoadFailure( + connection: Connection, + localPackageJsonPath: string, +): Promise { + try { + const packageJsonContent = await readFile(localPackageJsonPath, 'utf-8'); + const packageJson = JSON.parse(packageJsonContent); + const installedVersion = packageJson.version as string; + + // Check if it's a version issue + if (!satisfies(installedVersion, `>=${MIN_AGLINT_VERSION}`)) { + connection.console.error( + // eslint-disable-next-line max-len + `[lsp] AGLint ${installedVersion} is not compatible with the VSCode extension (minimum required: ${MIN_AGLINT_VERSION})`, + ); + } else if (!packageJson.exports || packageJson.type !== 'module') { + connection.console.error( + `[lsp] AGLint ${installedVersion} is not an ESM package (corrupted or incompatible)`, + ); + } else { + connection.console.error( + `[lsp] AGLint ${installedVersion} cannot be loaded (incompatible package structure)`, + ); + } + } catch (error) { + // Can't read package.json - corrupted installation + connection.console.error(`[lsp] AGLint package.json is unreadable: ${getErrorMessage(error)}`); + } +} + +/** + * Try to resolve AGLint using fallback method with global paths. + * + * @param connection Language server connection. + * @param dir Workspace root path. + * @param packageManager Package manager name. + * + * @returns Undefined (logs diagnostic info). + */ +async function tryFallbackResolution( + connection: Connection, + dir: string, + packageManager: PackageManager, +): Promise { + // Get global node_modules path if available + const globalPath = await findGlobalPathForPackageManager(packageManager); + const aglintPackageDir = tryResolveAglintPackage(dir, globalPath); + const localPackageJsonPath = aglintPackageDir ? join(aglintPackageDir, 'package.json') : undefined; + + if (aglintPackageDir) { + connection.console.info(`[lsp] AGLint found at: ${aglintPackageDir}`); + } + + if (localPackageJsonPath) { + // Package exists locally - read it to diagnose the issue + await diagnoseLoadFailure(connection, localPackageJsonPath); + return undefined; + } + + // Try to check if package.json can be resolved (for better error messages) + const aglintPackageJsonPath = await resolveModulePath( + dir, + `${AGLINT_PACKAGE_NAME}/package.json`, + packageManager, + (message: string) => { + connection.tracer.log(`[lsp] ${message}`); + }, + ); + + if (aglintPackageJsonPath && (await fileExists(aglintPackageJsonPath))) { + // Package exists globally but can't be loaded + connection.console.error( + '[lsp] AGLint is installed globally but cannot be loaded (likely incompatible version)', + ); + } else { + // Package is truly not installed + connection.console.info('[lsp] AGLint package is not installed'); + } + + return undefined; +} + +/** + * Load AGLint submodules (linter and CLI). + * + * @param connection Language server connection. + * @param dir Workspace root path. + * @param packageManager Package manager name. + * @param aglint Main AGLint module. + * @param aglintPath Path to AGLint main module. + * + * @returns LoadedAglint instance or undefined if loading failed. + */ +async function loadAglintSubmodules( + connection: Connection, + dir: string, + packageManager: PackageManager, + aglint: typeof AGLint, + aglintPath: string, +): Promise { + // Resolve linter module + const linterPath = await resolveModulePath( + dir, + `${AGLINT_PACKAGE_NAME}/linter`, + packageManager, + (message: string) => { + connection.tracer.log(`[lsp] ${message}`); + }, + ); + if (!linterPath) { + connection.console.error('[lsp] Failed to resolve AGLint linter module'); + return undefined; + } + + // Resolve CLI module + const cliPath = await resolveModulePath( + dir, + `${AGLINT_PACKAGE_NAME}/cli`, + packageManager, + (message: string) => { + connection.tracer.log(`[lsp] ${message}`); + }, + ); + if (!cliPath) { + connection.console.error('[lsp] Failed to resolve AGLint CLI module'); + return undefined; + } + + // Convert file paths to file:// URLs for dynamic import (required on Windows) + const linterUrl = pathToFileURL(linterPath).toString(); + const cliUrl = pathToFileURL(cliPath).toString(); + + // Load the submodules + const cli = await importModule(cliUrl) as typeof AGLintCliModule; + const pathAdapter = new cli.NodePathAdapter(); + const linter = await importModule(linterUrl) as typeof AGLintLinterModule; + + // aglintPath points to .../dist/index.js, we need to go up to the package root + // and then to config-presets directory + const packageRoot = pathAdapter.dirname(pathAdapter.dirname(aglintPath)); + const presetsRoot = pathAdapter.join(packageRoot, 'config-presets'); + + return new LoadedAglint( + linter, + cli, + presetsRoot, + aglint.version, + aglintPath, + connection, + dir, + packageManager, + ); +} + /** * Load the installed AGLint module. * @@ -217,8 +376,8 @@ export async function loadAglintModule( connection: Connection, dir: string, ): Promise { + // Detect package manager let preferredPackageManager = await preferredPM(dir); - if (!preferredPackageManager) { preferredPackageManager = { name: NPM, @@ -226,11 +385,13 @@ export async function loadAglintModule( }; } + const packageManager = preferredPackageManager.name as PackageManager; + // Try to resolve the main AGLint module const aglintPath = await resolveModulePath( dir, AGLINT_PACKAGE_NAME, - preferredPackageManager.name, + packageManager, (message: string) => { connection.tracer.log(`[lsp] ${message}`); }, @@ -240,138 +401,39 @@ export async function loadAglintModule( connection.console.info(`[lsp] AGLint found at: ${aglintPath}`); } + // If resolution failed, try fallback methods and return early if (!aglintPath) { - // Failed to resolve - try using resolve package with global path support - // Get global node_modules path if available - const globalPath = await findGlobalPathForPackageManager(preferredPackageManager.name); - const aglintPackageDir = tryResolveAglintPackage(dir, globalPath); - const localPackageJsonPath = aglintPackageDir ? join(aglintPackageDir, 'package.json') : undefined; - - if (aglintPackageDir) { - connection.console.info(`[lsp] AGLint found at: ${aglintPackageDir}`); - } - - if (localPackageJsonPath) { - // Package exists locally - read it to diagnose the issue - try { - const packageJsonContent = await readFile(localPackageJsonPath, 'utf-8'); - const packageJson = JSON.parse(packageJsonContent); - const installedVersion = packageJson.version as string; - - // Check if it's a version issue - if (!satisfies(installedVersion, `>=${MIN_AGLINT_VERSION}`)) { - connection.console.error( - // eslint-disable-next-line max-len - `[lsp] AGLint ${installedVersion} is not compatible with the VSCode extension (minimum required: ${MIN_AGLINT_VERSION})`, - ); - } else if (!packageJson.exports || packageJson.type !== 'module') { - connection.console.error( - `[lsp] AGLint ${installedVersion} is not an ESM package (corrupted or incompatible)`, - ); - } else { - connection.console.error( - `[lsp] AGLint ${installedVersion} cannot be loaded (incompatible package structure)`, - ); - } - } catch (error) { - // Can't read package.json - corrupted installation - connection.console.error(`[lsp] AGLint package.json is unreadable: ${getErrorMessage(error)}`); - } - return undefined; - } - - // Try to check if package.json can be resolved (for better error messages) - const aglintPackageJsonPath = await resolveModulePath( - dir, - `${AGLINT_PACKAGE_NAME}/package.json`, - preferredPackageManager.name, - (message: string) => { - connection.tracer.log(`[lsp] ${message}`); - }, - ); - - if (aglintPackageJsonPath && (await fileExists(aglintPackageJsonPath))) { - // Package exists globally but can't be loaded - connection.console.error( - '[lsp] AGLint is installed globally but cannot be loaded (likely incompatible version)', - ); - } else { - // Package is truly not installed - connection.console.info('[lsp] AGLint package is not installed'); - } - - return undefined; + return tryFallbackResolution(connection, dir, packageManager); } - // Dynamic import requires a URL, not a path + // Load the main AGLint module const externalAglintUrlPath = pathToFileURL(aglintPath).toString(); try { const aglint = await importModule(externalAglintUrlPath) as typeof AGLint; - const suffix = `version: ${aglint.version}, minimum required version: ${MIN_AGLINT_VERSION}`; - + // Check version compatibility if (!satisfies(aglint.version, `>=${MIN_AGLINT_VERSION}`)) { + const suffix = `version: ${aglint.version}, minimum required version: ${MIN_AGLINT_VERSION}`; connection.console.error( `[lsp] External AGLint module version is not compatible with the VSCode extension (${suffix})`, ); return undefined; } - const linterPath = await resolveModulePath( - dir, - `${AGLINT_PACKAGE_NAME}/linter`, - preferredPackageManager.name, - (message: string) => { - connection.tracer.log(`[lsp] ${message}`); - }, - ); - if (!linterPath) { - connection.console.error('[lsp] Failed to resolve AGLint linter module'); - return undefined; - } - const cliPath = await resolveModulePath( - dir, - `${AGLINT_PACKAGE_NAME}/cli`, - preferredPackageManager.name, - (message: string) => { - connection.tracer.log(`[lsp] ${message}`); - }, - ); - if (!cliPath) { - connection.console.error('[lsp] Failed to resolve AGLint CLI module'); - return undefined; - } - - // Convert file paths to file:// URLs for dynamic import (required on Windows) - const linterUrl = pathToFileURL(linterPath).toString(); - const cliUrl = pathToFileURL(cliPath).toString(); - - const cli = await importModule(cliUrl) as typeof AGLintCliModule; - const pathAdapter = new cli.NodePathAdapter(); - const linter = await importModule(linterUrl) as typeof AGLintLinterModule; - - // aglintPath points to .../dist/index.js, we need to go up to the package root - // and then to config-presets directory - const packageRoot = pathAdapter.dirname(pathAdapter.dirname(aglintPath)); - const presetsRoot = pathAdapter.join(packageRoot, 'config-presets'); - - return new LoadedAglint( - linter, - cli, - presetsRoot, - aglint.version, - aglintPath, + // Load submodules (linter and CLI) + return await loadAglintSubmodules( connection, dir, - preferredPackageManager.name as PackageManager, + packageManager, + aglint, + aglintPath, ); } catch (error: unknown) { connection.console.error( // eslint-disable-next-line max-len `[lsp] Failed to load external AGLint module from: ${aglintPath}, because of the following error: ${getErrorMessage(error)}`, ); + return undefined; } - - return undefined; } diff --git a/server/src/server.ts b/server/src/server.ts index 16b77e9..17c4137 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,54 +1,13 @@ /** * @file AGLint Language Server for VSCode (Node.js). - * - * @todo Split this server into multiple files by creating a server context. */ -import { fileURLToPath, pathToFileURL } from 'node:url'; - -import type { LinterConfigFile } from '@adguard/aglint/cli'; -import type { - LinterConfig, - LinterFixCommand, - LinterOffsetRange, - LinterPositionRange, - LinterResult, - LinterRunOptions, -} from '@adguard/aglint/linter'; -import { CommentMarker, type ConfigCommentRule, ConfigCommentRuleParser } from '@adguard/agtree'; -import debounce from 'debounce'; -import { - CodeAction, - CodeActionKind, - createConnection, - type Diagnostic, - DiagnosticSeverity, - DidChangeConfigurationNotification, - type InitializeParams, - type InitializeResult, - LRUCache, - Position, - ProposedFeatures, - Range, - TextDocumentEdit, - TextDocuments, - TextDocumentSyncKind, - TextEdit, - uinteger, -} from 'vscode-languageserver/node'; +import { createConnection, ProposedFeatures, TextDocuments } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; -import { EMPTY, LF, SPACE } from './common/constants'; -import { AglintContext } from './context/aglint-context'; -import { defaultSettings, type ExtensionSettings } from './settings'; -import { getErrorMessage, getErrorStack } from './utils/error'; -import { isFileUri } from './utils/uri'; - -/** - * Debounce delay for linting files. - * It is used to avoid too frequent linting when the user modifies the file. - */ -const LINT_FILE_DEBOUNCE_DELAY = 100; +import { ServerContext } from './context/server-context'; +import { registerEventHandlers, setupWorkspaceFolderHandler } from './handlers/event-handlers'; +import { handleInitialize } from './handlers/initialization'; /** * Create a connection for the server, using Node's IPC as a transport. @@ -64,930 +23,34 @@ connection.console.info(`[lsp] AGLint Language Server starting (Node.js ${proces const documents: TextDocuments = new TextDocuments(TextDocument); /** - * Whether the client supports the `workspace/configuration` request. - */ -let hasConfigurationCapability = false; - -/** - * Whether the client supports the `workspace/workspaceFolders` request. - */ -let hasWorkspaceFolderCapability = false; - -/** - * Root folder of the VSCode workspace. + * Server context holding all shared state. */ -let workspaceRoot: string | undefined; +const serverContext = new ServerContext(connection, documents); /** - * Actual settings for the extension (always synced). + * Handle server initialization. */ -let settings: ExtensionSettings = defaultSettings; +connection.onInitialize((params) => { + const result = handleInitialize(params, serverContext); -/** - * Initial debug mode from VSCode log level, used before AGLint context is created. - * Once context exists, use aglintContext.debuggerInstance.isEnabled() instead. - */ -let initialDebugMode = false; - -/** - * AGLint context instance, if initialized. - */ -let aglintContext: AglintContext | undefined; - -/** - * Flag to track if AGLint loading has failed. - * Prevents repeated attempts to load AGLint until package.json changes. - */ -let aglintLoadingFailed = false; - -/** - * Flag to track if AGLint loading is currently in progress. - * Prevents concurrent initialization attempts during startup. - */ -let aglintLoading = false; - -/** - * Cache for linting results, keyed by cache key. - * Uses LRU eviction strategy with size limit (no TTL). - */ -const lintCache = new LRUCache(100); - -/** - * Create a cache key for linting results. - * - * @param uri Document URI. - * @param aglintVersion AGLint version. - * @param documentVersion Document version (incremented on each change). - * @param configHash Hash of the linter config. - * - * @returns Cache key. - */ -function createLintCacheKey( - uri: string, - aglintVersion: string, - documentVersion: number, - configHash: string, -): string { - return `${uri}:${aglintVersion}:${documentVersion}:${configHash}`; -} - -/** - * Helper function to extract the workspace root URI from the initialization parameters. - * - * @param params Initialization parameters. - * - * @returns Workspace root URI or undefined if not found. - */ -const extractWorkspaceRootUri = (params: InitializeParams): string | undefined => { - let workspaceRootUri: string | undefined; - - if (params.initializationOptions && params.initializationOptions.workspaceFolder?.uri) { - workspaceRootUri = params.initializationOptions.workspaceFolder.uri; - } else if (params.rootUri) { - workspaceRootUri = params.rootUri; - } else if (params.workspaceFolders?.length) { - workspaceRootUri = params.workspaceFolders[0].uri; - } - - return workspaceRootUri; -}; - -/** - * Helper function to get the workspace root path from the workspace root URI. - * - * @param rootUri Workspace root URI. - * - * @returns Workspace root path or undefined if the URI is not a file URI. - */ -const getWorkspaceRootFromRootUri = (rootUri: string | undefined): string | undefined => { - if (!rootUri || !isFileUri(rootUri)) { - return undefined; - } - const path = fileURLToPath(rootUri); - return path === null ? undefined : path; -}; - -connection.onInitialize(async (params: InitializeParams) => { - const { capabilities, initializationOptions } = params; - - // Get initial debug state from client (based on VSCode's log level) - if (initializationOptions && typeof initializationOptions.enableAglintDebug === 'boolean') { - initialDebugMode = initializationOptions.enableAglintDebug; - } - - // Determine workspace root using helper functions - const workspaceRootUri = extractWorkspaceRootUri(params); - const rootFromUri = getWorkspaceRootFromRootUri(workspaceRootUri); - workspaceRoot = rootFromUri !== undefined ? rootFromUri : (params.rootPath ?? undefined); - - let message = 'AGLint Language Server initialized '; - if (workspaceRoot) { - message += `with workspace root: ${workspaceRoot}`; - } else { - message += 'without workspace root'; - } - connection.console.debug(`[lsp] ${message}`); - - // Does the client support the `workspace/configuration` request? - // If not, we fall back using global settings. - hasConfigurationCapability = !!(capabilities.workspace && !!capabilities.workspace.configuration); - - hasWorkspaceFolderCapability = !!(capabilities.workspace && !!capabilities.workspace.workspaceFolders); - - // TODO: Define the capabilities of the language server here - const result: InitializeResult = { - capabilities: { - codeActionProvider: true, - textDocumentSync: { - openClose: true, - change: TextDocumentSyncKind.Incremental, - }, - }, - }; - - // Since we start a new server instance for each workspace folder, - // we do not need to handle workspace folder changes. - if (hasWorkspaceFolderCapability) { - connection.workspace.onDidChangeWorkspaceFolders(() => { - connection.console.warn( - '[lsp] Workspace folder change event received (ignored by per-folder server instance).', - ); - }); - } + // Setup workspace folder change handler + setupWorkspaceFolderHandler(connection, serverContext); return result; }); /** - * Get the linter config for the given document. - * - * @param textDocument Document to get the linter config for. - * - * @returns Linter config for the document or undefined if the document is not lintable. - */ -async function getLinterConfig(textDocument: TextDocument): Promise { - // e.g. new unsaved documents - if (!isFileUri(textDocument.uri) || !workspaceRoot || !aglintContext) { - return undefined; - } - - const config = await aglintContext.linterTree.getResolvedConfig(fileURLToPath(textDocument.uri)); - - return config; -} - -/** - * Convert AGLint position range to VSCode range. - * - * @param range AGLint position range. - * - * @returns VSCode range. - */ -const getVscodeCodeRangeFromAglintPositionRange = (range: LinterPositionRange): Range => { - // Note: linting problems using 1-based line numbers, but VSCode uses 0-based line numbers - return Range.create( - Position.create(range.start.line - 1, range.start.column), - Position.create(range.end.line - 1, range.end.column), - ); -}; - -/** - * Get the rule documentation URL from the linter result. - * - * @param ruleId Rule ID. - * @param linterResult Linter result. - * - * @returns Rule documentation URL or undefined if the rule documentation URL is not found. - */ -const getRuleDocumentationUrlFromLinterResult = (ruleId: string, linterResult: LinterResult): string | undefined => { - if (!linterResult.metadata) { - return undefined; - } - - return linterResult.metadata[ruleId]?.docs?.url; -}; - -/** - * Convert AGLint result to VSCode diagnostics. - * - * @param linterResult Linter result. - * - * @returns VSCode diagnostics. - */ -const getVscodeDiagnosticsFromLinterResult = (linterResult: LinterResult): Diagnostic[] => { - const diagnostics: Diagnostic[] = []; - - if (!aglintContext) { - return diagnostics; - } - - for (const problem of linterResult.problems) { - const severity = problem.severity === aglintContext.aglint.linter.LinterRuleSeverity.Warning - ? DiagnosticSeverity.Warning - : DiagnosticSeverity.Error; - - const diagnostic: Diagnostic = { - severity, - range: getVscodeCodeRangeFromAglintPositionRange(problem.position), - message: problem.message, - source: 'aglint', - }; - - // Add permalink to the rule documentation - if (problem.ruleId) { - diagnostic.code = problem.ruleId; - const href = getRuleDocumentationUrlFromLinterResult(problem.ruleId, linterResult); - if (href) { - diagnostic.codeDescription = { - href, - }; - } - } - - if (problem.fix || problem.suggestions) { - diagnostic.data = {}; - - if (problem.fix) { - diagnostic.data.fix = problem.fix; - } - - if (problem.suggestions) { - diagnostic.data.suggestions = problem.suggestions; - } - } - - diagnostics.push(diagnostic); - } - - return diagnostics; -}; - -/** - * Lint the document and send the diagnostics to VSCode. - * - * @param textDocument Document to lint. - */ -async function lintFile(textDocument: TextDocument): Promise { - if ( - !isFileUri(textDocument.uri) - || !workspaceRoot - || !settings.enableAglint - || !aglintContext - || await aglintContext.linterTree.isIgnored(fileURLToPath(textDocument.uri)) - ) { - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); - return; - } - - const documentPath = fileURLToPath(textDocument.uri); - const startTime = Date.now(); - - try { - const config = await getLinterConfig(textDocument); - - if (!config) { - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); - return; - } - - const text = textDocument.getText(); - - // Normalize config for linting (this is what will actually be used) - const normalizedConfig: LinterConfig = { - platforms: config.platforms, - rules: config.rules ?? {}, - allowInlineConfig: true, - }; - - // Create cache key using document version and config hash - const configHash = aglintContext.aglint.cli.getLinterConfigHash(normalizedConfig); - const cacheKey = createLintCacheKey( - textDocument.uri, - aglintContext.aglint.version, - textDocument.version, - configHash, - ); - - // Check cache first if caching is enabled - if (settings.enableInMemoryAglintCache) { - const cachedDiagnostics = lintCache.get(cacheKey); - if (cachedDiagnostics) { - const duration = Date.now() - startTime; - connection.console.debug( - `[lsp] Linting completed for: ${documentPath} (from cache, ${duration}ms)`, - ); - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: cachedDiagnostics }); - return; - } - } - - connection.console.debug(`[lsp] Linting file: ${documentPath}`); - - const linterRunOptions: LinterRunOptions = { - fileProps: { - filePath: documentPath, - content: text, - cwd: workspaceRoot, - }, - config: normalizedConfig, - subParsers: aglintContext.aglint.linter.defaultSubParsers, - loadRule: aglintContext.aglint.loadRule, - // Need to include metadata to get the rule documentation - includeMetadata: true, - debug: aglintContext.debuggerInstance.module('linter-core'), - }; - - // connection.console.log(`Linting document: ${documentPath} with config: ${JSON.stringify(config, null, 2)}`); - - const linterResult = await aglintContext.aglint.linter.lint(linterRunOptions); - const diagnostics = getVscodeDiagnosticsFromLinterResult(linterResult); - - // Store result in cache if caching is enabled - if (settings.enableInMemoryAglintCache) { - lintCache.set(cacheKey, diagnostics); - } - - const duration = Date.now() - startTime; - connection.console.debug(`[lsp] Linting completed for: ${documentPath} (${duration}ms)`); - - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); - } catch (error: unknown) { - let message = `AGLint failed to lint the document: ${textDocument.uri}, got error: ${getErrorMessage(error)}`; - const stack = getErrorStack(error); - if (stack) { - message += `, ${stack}`; - } - connection.console.error(`[lsp] ${message}`); - - // Reset the diagnostics for the document - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); - - // Notify the client that the linting failed - await connection.sendNotification('aglint/status', { error }); - } -} - -/** - * Lint the document and send the diagnostics to VSCode. - * Debounced version of {@link lintFile}. - * - * @param textDocument Document to lint. - */ -const lintFileDebounced = debounce(lintFile, LINT_FILE_DEBOUNCE_DELAY); - -/** - * Parse AGLint config comment rule in a tolerant way (did not throw on parsing error). - * - * @param rule Rule to parse. - * - * @returns AGLint config comment rule node or null if parsing failed. + * Register all event handlers. */ -const parseConfigCommentTolerant = (rule: string): ConfigCommentRule | null => { - try { - return ConfigCommentRuleParser.parse(rule); - } catch (error: unknown) { - connection.console.debug( - `[lsp] '${rule}' is not a valid AGLint config comment rule: ${getErrorMessage(error)}`, - ); - return null; - } -}; +registerEventHandlers(connection, documents, serverContext); /** - * Convert AGLint offset range to VSCode range. - * - * @param textDocument Text document. - * @param range AGLint offset range. - * - * @returns VSCode range. + * Make the text document manager listen on the connection + * for open, change and close text document events. */ -const convertAglintRangeToVsCodeRange = (textDocument: TextDocument, range: LinterOffsetRange): Range => { - const [startOffset, endOffset] = range; - const start = textDocument.positionAt(startOffset); - const end = textDocument.positionAt(endOffset); - return Range.create(start, end); -}; - -/** - * Convert AGLint fix to VSCode code edit. - * - * @param textDocument Text document. - * @param fix AGLint fix. - * - * @returns VSCode code edit. - */ -const convertAglintFixToVsCodeCodeEdit = (textDocument: TextDocument, fix: LinterFixCommand): TextEdit => { - return TextEdit.replace( - convertAglintRangeToVsCodeRange(textDocument, fix.range), - fix.text, - ); -}; - -connection.onCodeAction((params) => { - const textDocument = documents.get(params.textDocument.uri); - if (textDocument === undefined) { - return undefined; - } - - const { diagnostics } = params.context; - const actions: CodeAction[] = []; - - // Make '! aglint-disable-next-line' prefix - const aglintDisableNextLinePrefix = [ - CommentMarker.Regular, - SPACE, - aglintContext?.aglint.linter.LinterConfigCommentType.DisableNextLine, - ].join(EMPTY); - - for (const diagnostic of diagnostics) { - const { code, range } = diagnostic; - const { line } = range.start; - - if (!code) { - // In this case we don't have a rule name, because some parsing error happened, - // and parsing errors have more priority than linting errors: if a rule cannot be parsed, - // it cannot be checked with linter rules. - // So we need to suggest disabling AGLint for the line completely as a quick fix. - const titleDisableRule = 'Disable AGLint for this line'; - const actionDisableRule = CodeAction.create(titleDisableRule, CodeActionKind.QuickFix); - - // Or delete this rule - const titleRemoveRule = 'Remove this rule'; - const actionRemoveRule = CodeAction.create(titleRemoveRule, CodeActionKind.QuickFix); - - if (line === 0) { - // If there are no previous lines, just insert the comment before the problematic line. - actionDisableRule.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.insert( - Position.create(line, 0), - `${aglintDisableNextLinePrefix}${LF}`, - )], - ), - ], - }; - - actions.push(actionDisableRule); - - actionRemoveRule.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.del(Range.create( - Position.create(line, 0), - Position.create(line + 1, 0), - ))], - ), - ], - }; - - actions.push(actionRemoveRule); - - continue; - } - - if (line > 0) { - // If we have previous lines - const previousLine = line - 1; - - // Get the previous line - const prevLine = textDocument.getText( - Range.create( - Position.create(previousLine, 0), - // Note: we do not know the length of the previous line, so we use the max value - Position.create(previousLine, uinteger.MAX_VALUE), - ), - ); - - // If the previous line is '! aglint-disable-next-line some-rule-name', we need to replace it - // to '! aglint-disable-next-line' - because in this case we want to disable AGLint completely - // for the problematic line, not just some rule. - const commentNode = parseConfigCommentTolerant(prevLine.trim()); - - if ( - commentNode - // eslint-disable-next-line max-len - && commentNode.command.value === aglintContext?.aglint.linter.LinterConfigCommentType.DisableNextLine - && commentNode.params - ) { - delete commentNode.params; - - actionDisableRule.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.replace( - Range.create( - Position.create(previousLine, 0), - Position.create(previousLine, prevLine.length), - ), - ConfigCommentRuleParser.generate(commentNode), - )], - ), - ], - }; - - actions.push(actionDisableRule); - continue; - } - - // Otherwise just insert the comment before the problematic line - actionDisableRule.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.insert( - Position.create(line, 0), - `${aglintDisableNextLinePrefix}${LF}`, - )], - ), - ], - }; - - actions.push(actionDisableRule); - - // Or remove rule - actionRemoveRule.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.del(Range.create( - Position.create(line, 0), - Position.create(line + 1, 0), - ))], - ), - ], - }; - - actions.push(actionRemoveRule); - continue; - } - } - - if (diagnostic.data?.fix) { - const { fix } = diagnostic.data; - - if (aglintContext?.aglint.linter.isLinterFixCommand(fix)) { - const actionFix = CodeAction.create(`Fix AGLint rule '${code}'`, CodeActionKind.QuickFix); - - actionFix.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [ - convertAglintFixToVsCodeCodeEdit( - textDocument, - fix, - ), - ], - ), - ], - }; - actions.push(actionFix); - } - } - - if (diagnostic.data?.suggestions) { - const { suggestions } = diagnostic.data; - - if (aglintContext?.aglint.linter.isLinterSuggestions(suggestions)) { - for (const suggestion of suggestions) { - const actionFix = CodeAction.create( - `Apply suggestion '${suggestion.message}' from AGLint rule '${code}'`, - CodeActionKind.QuickFix, - ); - - actionFix.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [ - convertAglintFixToVsCodeCodeEdit( - textDocument, - suggestion.fix, - ), - ], - ), - ], - }; - actions.push(actionFix); - } - } - } - - // If we are here, it means that we have a linter rule name, - // so we need to suggest disabling this rule for the line - const action = CodeAction.create(`Disable AGLint rule '${code}' for this line`, CodeActionKind.QuickFix); - - // If there are no previous lines, just insert the comment before the problematic line - if (line === 0) { - action.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.insert( - Position.create(line, 0), - `${aglintDisableNextLinePrefix}${SPACE}${code}${LF}`, - )], - ), - ], - }; - actions.push(action); - continue; - } - - if (line > 0) { - // If we have previous lines - const previousLine = line - 1; - - const prevLine = textDocument.getText( - Range.create( - Position.create(previousLine, 0), - // Note: we do not know the length of the previous line, so we use the max value - Position.create(previousLine, uinteger.MAX_VALUE), - ), - ); - - // If the previous line is '! aglint-disable-next-line some-rule-name', we need to replace it - // to '! aglint-disable-next-line some-rule-name, currently-problematic-rule-name'. - // In other words, we just need to add the new rule to the list of rules to disable. - const commentNode = parseConfigCommentTolerant(prevLine.trim()); - - if ( - commentNode - // eslint-disable-next-line max-len - && commentNode.command.value === aglintContext?.aglint.linter.LinterConfigCommentType.DisableNextLine - && commentNode.params - && commentNode.params.type === 'ParameterList' - ) { - commentNode.params.children.push({ - type: 'Value', - value: String(code), - }); - action.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.replace( - Range.create( - Position.create(previousLine, 0), - Position.create(previousLine, prevLine.length), - ), - ConfigCommentRuleParser.generate(commentNode), - )], - ), - ], - }; - actions.push(action); - continue; - } - - // Otherwise just insert the comment before the problematic line - action.edit = { - documentChanges: [ - TextDocumentEdit.create( - { uri: textDocument.uri, version: textDocument.version }, - [TextEdit.insert( - Position.create(line, 0), - `${aglintDisableNextLinePrefix}${SPACE}${code}${LF}`, - )], - ), - ], - }; - actions.push(action); - continue; - } - } - return actions; -}); - -/** - * Remove all diagnostics from all open text documents. - */ -function removeAllDiagnostics() { - documents.all().forEach((document) => { - connection.sendDiagnostics({ uri: document.uri, diagnostics: [] }); - }); -} - -/** - * Rebuild the cached paths and revalidate any open text documents. - */ -async function refreshLinter() { - if (!settings.enableAglint || !workspaceRoot) { - removeAllDiagnostics(); - return; - } - - // Revalidate any open text documents - // Note: No need to clear cache here - cache keys include AGLint version, - // so version changes are handled automatically - documents.all().forEach(lintFile); -} - -/** - * Pull the settings from VSCode and update the settings variable. It also - * re-builts the cached paths and revalidates any open text documents. - * - * "In this model the clients simply sends an empty change event to signal that the settings have - * changed and must be reread". - * - * @see https://github.com/microsoft/vscode-languageserver-node/issues/380#issuecomment-414691493 - */ -async function pullSettings() { - const previousEnableAglint = settings.enableAglint; - const previousEnableCache = settings.enableInMemoryAglintCache; - - if (hasConfigurationCapability) { - const scopeUri = workspaceRoot ? pathToFileURL(workspaceRoot).toString() : undefined; - const receivedSettings = await connection.workspace.getConfiguration({ scopeUri, section: 'adblock' }); - - // Update the settings. No need to validate them, VSCode does this for us based on the schema - // specified in the package.json - // If we didn't receive any settings, use the default ones - settings = receivedSettings || defaultSettings; - } else { - settings = defaultSettings; - } - - // If nothing changed and AGLint is already initialized OR loading failed, skip heavy work - if ( - (aglintContext || aglintLoadingFailed) - && previousEnableAglint === settings.enableAglint - && previousEnableCache === settings.enableInMemoryAglintCache - ) { - return; - } - - // Clear cache if caching was disabled - if (previousEnableCache && !settings.enableInMemoryAglintCache) { - lintCache.clear(); - connection.console.info('[lsp] AGLint cache cleared (caching disabled)'); - } - - // Send status notification about AGLint being enabled/disabled - connection.sendNotification('aglint/status', { aglintEnabled: settings.enableAglint }); - - // If AGLint is disabled, clean up and return early - if (!settings.enableAglint) { - removeAllDiagnostics(); - connection.console.debug('[lsp] AGLint is disabled'); - return; - } - - connection.console.debug('[lsp] AGLint integration is enabled'); - - // Initialize AGLint context if not already initialized - if (!aglintContext && !aglintLoadingFailed && !aglintLoading) { - if (!workspaceRoot) { - connection.console.error('[lsp] Workspace root is not defined'); - removeAllDiagnostics(); - return; - } - - // Set loading flag to prevent concurrent initialization - aglintLoading = true; - - try { - aglintContext = await AglintContext.create(connection, documents, workspaceRoot, initialDebugMode); - - if (!aglintContext) { - aglintLoadingFailed = true; - connection.console.info( - '[lsp] AGLint loading failed. Will retry when package.json or node_modules changes.', - ); - removeAllDiagnostics(); - return; - } - } finally { - // Always clear loading flag - aglintLoading = false; - } - } - - // Log cache setting changes - if (previousEnableCache !== settings.enableInMemoryAglintCache) { - if (settings.enableInMemoryAglintCache) { - connection.console.info('[lsp] In-memory linting cache enabled'); - } else { - connection.console.info('[lsp] In-memory linting cache disabled'); - lintCache.clear(); - connection.console.debug('[lsp] Cache cleared'); - } - } - - await refreshLinter(); -} +documents.listen(connection); /** - * Debounced function to retry AGLint loading after package.json or node_modules changes. - * Waits 2 seconds for file system operations to settle before attempting reload. + * Listen on the connection. */ -const retryAglintLoading = debounce(async () => { - if (aglintLoadingFailed && !aglintLoading) { - connection.console.info('[lsp] Retrying AGLint loading after package changes settled'); - aglintLoadingFailed = false; - await pullSettings(); - } -}, 2000); - -connection.onDidChangeConfiguration(async () => { - await pullSettings(); -}); - -// Listen for log level changes from the client -connection.onNotification('client/logLevelChanged', (params: { enableAglintDebug: boolean }) => { - const requestedDebugMode = params.enableAglintDebug; - - // If AGLint context exists, check current state and update if needed - if (aglintContext) { - const currentDebugMode = aglintContext.debuggerInstance.isEnabled(); - - // If debug state didn't change, nothing to do - if (currentDebugMode === requestedDebugMode) { - return; - } - - const status = requestedDebugMode ? 'enabled' : 'disabled'; - connection.console.info(`[lsp] AGLint debug mode ${status} (log level changed)`); - - if (requestedDebugMode) { - aglintContext.debuggerInstance.enable(); - } else { - aglintContext.debuggerInstance.disable(); - } - } else { - // AGLint not initialized yet, just store the initial state for when it is created - initialDebugMode = requestedDebugMode; - } -}); - -// Called when any of monitored file paths change -connection.onDidChangeWatchedFiles(async (events) => { - const { changes } = events; - let shouldRetryAglint = false; - - for (const change of changes) { - const filePath = fileURLToPath(change.uri); - connection.console.info(`[lsp] Configuration file changed: ${filePath}`); - - // Check if package.json or node_modules changed (for AGLint installation detection) - if (filePath.endsWith('package.json') || filePath.endsWith('node_modules')) { - shouldRetryAglint = true; - } - - // eslint-disable-next-line no-await-in-loop - await aglintContext?.linterTree.changed(filePath); - } - - // If package.json or node_modules changed and loading previously failed, schedule a retry - // Use debounce to wait for file system operations to settle (e.g., during npm install) - if (shouldRetryAglint && aglintLoadingFailed && !aglintLoading) { - connection.console.info('[lsp] package.json or node_modules changed, will retry AGLint loading after settle'); - retryAglintLoading(); - } - - // Reset current file diagnostics - removeAllDiagnostics(); - - // Note: No need to clear cache here - cache keys include config hash, - // so config changes are handled automatically - await refreshLinter(); -}); - -// The content of a text document has changed. This event is emitted -// when the text document first opened or when its content has changed. -documents.onDidChangeContent((change) => { - lintFileDebounced(change.document); -}); - -connection.onInitialized(async () => { - if (hasConfigurationCapability) { - // Register for all configuration changes. - connection.client.register(DidChangeConfigurationNotification.type, undefined); - } - - if (hasWorkspaceFolderCapability) { - connection.workspace.onDidChangeWorkspaceFolders(() => { - connection.console.warn('[lsp] Workspace folder change event received.'); - }); - } - - if (!workspaceRoot) { - connection.console.error('[lsp] Could not determine the workspace root of the VSCode instance'); - } else { - // Pull the settings from VSCode - await pullSettings(); - - connection.console.info(`[lsp] AGLint Language Server initialized in workspace: ${workspaceRoot}`); - } -}); - -// Make the text document manager listen on the connection -// for open, change and close text document events -documents.listen(connection); - -// Listen on the connection connection.listen(); diff --git a/server/src/utils/import.ts b/server/src/utils/import.ts index 54c8aa7..8876c63 100644 --- a/server/src/utils/import.ts +++ b/server/src/utils/import.ts @@ -8,7 +8,7 @@ * @throws If the module cannot be found. */ export const importModule = async (path: string): Promise => { - const module = await import(path); + const module = await import(/* webpackIgnore: true */ path); // Module may have a default export if ('default' in module) { diff --git a/server/src/utils/uri.ts b/server/src/utils/uri.ts index d29f6ef..99788db 100644 --- a/server/src/utils/uri.ts +++ b/server/src/utils/uri.ts @@ -1,16 +1,9 @@ /** * @file Utility functions for working with URIs. */ +import { FileScheme } from '@vscode-adblock-syntax/shared'; import { URI } from 'vscode-uri'; -/** - * Schemes for file documents. - */ -// TODO: Add more schemes if needed -const enum FileScheme { - File = 'file', -} - /** * Checks if the given URI is a file URI. * diff --git a/server/src/utils/workspace.ts b/server/src/utils/workspace.ts new file mode 100644 index 0000000..d374c9c --- /dev/null +++ b/server/src/utils/workspace.ts @@ -0,0 +1,45 @@ +/** + * @file Workspace-related utility functions. + */ + +import { fileURLToPath } from 'node:url'; + +import type { InitializeParams } from 'vscode-languageserver/node'; + +import { isFileUri } from './uri'; + +/** + * Extract the workspace root URI from initialization parameters. + * + * @param params Initialization parameters. + * + * @returns Workspace root URI or undefined if not found. + */ +export function extractWorkspaceRootUri(params: InitializeParams): string | undefined { + let workspaceRootUri: string | undefined; + + if (params.initializationOptions && params.initializationOptions.workspaceFolder?.uri) { + workspaceRootUri = params.initializationOptions.workspaceFolder.uri; + } else if (params.rootUri) { + workspaceRootUri = params.rootUri; + } else if (params.workspaceFolders?.length) { + workspaceRootUri = params.workspaceFolders[0].uri; + } + + return workspaceRootUri; +} + +/** + * Get the workspace root path from the workspace root URI. + * + * @param rootUri Workspace root URI. + * + * @returns Workspace root path or undefined if the URI is not a file URI. + */ +export function getWorkspaceRootFromRootUri(rootUri: string | undefined): string | undefined { + if (!rootUri || !isFileUri(rootUri)) { + return undefined; + } + const path = fileURLToPath(rootUri); + return path === null ? undefined : path; +} diff --git a/server/test/code-actions/utils.test.ts b/server/test/code-actions/utils.test.ts new file mode 100644 index 0000000..0b9bce3 --- /dev/null +++ b/server/test/code-actions/utils.test.ts @@ -0,0 +1,245 @@ +/** + * @file Tests for code action utilities. + */ + +import { describe, expect, it } from 'vitest'; +import { TextDocument } from 'vscode-languageserver-textdocument'; + +import { + convertAglintFixToVscodeTextEdit, + convertAglintOffsetRangeToVscodeRange, + getPreviousLineText, + parseConfigCommentTolerant, +} from '../../src/code-actions/utils'; + +describe('parseConfigCommentTolerant', () => { + it('should parse valid config comment rules', () => { + const result = parseConfigCommentTolerant('! aglint-disable-next-line'); + expect(result).not.toBeNull(); + }); + + it('should parse config comment with specific rules', () => { + const result = parseConfigCommentTolerant('! aglint-disable-next-line rule-name'); + expect(result).not.toBeNull(); + }); + + it('should return null for invalid config comments', () => { + const result = parseConfigCommentTolerant('invalid-rule-format!!!'); + expect(result).toBeNull(); + }); + + it('should handle parsing without throwing errors', () => { + // The parser is tolerant and returns null instead of throwing + // Test that various invalid inputs don't throw + expect(() => { + parseConfigCommentTolerant('invalid!!!'); + }).not.toThrow(); + + expect(() => { + parseConfigCommentTolerant('! aglint-enable-[invalid'); + }).not.toThrow(); + + expect(() => { + parseConfigCommentTolerant(''); + }).not.toThrow(); + }); +}); + +describe('convertAglintOffsetRangeToVscodeRange', () => { + it('should convert offset range to VSCode range', () => { + const content = 'hello world\nfoo bar'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + // Range from index 6 to 11 ("world") + const offsetRange: [number, number] = [6, 11]; + const range = convertAglintOffsetRangeToVscodeRange(document, offsetRange); + + expect(range.start.line).toBe(0); + expect(range.start.character).toBe(6); + expect(range.end.line).toBe(0); + expect(range.end.character).toBe(11); + }); + + it('should handle multi-line ranges', () => { + const content = 'line1\nline2\nline3'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + // Range from start of line2 to end of line2 (index 6 to 11) + const offsetRange: [number, number] = [6, 11]; + const range = convertAglintOffsetRangeToVscodeRange(document, offsetRange); + + expect(range.start.line).toBe(1); + expect(range.start.character).toBe(0); + expect(range.end.line).toBe(1); + expect(range.end.character).toBe(5); + }); + + it('should handle zero-length ranges (insertion points)', () => { + const content = 'hello'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const offsetRange: [number, number] = [2, 2]; + const range = convertAglintOffsetRangeToVscodeRange(document, offsetRange); + + expect(range.start.line).toBe(0); + expect(range.start.character).toBe(2); + expect(range.end.line).toBe(0); + expect(range.end.character).toBe(2); + }); + + it('should handle ranges at the start of document', () => { + const content = 'hello world'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const offsetRange: [number, number] = [0, 5]; + const range = convertAglintOffsetRangeToVscodeRange(document, offsetRange); + + expect(range.start.line).toBe(0); + expect(range.start.character).toBe(0); + expect(range.end.line).toBe(0); + expect(range.end.character).toBe(5); + }); + + it('should handle ranges at the end of document', () => { + const content = 'hello'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const offsetRange: [number, number] = [0, 5]; + const range = convertAglintOffsetRangeToVscodeRange(document, offsetRange); + + expect(range.start.line).toBe(0); + expect(range.start.character).toBe(0); + expect(range.end.line).toBe(0); + expect(range.end.character).toBe(5); + }); +}); + +describe('convertAglintFixToVscodeTextEdit', () => { + it('should convert AGLint fix to VSCode text edit', () => { + const content = 'hello world'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const fix = { + range: [6, 11] as [number, number], + text: 'universe', + }; + + const textEdit = convertAglintFixToVscodeTextEdit(document, fix); + + expect(textEdit.range.start.line).toBe(0); + expect(textEdit.range.start.character).toBe(6); + expect(textEdit.range.end.line).toBe(0); + expect(textEdit.range.end.character).toBe(11); + expect(textEdit.newText).toBe('universe'); + }); + + it('should handle deletion (empty replacement text)', () => { + const content = 'hello world'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const fix = { + range: [5, 11] as [number, number], + text: '', + }; + + const textEdit = convertAglintFixToVscodeTextEdit(document, fix); + + expect(textEdit.newText).toBe(''); + }); + + it('should handle insertion (zero-length range)', () => { + const content = 'hello'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const fix = { + range: [5, 5] as [number, number], + text: ' world', + }; + + const textEdit = convertAglintFixToVscodeTextEdit(document, fix); + + expect(textEdit.range.start.character).toBe(5); + expect(textEdit.range.end.character).toBe(5); + expect(textEdit.newText).toBe(' world'); + }); + + it('should handle multi-line replacements', () => { + const content = 'line1\nline2'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const fix = { + range: [0, 5] as [number, number], + text: 'first line', + }; + + const textEdit = convertAglintFixToVscodeTextEdit(document, fix); + + expect(textEdit.newText).toBe('first line'); + }); +}); + +describe('getPreviousLineText', () => { + it('should return previous line text', () => { + const content = 'line 0\nline 1\nline 2'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 1); + + expect(previousLine).toBe('line 0'); + }); + + it('should return undefined for line 0', () => { + const content = 'line 0\nline 1'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 0); + + expect(previousLine).toBeUndefined(); + }); + + it('should handle empty previous lines', () => { + const content = '\nline 1'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 1); + + expect(previousLine).toBe(''); + }); + + it('should get previous line for line 2', () => { + const content = 'line 0\nline 1\nline 2'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 2); + + expect(previousLine).toBe('line 1'); + }); + + it('should handle long lines correctly', () => { + const longLine = 'a'.repeat(1000); + const content = `${longLine}\nline 1`; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 1); + + expect(previousLine).toBe(longLine); + }); + + it('should handle lines with special characters', () => { + const content = 'line with $pecial ch@racters!\nnext line'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 1); + + expect(previousLine).toBe('line with $pecial ch@racters!'); + }); + + it('should handle lines with tabs and spaces', () => { + const content = '\t\tindented line\nnext line'; + const document = TextDocument.create('file:///test.txt', 'text', 1, content); + + const previousLine = getPreviousLineText(document, 1); + + expect(previousLine).toBe('\t\tindented line'); + }); +}); diff --git a/server/test/handlers/configuration.test.ts b/server/test/handlers/configuration.test.ts new file mode 100644 index 0000000..f6e2f05 --- /dev/null +++ b/server/test/handlers/configuration.test.ts @@ -0,0 +1,512 @@ +/** + * @file Tests for configuration and settings management. + */ + +import { + afterEach, + beforeEach, + describe, + expect, + it, + vi, +} from 'vitest'; + +import { AglintContext } from '../../src/context/aglint-context'; +import { createRetryAglintLoading, pullSettings } from '../../src/handlers/configuration'; +import * as lintingOperations from '../../src/linting/orchestration'; +import { defaultSettings } from '../../src/settings'; +import { createMockConnection, createMockServerContext } from '../helpers'; + +// Mock the linting operations +vi.mock('../../src/linting/orchestration', () => ({ + refreshLinter: vi.fn(), + removeAllDiagnostics: vi.fn(), +})); + +// Mock AglintContext +vi.mock('../../src/context/aglint-context', () => ({ + AglintContext: { + create: vi.fn(), + }, +})); + +describe('pullSettings', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('settings retrieval', () => { + it('should fetch settings from workspace when capability is available', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: true }; + + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + await pullSettings(context, connection); + + expect(connection.workspace.getConfiguration).toHaveBeenCalledWith({ + scopeUri: 'file:///test/workspace', + section: 'adblock', + }); + expect(context.settings).toEqual(mockSettings); + }); + + it('should use default settings when no capability', async () => { + const context = createMockServerContext(); + context.hasConfigurationCapability = false; + const connection = createMockConnection(); + + await pullSettings(context, connection); + + expect(connection.workspace.getConfiguration).not.toHaveBeenCalled(); + expect(context.settings).toEqual(defaultSettings); + }); + + it('should use default settings when getConfiguration returns null', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + connection.workspace.getConfiguration.mockResolvedValue(null); + + await pullSettings(context, connection); + + expect(context.settings).toEqual(defaultSettings); + }); + + it('should handle workspace root without file URI', async () => { + const context = createMockServerContext(); + context.workspaceRoot = undefined; + const connection = createMockConnection(); + + await pullSettings(context, connection); + + expect(connection.workspace.getConfiguration).toHaveBeenCalledWith({ + scopeUri: undefined, + section: 'adblock', + }); + }); + }); + + describe('cache management', () => { + it('should clear cache when caching is disabled', async () => { + const context = createMockServerContext(); + context.settings.enableInMemoryAglintCache = true; + context.aglintContext = {} as any; // Already initialized + const connection = createMockConnection(); + + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: false }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + const clearSpy = vi.spyOn(context.lintingCache, 'clear'); + + await pullSettings(context, connection); + + expect(clearSpy).toHaveBeenCalled(); + expect(connection.console.info).toHaveBeenCalledWith( + '[lsp] AGLint cache cleared (caching disabled)', + ); + }); + + it('should not clear cache when it was already disabled', async () => { + const context = createMockServerContext(); + context.settings.enableInMemoryAglintCache = false; + context.aglintContext = {} as any; + const connection = createMockConnection(); + + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: false }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + const clearSpy = vi.spyOn(context.lintingCache, 'clear'); + + await pullSettings(context, connection); + + expect(clearSpy).not.toHaveBeenCalled(); + }); + + it('should log when cache is enabled', async () => { + const context = createMockServerContext(); + context.settings.enableInMemoryAglintCache = false; + context.aglintContext = {} as any; + const connection = createMockConnection(); + + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: true }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + await pullSettings(context, connection); + + expect(connection.console.info).toHaveBeenCalledWith( + '[lsp] In-memory linting cache enabled', + ); + }); + }); + + describe('AGLint enable/disable', () => { + it('should send status notification when settings change', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: true }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + await pullSettings(context, connection); + + expect(connection.sendNotification).toHaveBeenCalledWith('aglint/status', { + aglintEnabled: true, + }); + }); + + it('should remove diagnostics and return early when AGLint is disabled', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + + const mockSettings = { enableAglint: false, enableInMemoryAglintCache: true }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + await pullSettings(context, connection); + + expect(lintingOperations.removeAllDiagnostics).toHaveBeenCalledWith( + context.documents, + connection, + ); + expect(connection.console.debug).toHaveBeenCalledWith('[lsp] AGLint is disabled'); + expect(lintingOperations.refreshLinter).not.toHaveBeenCalled(); + }); + + it('should log when AGLint is enabled', async () => { + const context = createMockServerContext(); + context.aglintContext = {} as any; // Already initialized + const connection = createMockConnection(); + + const mockSettings = { enableAglint: true, enableInMemoryAglintCache: true }; + connection.workspace.getConfiguration.mockResolvedValue(mockSettings); + + await pullSettings(context, connection); + + expect(connection.console.debug).toHaveBeenCalledWith('[lsp] AGLint integration is enabled'); + }); + }); + + describe('AGLint context initialization', () => { + it('should initialize AGLint context when not already initialized', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + const mockAglintContext = { initialized: true }; + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + vi.mocked(AglintContext.create).mockResolvedValue(mockAglintContext as any); + + await pullSettings(context, connection); + + expect(AglintContext.create).toHaveBeenCalledWith( + connection, + context.documents, + context.workspaceRoot, + context.initialDebugMode, + ); + expect(context.aglintContext).toBe(mockAglintContext); + expect(lintingOperations.refreshLinter).toHaveBeenCalledWith(context, connection); + }); + + it('should not initialize if already initialized', async () => { + const context = createMockServerContext(); + context.aglintContext = { existing: true } as any; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should not initialize if loading failed', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = true; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should not initialize if already loading', async () => { + const context = createMockServerContext(); + context.aglintLoading = true; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should return early if workspace root is not defined', async () => { + const context = createMockServerContext(); + context.workspaceRoot = undefined; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(connection.console.error).toHaveBeenCalledWith('[lsp] Workspace root is not defined'); + expect(lintingOperations.removeAllDiagnostics).toHaveBeenCalledWith( + context.documents, + connection, + ); + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should set loading flag during initialization', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + let loadingDuringCreate = false; + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + vi.mocked(AglintContext.create).mockImplementation(async () => { + loadingDuringCreate = context.aglintLoading; + return { initialized: true } as any; + }); + + await pullSettings(context, connection); + + expect(loadingDuringCreate).toBe(true); + expect(context.aglintLoading).toBe(false); // Cleared after + }); + + it('should clear loading flag even if initialization fails', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + vi.mocked(AglintContext.create).mockRejectedValue(new Error('Init failed')); + + await expect(pullSettings(context, connection)).rejects.toThrow('Init failed'); + expect(context.aglintLoading).toBe(false); + }); + + it('should handle initialization returning null', async () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + vi.mocked(AglintContext.create).mockResolvedValue(null as any); + + await pullSettings(context, connection); + + expect(context.aglintLoadingFailed).toBe(true); + expect(connection.console.info).toHaveBeenCalledWith( + '[lsp] AGLint loading failed. Will retry when package.json or node_modules changes.', + ); + expect(lintingOperations.removeAllDiagnostics).toHaveBeenCalledWith( + context.documents, + connection, + ); + }); + }); + + describe('optimization - skip unnecessary work', () => { + it('should skip refresh when nothing changed and AGLint is initialized', async () => { + const context = createMockServerContext(); + context.aglintContext = { existing: true } as any; + context.settings.enableAglint = true; + context.settings.enableInMemoryAglintCache = true; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + // Should return early without calling refreshLinter + expect(lintingOperations.refreshLinter).not.toHaveBeenCalled(); + }); + + it('should skip refresh when nothing changed and loading failed', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = true; + context.settings.enableAglint = true; + context.settings.enableInMemoryAglintCache = true; + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(lintingOperations.refreshLinter).not.toHaveBeenCalled(); + }); + + it('should refresh when enableAglint changes', async () => { + const context = createMockServerContext(); + context.aglintContext = { existing: true } as any; + context.settings.enableAglint = false; // Was disabled + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, // Now enabled + enableInMemoryAglintCache: true, + }); + + await pullSettings(context, connection); + + expect(lintingOperations.refreshLinter).toHaveBeenCalled(); + }); + + it('should refresh when cache setting changes', async () => { + const context = createMockServerContext(); + context.aglintContext = { existing: true } as any; + context.settings.enableAglint = true; + context.settings.enableInMemoryAglintCache = false; // Was disabled + const connection = createMockConnection(); + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, // Now enabled + }); + + await pullSettings(context, connection); + + expect(lintingOperations.refreshLinter).toHaveBeenCalled(); + }); + }); +}); + +describe('createRetryAglintLoading', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + vi.useRealTimers(); + }); + + it('should return a debounced function', () => { + const context = createMockServerContext(); + const connection = createMockConnection(); + + const retryFn = createRetryAglintLoading(context, connection); + + expect(typeof retryFn).toBe('function'); + expect(retryFn.clear).toBeDefined(); // Debounce functions have .clear() + }); + + it('should retry loading when loading failed and not currently loading', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = true; + const connection = createMockConnection(); + const mockAglintContext = { initialized: true }; + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + vi.mocked(AglintContext.create).mockResolvedValue(mockAglintContext as any); + + const retryFn = createRetryAglintLoading(context, connection); + + // Call and advance timers to trigger debounce + retryFn(); + await vi.advanceTimersByTimeAsync(2000); + + expect(connection.console.info).toHaveBeenCalledWith( + '[lsp] Retrying AGLint loading after package changes settled', + ); + expect(context.aglintLoadingFailed).toBe(false); + }); + + it('should not retry if loading did not fail', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = false; + const connection = createMockConnection(); + + const retryFn = createRetryAglintLoading(context, connection); + + retryFn(); + await vi.advanceTimersByTimeAsync(2000); + + expect(connection.console.info).not.toHaveBeenCalled(); + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should not retry if currently loading', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = true; + context.aglintLoading = true; + const connection = createMockConnection(); + + const retryFn = createRetryAglintLoading(context, connection); + + retryFn(); + await vi.advanceTimersByTimeAsync(2000); + + expect(AglintContext.create).not.toHaveBeenCalled(); + }); + + it('should debounce multiple calls', async () => { + const context = createMockServerContext(); + context.aglintLoadingFailed = true; + const connection = createMockConnection(); + const mockAglintContext = { initialized: true }; + + connection.workspace.getConfiguration.mockResolvedValue({ + enableAglint: true, + enableInMemoryAglintCache: true, + }); + vi.mocked(AglintContext.create).mockResolvedValue(mockAglintContext as any); + + const retryFn = createRetryAglintLoading(context, connection); + + // Call multiple times quickly + retryFn(); + await vi.advanceTimersByTimeAsync(100); + retryFn(); + await vi.advanceTimersByTimeAsync(100); + retryFn(); + + // Advance to trigger debounce + await vi.advanceTimersByTimeAsync(2000); + + // Should execute, but due to debouncing, multiple quick calls result in one execution + expect(connection.console.info).toHaveBeenCalled(); + expect(connection.console.info).toHaveBeenCalledWith( + '[lsp] Retrying AGLint loading after package changes settled', + ); + }); +}); diff --git a/server/test/handlers/initialization.test.ts b/server/test/handlers/initialization.test.ts new file mode 100644 index 0000000..11a6664 --- /dev/null +++ b/server/test/handlers/initialization.test.ts @@ -0,0 +1,327 @@ +/** + * @file Tests for server initialization handler. + */ + +import { + describe, + expect, + it, + vi, +} from 'vitest'; +import { TextDocumentSyncKind } from 'vscode-languageserver/node'; + +import { handleInitialize } from '../../src/handlers/initialization'; +import { createMockServerContext } from '../helpers'; + +describe('handleInitialize', () => { + describe('server capabilities', () => { + it('should return correct server capabilities', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + const result = handleInitialize(params, context); + + expect(result.capabilities).toEqual({ + codeActionProvider: true, + textDocumentSync: { + openClose: true, + change: TextDocumentSyncKind.Incremental, + }, + }); + }); + + it('should always enable code action provider', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + const result = handleInitialize(params, context); + + expect(result.capabilities.codeActionProvider).toBe(true); + }); + + it('should always configure text document sync', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + const result = handleInitialize(params, context); + + expect(result.capabilities.textDocumentSync).toEqual({ + openClose: true, + change: TextDocumentSyncKind.Incremental, + }); + }); + }); + + describe('debug mode initialization', () => { + it('should set initialDebugMode to true when enabled in options', () => { + const params = { + capabilities: {}, + initializationOptions: { + enableAglintDebug: true, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(true); + }); + + it('should set initialDebugMode to false when disabled in options', () => { + const params = { + capabilities: {}, + initializationOptions: { + enableAglintDebug: false, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(false); + }); + + it('should not change initialDebugMode when not provided', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + context.initialDebugMode = true; // Set to true initially + + handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(true); // Should remain unchanged + }); + + it('should ignore non-boolean enableAglintDebug values', () => { + const params = { + capabilities: {}, + initializationOptions: { + enableAglintDebug: 'true', // String, not boolean + }, + } as any; + const context = createMockServerContext(); + const originalDebugMode = context.initialDebugMode; + + handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(originalDebugMode); + }); + }); + + describe('workspace root extraction', () => { + it('should extract workspace root from file URI', () => { + const params = { + capabilities: {}, + rootUri: 'file:///Users/test/workspace', + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.workspaceRoot).toBe('/Users/test/workspace'); + }); + + it('should use rootPath as fallback when URI conversion fails', () => { + const params = { + capabilities: {}, + rootUri: 'vscode://custom/uri', + rootPath: '/fallback/path', + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.workspaceRoot).toBe('/fallback/path'); + }); + + it('should set workspaceRoot to undefined when no workspace info available', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.workspaceRoot).toBeUndefined(); + }); + + it('should log initialization message with workspace root', () => { + const params = { + capabilities: {}, + rootUri: 'file:///Users/test/workspace', + } as any; + const context = createMockServerContext(); + const debugSpy = vi.spyOn(context.connection.console, 'debug'); + + handleInitialize(params, context); + + expect(debugSpy).toHaveBeenCalledWith( + '[lsp] AGLint Language Server initialized with workspace root: /Users/test/workspace', + ); + }); + + it('should log initialization message without workspace root', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + const debugSpy = vi.spyOn(context.connection.console, 'debug'); + + handleInitialize(params, context); + + expect(debugSpy).toHaveBeenCalledWith( + '[lsp] AGLint Language Server initialized without workspace root', + ); + }); + }); + + describe('client capabilities detection', () => { + it('should detect workspace configuration capability', () => { + const params = { + capabilities: { + workspace: { + configuration: true, + }, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasConfigurationCapability).toBe(true); + }); + + it('should detect missing workspace configuration capability', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasConfigurationCapability).toBe(false); + }); + + it('should detect workspace folders capability', () => { + const params = { + capabilities: { + workspace: { + workspaceFolders: true, + }, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasWorkspaceFolderCapability).toBe(true); + }); + + it('should detect missing workspace folders capability', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasWorkspaceFolderCapability).toBe(false); + }); + + it('should detect both capabilities when present', () => { + const params = { + capabilities: { + workspace: { + configuration: true, + workspaceFolders: true, + }, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasConfigurationCapability).toBe(true); + expect(context.hasWorkspaceFolderCapability).toBe(true); + }); + + it('should handle null workspace capabilities', () => { + const params = { + capabilities: { + workspace: null, + }, + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.hasConfigurationCapability).toBe(false); + expect(context.hasWorkspaceFolderCapability).toBe(false); + }); + }); + + describe('integration scenarios', () => { + it('should handle complete initialization with all options', () => { + const params = { + capabilities: { + workspace: { + configuration: true, + workspaceFolders: true, + }, + }, + initializationOptions: { + enableAglintDebug: true, + workspaceFolder: { + uri: 'file:///complete/workspace', + }, + }, + rootUri: 'file:///complete/workspace', + } as any; + const context = createMockServerContext(); + + const result = handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(true); + expect(context.workspaceRoot).toBe('/complete/workspace'); + expect(context.hasConfigurationCapability).toBe(true); + expect(context.hasWorkspaceFolderCapability).toBe(true); + expect(result.capabilities.codeActionProvider).toBe(true); + }); + + it('should handle minimal initialization', () => { + const params = { + capabilities: {}, + } as any; + const context = createMockServerContext(); + + const result = handleInitialize(params, context); + + expect(context.initialDebugMode).toBe(false); + expect(context.workspaceRoot).toBeUndefined(); + expect(context.hasConfigurationCapability).toBe(false); + expect(context.hasWorkspaceFolderCapability).toBe(false); + expect(result.capabilities).toBeDefined(); + }); + + it('should handle initialization with Windows paths', () => { + const params = { + capabilities: {}, + rootUri: 'file:///C:/Users/test/workspace', + } as any; + const context = createMockServerContext(); + + handleInitialize(params, context); + + expect(context.workspaceRoot).toBeDefined(); + expect(context.workspaceRoot).toContain('Users'); + expect(context.workspaceRoot).toContain('test'); + }); + }); +}); diff --git a/server/test/helpers/index.ts b/server/test/helpers/index.ts new file mode 100644 index 0000000..ddad1d4 --- /dev/null +++ b/server/test/helpers/index.ts @@ -0,0 +1,5 @@ +/** + * @file Test helpers re-exports. + */ + +export { createMockConnection, createMockServerContext } from './mocks'; diff --git a/server/test/helpers/mocks.ts b/server/test/helpers/mocks.ts new file mode 100644 index 0000000..eac66b2 --- /dev/null +++ b/server/test/helpers/mocks.ts @@ -0,0 +1,87 @@ +/** + * @file Shared test mocks and helpers. + */ + +import { vi } from 'vitest'; + +import type { ServerContext } from '../../src/context/server-context'; +import { defaultSettings } from '../../src/settings'; + +/** + * Creates a mock connection for testing. + * + * @returns Mock connection object. + */ +export function createMockConnection() { + return { + workspace: { + getConfiguration: vi.fn(), + }, + console: { + debug: vi.fn(), + info: vi.fn(), + error: vi.fn(), + warn: vi.fn(), + log: vi.fn(), + }, + sendNotification: vi.fn(), + onNotification: vi.fn(), + onRequest: vi.fn(), + onCodeAction: vi.fn(), + } as any; +} + +/** + * Creates a mock ServerContext for testing. + * + * @param overrides Optional overrides for specific properties. + * + * @returns Mock server context. + */ +export function createMockServerContext(overrides?: Partial): ServerContext { + const mockContext = { + connection: createMockConnection(), + documents: { + all: vi.fn(() => []), + get: vi.fn(), + keys: vi.fn(() => []), + } as any, + settings: { ...defaultSettings }, + workspaceRoot: '/test/workspace', + initialDebugMode: false, + hasConfigurationCapability: true, + hasWorkspaceFolderCapability: false, + aglintContext: null, + aglintLoading: false, + aglintLoadingFailed: false, + lintingCache: new Map(), + // Add mutation methods + updateSettings: vi.fn((settings) => { + mockContext.settings = settings; + }), + updateInitialDebugMode: vi.fn((enabled) => { + mockContext.initialDebugMode = enabled; + }), + updateAglintContext: vi.fn((context) => { + mockContext.aglintContext = context; + }), + setAglintLoading: vi.fn((loading) => { + mockContext.aglintLoading = loading; + }), + setAglintLoadingFailed: vi.fn((failed) => { + mockContext.aglintLoadingFailed = failed; + }), + setWorkspaceRoot: vi.fn((root) => { + mockContext.workspaceRoot = root; + }), + setConfigurationCapability: vi.fn((hasCapability) => { + mockContext.hasConfigurationCapability = hasCapability; + }), + setWorkspaceFolderCapability: vi.fn((hasCapability) => { + mockContext.hasWorkspaceFolderCapability = hasCapability; + }), + ...overrides, + } as any; + + return mockContext; +} diff --git a/server/test/linting/cache.test.ts b/server/test/linting/cache.test.ts new file mode 100644 index 0000000..bd25d44 --- /dev/null +++ b/server/test/linting/cache.test.ts @@ -0,0 +1,182 @@ +/** + * @file Tests for linting cache management. + */ + +import { + beforeEach, + describe, + expect, + it, +} from 'vitest'; + +import { createLintCacheKey, LintingCache } from '../../src/linting/cache'; + +describe('createLintCacheKey', () => { + it('should create a unique key from uri, version, document version, and config hash', () => { + const key = createLintCacheKey( + 'file:///path/to/file.txt', + '1.0.0', + 5, + 'abc123', + ); + + expect(key).toBe('file:///path/to/file.txt:1.0.0:5:abc123'); + }); + + it('should create different keys for different URIs', () => { + const key1 = createLintCacheKey('file:///path/file1.txt', '1.0.0', 1, 'hash'); + const key2 = createLintCacheKey('file:///path/file2.txt', '1.0.0', 1, 'hash'); + + expect(key1).not.toBe(key2); + }); + + it('should create different keys for different AGLint versions', () => { + const key1 = createLintCacheKey('file:///file.txt', '1.0.0', 1, 'hash'); + const key2 = createLintCacheKey('file:///file.txt', '1.0.1', 1, 'hash'); + + expect(key1).not.toBe(key2); + }); + + it('should create different keys for different document versions', () => { + const key1 = createLintCacheKey('file:///file.txt', '1.0.0', 1, 'hash'); + const key2 = createLintCacheKey('file:///file.txt', '1.0.0', 2, 'hash'); + + expect(key1).not.toBe(key2); + }); + + it('should create different keys for different config hashes', () => { + const key1 = createLintCacheKey('file:///file.txt', '1.0.0', 1, 'hash1'); + const key2 = createLintCacheKey('file:///file.txt', '1.0.0', 1, 'hash2'); + + expect(key1).not.toBe(key2); + }); + + it('should handle empty strings', () => { + const key = createLintCacheKey('', '', 0, ''); + expect(key).toBe('::0:'); + }); + + it('should handle special characters in URIs', () => { + const key = createLintCacheKey( + 'file:///path/with spaces/file.txt', + '1.0.0', + 1, + 'hash', + ); + + expect(key).toContain('file:///path/with spaces/file.txt'); + }); +}); + +describe('LintingCache', () => { + let cache: LintingCache; + + beforeEach(() => { + cache = new LintingCache(); + }); + + describe('get and set', () => { + it('should store and retrieve diagnostics', () => { + const key = 'test-key'; + const diagnostics: any[] = [ + { + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 5 }, + }, + message: 'Test error', + severity: 1, + }, + ]; + + cache.set(key, diagnostics); + const retrieved = cache.get(key); + + expect(retrieved).toEqual(diagnostics); + }); + + it('should return undefined for non-existent keys', () => { + const result = cache.get('non-existent-key'); + expect(result).toBeUndefined(); + }); + + it('should overwrite existing entries', () => { + const key = 'test-key'; + const diagnostics1 = [{ message: 'First', severity: 1 } as any]; + const diagnostics2 = [{ message: 'Second', severity: 2 } as any]; + + cache.set(key, diagnostics1); + cache.set(key, diagnostics2); + + const retrieved = cache.get(key); + expect(retrieved).toEqual(diagnostics2); + }); + + it('should handle empty diagnostics array', () => { + const key = 'test-key'; + const diagnostics: any[] = []; + + cache.set(key, diagnostics); + const retrieved = cache.get(key); + + expect(retrieved).toEqual([]); + }); + + it('should store multiple different entries', () => { + const key1 = 'key-1'; + const key2 = 'key-2'; + const diagnostics1 = [{ message: 'Error 1' } as any]; + const diagnostics2 = [{ message: 'Error 2' } as any]; + + cache.set(key1, diagnostics1); + cache.set(key2, diagnostics2); + + expect(cache.get(key1)).toEqual(diagnostics1); + expect(cache.get(key2)).toEqual(diagnostics2); + }); + }); + + describe('clear', () => { + it('should remove all entries from cache', () => { + const key1 = 'key-1'; + const key2 = 'key-2'; + const diagnostics = [{ message: 'Error' } as any]; + + cache.set(key1, diagnostics); + cache.set(key2, diagnostics); + + cache.clear(); + + expect(cache.get(key1)).toBeUndefined(); + expect(cache.get(key2)).toBeUndefined(); + }); + + it('should allow new entries after clear', () => { + const key = 'test-key'; + const diagnostics = [{ message: 'Error' } as any]; + + cache.set(key, diagnostics); + cache.clear(); + + const newDiagnostics = [{ message: 'New error' } as any]; + cache.set(key, newDiagnostics); + + expect(cache.get(key)).toEqual(newDiagnostics); + }); + }); + + describe('LRU behavior', () => { + it('should maintain entries up to max capacity', () => { + // LRU cache has max 100 entries + // Add 50 entries - all should be accessible + for (let i = 0; i < 50; i += 1) { + cache.set(`key-${i}`, [{ message: `Error ${i}` } as any]); + } + + // All 50 should still be accessible + for (let i = 0; i < 50; i += 1) { + expect(cache.get(`key-${i}`)).toBeDefined(); + } + }); + }); +}); diff --git a/server/test/linting/diagnostics.test.ts b/server/test/linting/diagnostics.test.ts new file mode 100644 index 0000000..9b8a50a --- /dev/null +++ b/server/test/linting/diagnostics.test.ts @@ -0,0 +1,349 @@ +/* eslint-disable @typescript-eslint/no-restricted-imports */ +/** + * @file Tests for diagnostic conversion utilities. + */ + +import { + type LinterFixCommand, + type LinterResult, + type LinterRuleSeverity, + LinterRuleType, + type LinterSuggestion, +} from '@adguard/aglint/linter'; +import { describe, expect, it } from 'vitest'; +import { DiagnosticSeverity } from 'vscode-languageserver/node'; + +import { convertAglintPositionToVscodeRange, convertLinterResultToDiagnostics } from '../../src/linting/diagnostics'; + +describe('convertAglintPositionToVscodeRange', () => { + it('should convert AGLint 1-based positions to VSCode 0-based positions', () => { + const aglintRange = { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }; + + const vscodeRange = convertAglintPositionToVscodeRange(aglintRange); + + expect(vscodeRange.start.line).toBe(0); // 1 - 1 = 0 + expect(vscodeRange.start.character).toBe(0); + expect(vscodeRange.end.line).toBe(0); // 1 - 1 = 0 + expect(vscodeRange.end.character).toBe(5); + }); + + it('should handle multi-line ranges', () => { + const aglintRange = { + start: { line: 5, column: 10 }, + end: { line: 8, column: 20 }, + }; + + const vscodeRange = convertAglintPositionToVscodeRange(aglintRange); + + expect(vscodeRange.start.line).toBe(4); // 5 - 1 + expect(vscodeRange.start.character).toBe(10); + expect(vscodeRange.end.line).toBe(7); // 8 - 1 + expect(vscodeRange.end.character).toBe(20); + }); + + it('should handle zero-column positions', () => { + const aglintRange = { + start: { line: 10, column: 0 }, + end: { line: 10, column: 0 }, + }; + + const vscodeRange = convertAglintPositionToVscodeRange(aglintRange); + + expect(vscodeRange.start.line).toBe(9); // 10 - 1 + expect(vscodeRange.start.character).toBe(0); + expect(vscodeRange.end.line).toBe(9); + expect(vscodeRange.end.character).toBe(0); + }); +}); + +describe('convertLinterResultToDiagnostics', () => { + const mockAglintContext = { + aglint: { + linter: { + LinterRuleSeverity: { + Warning: 1, + Error: 2, + }, + }, + }, + } as any; + + it('should convert AGLint problems to VSCode diagnostics', () => { + const linterResult: LinterResult = { + problems: [ + { + ruleId: 'test-rule', + message: 'Test error message', + severity: 2 as LinterRuleSeverity, // Error + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 }, + }, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics).toHaveLength(1); + expect(diagnostics[0].message).toBe('Test error message'); + expect(diagnostics[0].severity).toBe(DiagnosticSeverity.Error); + expect(diagnostics[0].source).toBe('aglint'); + expect(diagnostics[0].code).toBe('test-rule'); + }); + + it('should convert warning severity correctly', () => { + const linterResult: LinterResult = { + problems: [ + { + message: 'Warning message', + severity: 1 as LinterRuleSeverity, // Warning + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + }, + ], + metadata: {}, + warningCount: 1, + errorCount: 0, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].severity).toBe(DiagnosticSeverity.Warning); + }); + + it('should include code description with documentation URL', () => { + const linterResult: LinterResult = { + problems: [ + { + ruleId: 'test-rule', + message: 'Test error', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + }, + ], + metadata: { + 'test-rule': { + type: LinterRuleType.Layout, + docs: { + name: 'test-rule', + description: 'Test rule', + recommended: false, + url: 'https://example.com/rules/test-rule', + }, + }, + }, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].codeDescription).toEqual({ + href: 'https://example.com/rules/test-rule', + }); + }); + + it('should not include code description if URL is missing', () => { + const linterResult: LinterResult = { + problems: [ + { + ruleId: 'test-rule', + message: 'Test error', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].codeDescription).toBeUndefined(); + }); + + it('should attach fix data when available', () => { + const fixCommand: LinterFixCommand = { + range: [0, 10], + text: 'fixed text', + }; + + const linterResult: LinterResult = { + problems: [ + { + message: 'Test error', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + fix: fixCommand, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].data).toEqual({ fix: fixCommand }); + }); + + it('should attach suggestions data when available', () => { + const suggestions: LinterSuggestion[] = [ + { message: 'Suggestion 1', fix: { range: [0, 5], text: 'fix1' } }, + { message: 'Suggestion 2', fix: { range: [0, 10], text: 'fix2' } }, + ]; + + const linterResult: LinterResult = { + problems: [ + { + message: 'Test error', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + suggestions, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].data).toEqual({ suggestions }); + }); + + it('should attach both fix and suggestions when available', () => { + const fix: LinterFixCommand = { range: [0, 10], text: 'fixed' }; + const suggestions: LinterSuggestion[] = [{ message: 'Suggestion', fix: { range: [0, 5], text: 'fix' } }]; + + const linterResult: LinterResult = { + problems: [ + { + message: 'Test error', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + fix, + suggestions, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].data).toEqual({ fix, suggestions }); + }); + + it('should handle empty problems array', () => { + const linterResult: LinterResult = { + problems: [], + metadata: {}, + warningCount: 0, + errorCount: 0, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics).toEqual([]); + }); + + it('should handle multiple problems', () => { + const linterResult: LinterResult = { + problems: [ + { + message: 'Error 1', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + }, + { + message: 'Error 2', + severity: 1 as LinterRuleSeverity, + position: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 }, + }, + }, + { + message: 'Error 3', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 3, column: 0 }, + end: { line: 3, column: 5 }, + }, + }, + ], + metadata: {}, + warningCount: 1, + errorCount: 2, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics).toHaveLength(3); + expect(diagnostics[0].message).toBe('Error 1'); + expect(diagnostics[1].message).toBe('Error 2'); + expect(diagnostics[2].message).toBe('Error 3'); + }); + + it('should not include code when ruleId is missing', () => { + const linterResult: LinterResult = { + problems: [ + { + message: 'Error without rule', + severity: 2 as LinterRuleSeverity, + position: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 }, + }, + }, + ], + metadata: {}, + warningCount: 0, + errorCount: 1, + fatalErrorCount: 0, + }; + + const diagnostics = convertLinterResultToDiagnostics(linterResult, mockAglintContext); + + expect(diagnostics[0].code).toBeUndefined(); + }); +}); diff --git a/server/test/utils/error.test.ts b/server/test/utils/error.test.ts new file mode 100644 index 0000000..88907e7 --- /dev/null +++ b/server/test/utils/error.test.ts @@ -0,0 +1,171 @@ +/** + * @file Tests for error utilities. + */ + +import { describe, expect, it } from 'vitest'; + +import { getErrorMessage, getErrorStack } from '../../src/utils/error'; + +describe('getErrorMessage', () => { + it('should extract message from Error object', () => { + const error = new Error('Test error message'); + expect(getErrorMessage(error)).toBe('Test error message'); + }); + + it('should extract message from custom error with message property', () => { + const error = { message: 'Custom error message' }; + expect(getErrorMessage(error)).toBe('Custom error message'); + }); + + it('should convert string to error message', () => { + const error = 'Simple string error'; + expect(getErrorMessage(error)).toBe('"Simple string error"'); + }); + + it('should convert number to error message', () => { + const error = 42; + expect(getErrorMessage(error)).toBe('42'); + }); + + it('should convert boolean to error message', () => { + expect(getErrorMessage(true)).toBe('true'); + expect(getErrorMessage(false)).toBe('false'); + }); + + it('should convert null to error message', () => { + expect(getErrorMessage(null)).toBe('null'); + }); + + it('should convert undefined to error message', () => { + expect(getErrorMessage(undefined)).toBe(''); + }); + + it('should convert object to JSON string error message', () => { + const error = { code: 'ERR_001', details: 'Something went wrong' }; + const message = getErrorMessage(error); + expect(message).toContain('ERR_001'); + expect(message).toContain('Something went wrong'); + }); + + it('should handle objects with circular references', () => { + const error: any = { name: 'CircularError' }; + error.self = error; // Create circular reference + + const message = getErrorMessage(error); + expect(message).toBeTruthy(); + // Should not throw and should contain some string representation + expect(typeof message).toBe('string'); + }); + + it('should handle array as error', () => { + const error = ['error1', 'error2']; + const message = getErrorMessage(error); + expect(message).toContain('error1'); + expect(message).toContain('error2'); + }); + + it('should handle nested error objects', () => { + const error = { + message: 'Outer error', + cause: new Error('Inner error'), + }; + expect(getErrorMessage(error)).toBe('Outer error'); + }); +}); + +describe('getErrorStack', () => { + it('should extract stack trace from Error object', () => { + const error = new Error('Test error'); + const stack = getErrorStack(error); + + expect(stack).toBeDefined(); + expect(stack).toContain('Error'); + }); + + it('should return undefined for objects without stack', () => { + const error = { message: 'No stack here' }; + const stack = getErrorStack(error); + + // Stack should be undefined for plain objects + expect(stack).toBeUndefined(); + }); + + it('should handle string errors', () => { + const error = 'String error'; + const stack = getErrorStack(error); + + // String errors get converted to Error objects which have stacks + expect(typeof stack).toBe('string'); + }); + + it('should handle Error with custom stack property', () => { + const error = new Error('Test'); + error.stack = 'Custom stack trace'; + + expect(getErrorStack(error)).toBe('Custom stack trace'); + }); + + it('should handle null and undefined', () => { + // Both should be converted to Error objects with stacks + expect(typeof getErrorStack(null)).toBe('string'); + expect(typeof getErrorStack(undefined)).toBe('string'); + }); + + it('should handle objects with circular references', () => { + const error: any = { name: 'CircularError' }; + error.self = error; + + const stack = getErrorStack(error); + // Should not throw + expect(stack !== undefined || stack === undefined).toBe(true); + }); +}); + +describe('error utilities edge cases', () => { + it('should handle Symbol as error', () => { + const error = Symbol('test-symbol'); + const message = getErrorMessage(error); + + // Symbols can't be JSON-stringified (returns undefined), which becomes empty string + expect(typeof message).toBe('string'); + // The actual message will be empty since JSON.stringify(Symbol) is undefined + }); + + it('should handle function as error', () => { + const error = function testFunction() { return 'error'; }; + const message = getErrorMessage(error); + + expect(typeof message).toBe('string'); + }); + + it('should handle BigInt as error', () => { + const error = BigInt(9007199254740991); + const message = getErrorMessage(error); + + expect(message).toContain('9007199254740991'); + }); + + it('should preserve Error subclass information', () => { + /** + * Custom error class for testing. + */ + class CustomError extends Error { + /** + * Creates a CustomError. + * + * @param message Error message. + */ + constructor(message: string) { + super(message); + this.name = 'CustomError'; + } + } + + const error = new CustomError('Custom error occurred'); + expect(getErrorMessage(error)).toBe('Custom error occurred'); + + const stack = getErrorStack(error); + expect(stack).toBeDefined(); + expect(stack).toContain('CustomError'); + }); +}); diff --git a/server/test/utils/package-managers.test.ts b/server/test/utils/package-managers.test.ts new file mode 100644 index 0000000..2411415 --- /dev/null +++ b/server/test/utils/package-managers.test.ts @@ -0,0 +1,222 @@ +/** + * @file Tests for package manager utilities. + */ + +import { + describe, + expect, + it, + vi, +} from 'vitest'; + +import { + BUN, + findGlobalPathForPackageManager, + getInstallationCommand, + NPM, + PNPM, + YARN, +} from '../../src/utils/package-managers'; + +// Mock the internal 'run' function that spawns child processes +// This prevents actual shell command execution during tests +vi.mock('node:child_process', () => ({ + spawnSync: vi.fn(() => ({ + status: 0, + stdout: Buffer.from('/mock/global/path\n'), + stderr: Buffer.from(''), + })), +})); + +describe('package manager constants', () => { + it('should export correct package manager constants', () => { + expect(NPM).toBe('npm'); + expect(YARN).toBe('yarn'); + expect(PNPM).toBe('pnpm'); + expect(BUN).toBe('bun'); + }); +}); + +describe('getInstallationCommand', () => { + describe('npm', () => { + it('should generate local install command', () => { + expect(getInstallationCommand(NPM, 'package-name')).toBe('npm install package-name'); + }); + + it('should generate global install command', () => { + expect(getInstallationCommand(NPM, 'package-name', true)).toBe('npm install -g package-name'); + }); + + it('should handle package with scope', () => { + expect(getInstallationCommand(NPM, '@scope/package')).toBe('npm install @scope/package'); + }); + + it('should handle package with version', () => { + expect(getInstallationCommand(NPM, 'package@1.2.3')).toBe('npm install package@1.2.3'); + }); + }); + + describe('yarn', () => { + it('should generate local install command', () => { + expect(getInstallationCommand(YARN, 'package-name')).toBe('yarn add package-name'); + }); + + it('should generate global install command', () => { + expect(getInstallationCommand(YARN, 'package-name', true)).toBe('yarn global add package-name'); + }); + + it('should handle scoped packages', () => { + expect(getInstallationCommand(YARN, '@scope/package')).toBe('yarn add @scope/package'); + }); + + it('should handle packages with version', () => { + expect(getInstallationCommand(YARN, 'package@1.2.3')).toBe('yarn add package@1.2.3'); + }); + }); + + describe('pnpm', () => { + it('should generate local install command', () => { + expect(getInstallationCommand(PNPM, 'package-name')).toBe('pnpm add package-name'); + }); + + it('should generate global install command', () => { + expect(getInstallationCommand(PNPM, 'package-name', true)).toBe('pnpm add -g package-name'); + }); + + it('should handle scoped packages', () => { + expect(getInstallationCommand(PNPM, '@scope/package')).toBe('pnpm add @scope/package'); + }); + + it('should handle packages with version', () => { + expect(getInstallationCommand(PNPM, 'package@1.2.3')).toBe('pnpm add package@1.2.3'); + }); + }); + + describe('bun', () => { + it('should generate local install command', () => { + expect(getInstallationCommand(BUN, 'package-name')).toBe('bun add package-name'); + }); + + it('should generate global install command', () => { + expect(getInstallationCommand(BUN, 'package-name', true)).toBe('bun add -g package-name'); + }); + + it('should handle scoped packages', () => { + expect(getInstallationCommand(BUN, '@scope/package')).toBe('bun add @scope/package'); + }); + + it('should handle packages with version', () => { + expect(getInstallationCommand(BUN, 'package@1.2.3')).toBe('bun add package@1.2.3'); + }); + }); + + describe('edge cases', () => { + it('should handle empty package name', () => { + const cmd = getInstallationCommand(NPM, ''); + expect(cmd).toContain('npm install'); + }); + + it('should handle package names with special characters', () => { + expect(getInstallationCommand(NPM, 'package-with-dashes')).toBe('npm install package-with-dashes'); + }); + + it('should handle very long package names', () => { + const longName = 'a'.repeat(100); + const cmd = getInstallationCommand(NPM, longName); + expect(cmd).toContain(longName); + }); + + it('should handle unknown package manager gracefully', () => { + const cmd = getInstallationCommand('unknown' as any, 'package'); + expect(cmd).toBe('Unknown package manager'); + }); + }); +}); + +describe('findGlobalPathForPackageManager', () => { + it('should be an async function', () => { + expect(findGlobalPathForPackageManager).toBeInstanceOf(Function); + const result = findGlobalPathForPackageManager(NPM); + expect(result).toBeInstanceOf(Promise); + }); + + it('should accept NPM as package manager', async () => { + // We can't test actual execution without mocking child_process, + // but we can verify it doesn't throw + const result = await findGlobalPathForPackageManager(NPM); + // Result can be string or undefined depending on system + expect(typeof result === 'string' || result === undefined).toBe(true); + }); + + it('should accept YARN as package manager', async () => { + const result = await findGlobalPathForPackageManager(YARN); + expect(typeof result === 'string' || result === undefined).toBe(true); + }); + + it('should accept PNPM as package manager', async () => { + const result = await findGlobalPathForPackageManager(PNPM); + expect(typeof result === 'string' || result === undefined).toBe(true); + }); + + it('should accept BUN as package manager', async () => { + const result = await findGlobalPathForPackageManager(BUN); + expect(typeof result === 'string' || result === undefined).toBe(true); + }); + + it('should accept tracer function', async () => { + const traces: string[] = []; + const tracer = (msg: string) => traces.push(msg); + + await findGlobalPathForPackageManager(NPM, tracer); + + // Tracer may or may not be called depending on system state + // Just verify it doesn't throw + expect(Array.isArray(traces)).toBe(true); + }); + + it('should return undefined for unknown package manager', async () => { + const result = await findGlobalPathForPackageManager('unknown' as any); + expect(result).toBeUndefined(); + }); +}); + +describe('command format validation', () => { + it('should generate valid shell commands for all package managers', () => { + const packageManagers = [NPM, YARN, PNPM, BUN]; + const testPackage = 'test-package'; + + packageManagers.forEach((pm) => { + const localCmd = getInstallationCommand(pm, testPackage, false); + const globalCmd = getInstallationCommand(pm, testPackage, true); + + // Commands should contain the package manager name + expect(localCmd).toContain(pm); + expect(globalCmd).toContain(pm); + + // Commands should contain the package name + expect(localCmd).toContain(testPackage); + expect(globalCmd).toContain(testPackage); + + // Global commands should have global flag + if (pm === YARN) { + expect(globalCmd).toContain('global'); + } else { + expect(globalCmd).toContain('-g'); + } + }); + }); + + it('should generate commands without extra whitespace', () => { + const cmd = getInstallationCommand(NPM, 'package'); + expect(cmd).not.toMatch(/\s{2,}/); // No double spaces + expect(cmd.trim()).toBe(cmd); // No leading/trailing spaces + }); + + it('should maintain command structure consistency', () => { + // All commands should follow pattern: + expect(getInstallationCommand(NPM, 'pkg')).toMatch(/^npm install pkg$/); + expect(getInstallationCommand(YARN, 'pkg')).toMatch(/^yarn add pkg$/); + expect(getInstallationCommand(PNPM, 'pkg')).toMatch(/^pnpm add pkg$/); + expect(getInstallationCommand(BUN, 'pkg')).toMatch(/^bun add pkg$/); + }); +}); diff --git a/server/test/utils/uri.test.ts b/server/test/utils/uri.test.ts new file mode 100644 index 0000000..e8db59f --- /dev/null +++ b/server/test/utils/uri.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest'; + +import { isFileUri } from '../../src/utils/uri'; + +describe('isFileUri', () => { + it('returns true for a valid file URI', () => { + expect(isFileUri('file:///Users/test/project/file.txt')).toBe(true); + expect(isFileUri('file:///C:/Users/test/file.txt')).toBe(true); // Windows-style path + }); + + it('returns false for non-file URIs', () => { + expect(isFileUri('http://example.com')).toBe(false); + expect(isFileUri('https://example.com')).toBe(false); + expect(isFileUri('ftp://example.com')).toBe(false); + expect(isFileUri('vscode://file/path')).toBe(false); + }); + + it('is case-insensitive for scheme', () => { + expect(isFileUri('FILE:///Users/test/file.txt')).toBe(true); + expect(isFileUri('File:///Users/test/file.txt')).toBe(true); + }); +}); diff --git a/server/test/utils/workspace.test.ts b/server/test/utils/workspace.test.ts new file mode 100644 index 0000000..96c256b --- /dev/null +++ b/server/test/utils/workspace.test.ts @@ -0,0 +1,231 @@ +/** + * @file Tests for workspace utilities. + */ + +import { describe, expect, it } from 'vitest'; + +import { extractWorkspaceRootUri, getWorkspaceRootFromRootUri } from '../../src/utils/workspace'; + +describe('extractWorkspaceRootUri', () => { + it('should extract from initializationOptions.workspaceFolder.uri (highest priority)', () => { + const params = { + initializationOptions: { + workspaceFolder: { + uri: 'file:///workspace/from/init-options', + }, + }, + rootUri: 'file:///workspace/from/rootUri', + workspaceFolders: [ + { uri: 'file:///workspace/from/folders', name: 'test' }, + ], + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///workspace/from/init-options'); + }); + + it('should extract from rootUri when initializationOptions.workspaceFolder is not available', () => { + const params = { + rootUri: 'file:///workspace/from/rootUri', + workspaceFolders: [ + { uri: 'file:///workspace/from/folders', name: 'test' }, + ], + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///workspace/from/rootUri'); + }); + + it('should extract from workspaceFolders[0] when neither initializationOptions nor rootUri available', () => { + const params = { + workspaceFolders: [ + { uri: 'file:///workspace/from/folders', name: 'test' }, + ], + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///workspace/from/folders'); + }); + + it('should return undefined when no workspace information is available', () => { + const params = {} as any; + + expect(extractWorkspaceRootUri(params)).toBeUndefined(); + }); + + it('should return undefined when workspaceFolders is empty array', () => { + const params = { + workspaceFolders: [], + } as any; + + expect(extractWorkspaceRootUri(params)).toBeUndefined(); + }); + + it('should return undefined when initializationOptions exists but workspaceFolder is missing', () => { + const params = { + initializationOptions: { + someOtherOption: true, + }, + rootUri: null, + } as any; + + // rootUri is null (falsy), so logic falls through and returns undefined + expect(extractWorkspaceRootUri(params)).toBeUndefined(); + }); + + it('should handle multiple workspace folders and pick the first one', () => { + const params = { + workspaceFolders: [ + { uri: 'file:///workspace/first', name: 'first' }, + { uri: 'file:///workspace/second', name: 'second' }, + { uri: 'file:///workspace/third', name: 'third' }, + ], + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///workspace/first'); + }); + + it('should prioritize initializationOptions even when all sources are present', () => { + const params = { + initializationOptions: { + workspaceFolder: { + uri: 'file:///priority/init-options', + }, + }, + rootUri: 'file:///priority/rootUri', + workspaceFolders: [ + { uri: 'file:///priority/folders', name: 'test' }, + ], + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///priority/init-options'); + }); + + it('should handle Windows-style file URIs', () => { + const params = { + rootUri: 'file:///C:/Users/test/workspace', + } as any; + + expect(extractWorkspaceRootUri(params)).toBe('file:///C:/Users/test/workspace'); + }); +}); + +describe('getWorkspaceRootFromRootUri', () => { + it('should convert file URI to path', () => { + const uri = 'file:///Users/test/workspace'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBe('/Users/test/workspace'); + }); + + it('should return undefined for non-file URI (http)', () => { + const uri = 'http://example.com/workspace'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeUndefined(); + }); + + it('should return undefined for non-file URI (https)', () => { + const uri = 'https://example.com/workspace'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeUndefined(); + }); + + it('should return undefined for undefined URI', () => { + const path = getWorkspaceRootFromRootUri(undefined); + + expect(path).toBeUndefined(); + }); + + it('should return undefined for empty string', () => { + const path = getWorkspaceRootFromRootUri(''); + + expect(path).toBeUndefined(); + }); + + it('should handle Windows-style file URI', () => { + const uri = 'file:///C:/Users/test/workspace'; + const path = getWorkspaceRootFromRootUri(uri); + + // On Windows this will return C:\Users\test\workspace + // On Unix this will return /C:/Users/test/workspace + expect(path).toBeDefined(); + expect(path).toContain('Users'); + expect(path).toContain('test'); + expect(path).toContain('workspace'); + }); + + it('should handle file URI with special characters', () => { + const uri = 'file:///workspace/with%20spaces'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeDefined(); + expect(path).toContain('with spaces'); + }); + + it('should handle file URI with encoded characters', () => { + // Note: fileURLToPath throws on encoded slashes + const uri = 'file:///workspace/with%20spaces'; // Use encoded space instead + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeDefined(); + expect(path).toContain('workspace'); + expect(path).toContain('with spaces'); + }); + + it('should return undefined for malformed URIs', () => { + // Malformed URIs are not file:// URIs, so isFileUri returns false + const path = getWorkspaceRootFromRootUri('vscode://file'); + + expect(path).toBeUndefined(); + }); + + it('should handle file URI with trailing slash', () => { + const uri = 'file:///Users/test/workspace/'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeDefined(); + expect(path).toContain('workspace'); + }); + + it('should handle file URI with query parameters (edge case)', () => { + const uri = 'file:///Users/test/workspace?param=value'; + const path = getWorkspaceRootFromRootUri(uri); + + expect(path).toBeDefined(); + }); +}); + +describe('workspace utilities integration', () => { + it('should handle full workflow from params to path', () => { + const params = { + rootUri: 'file:///Users/developer/project', + } as any; + + const uri = extractWorkspaceRootUri(params); + expect(uri).toBe('file:///Users/developer/project'); + + const path = getWorkspaceRootFromRootUri(uri); + expect(path).toBe('/Users/developer/project'); + }); + + it('should handle workflow with no workspace info', () => { + const params = {} as any; + + const uri = extractWorkspaceRootUri(params); + expect(uri).toBeUndefined(); + + const path = getWorkspaceRootFromRootUri(uri); + expect(path).toBeUndefined(); + }); + + it('should handle workflow with non-file URI', () => { + const params = { + rootUri: 'vscode://file/path', + } as any; + + const uri = extractWorkspaceRootUri(params); + expect(uri).toBe('vscode://file/path'); + + const path = getWorkspaceRootFromRootUri(uri); + expect(path).toBeUndefined(); // Not a file:// URI + }); +}); diff --git a/server/tsconfig.base.json b/server/tsconfig.base.json new file mode 100644 index 0000000..900ed38 --- /dev/null +++ b/server/tsconfig.base.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.base.json" +} diff --git a/server/tsconfig.build.json b/server/tsconfig.build.json new file mode 100644 index 0000000..8bff08d --- /dev/null +++ b/server/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "out", + "rootDir": "src", + "declaration": true, + "emitDeclarationOnly": true, + "noEmit": false, + "types": ["node"] + }, + "include": ["src/**/*"] +} diff --git a/server/tsconfig.json b/server/tsconfig.json index e2df667..fade2fd 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -1,16 +1,14 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "target": "es2020", - "lib": ["es2020"], - "module": "preserve", - "moduleResolution": "bundler", - "sourceMap": true, - "strict": true, - "outDir": "out", - "rootDir": "src", - "esModuleInterop": true, - "skipLibCheck": true + "noEmit": true }, - "include": ["src"], + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ".eslintrc.cjs", + "vitest.config.ts", + "rspack.config.ts" + ], "exclude": ["node_modules", ".vscode-test"] } diff --git a/server/vitest.config.ts b/server/vitest.config.ts new file mode 100644 index 0000000..4ea1026 --- /dev/null +++ b/server/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + watch: false, + coverage: { + include: [ + 'src/**/*.ts', + ], + }, + }, +}); diff --git a/shared/.eslintrc.cjs b/shared/.eslintrc.cjs new file mode 100644 index 0000000..fb10704 --- /dev/null +++ b/shared/.eslintrc.cjs @@ -0,0 +1,9 @@ +const path = require('node:path'); + +module.exports = { + extends: '../.eslintrc.cjs', + parserOptions: { + tsconfigRootDir: path.join(__dirname), + project: 'tsconfig.json', + }, +}; diff --git a/shared/.lintstagedrc.js b/shared/.lintstagedrc.js new file mode 100644 index 0000000..a589197 --- /dev/null +++ b/shared/.lintstagedrc.js @@ -0,0 +1,33 @@ +/** @type {import('lint-staged').Configuration} */ +const path = require('node:path'); + +/** + * Make file path relative to the current working directory + * + * @param {string} file File path + * + * @returns {string} Relative path + */ +const makeRelative = (file) => path.relative(process.cwd(), file); + +module.exports = { + '**/*.md': 'markdownlint', + '**/*.js': 'eslint --cache', + '**/*.ts': [ + // Type-check only the staged TS files while still honoring tsconfig + // Exclude config files that import build tools (they're checked by tsconfig.json) + (files) => { + const filesToCheck = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return filesToCheck.length > 0 ? `tsc-files --noEmit ${filesToCheck.join(' ')}` : 'echo "No files to type-check"'; + }, + + // Run tests that are related to those changed files + (files) => { + const testableFiles = files.filter(file => !file.includes('rspack.config.ts') && !file.includes('vitest.config.ts')); + return testableFiles.length > 0 ? `vitest related --run ${testableFiles.map(makeRelative).join(' ')}` : 'echo "No test files"'; + }, + + // Lint the staged TS files + 'eslint --cache', + ], +}; diff --git a/shared/README.md b/shared/README.md new file mode 100644 index 0000000..e5c2b2d --- /dev/null +++ b/shared/README.md @@ -0,0 +1,6 @@ +# @vscode-adblock-syntax/shared + +Shared utilities for vscode-adblock-syntax packages. + +This package contains common utilities and types shared between the client and server +packages. diff --git a/shared/package.json b/shared/package.json new file mode 100644 index 0000000..2721ec6 --- /dev/null +++ b/shared/package.json @@ -0,0 +1,44 @@ +{ + "name": "@vscode-adblock-syntax/shared", + "description": "Shared utilities for vscode-adblock-syntax packages.", + "version": "1.0.0", + "license": "MIT", + "author": "AdGuard Software Ltd.", + "private": true, + "files": [ + "out" + ], + "exports": { + ".": { + "types": "./out/index.d.ts", + "import": "./out/index.js" + } + }, + "typesVersions": { + "*": { + "*": [ + "out/index.d.ts" + ] + } + }, + "engines": { + "node": ">=20.0.0" + }, + "scripts": { + "prebuild": "rimraf out", + "build": "rspack", + "postbuild": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "test": "vitest", + "lint:code": "eslint . --cache --ext .ts --ext .js --ext .cjs", + "lint:md": "markdownlint . --ignore-path ../.markdownlintignore", + "lint": "pnpm run lint:code && pnpm run lint:md" + }, + "devDependencies": { + "@rspack/cli": "catalog:", + "@rspack/core": "catalog:", + "rimraf": "catalog:", + "tsc-files": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + } +} diff --git a/shared/rspack.config.ts b/shared/rspack.config.ts new file mode 100644 index 0000000..50f7201 --- /dev/null +++ b/shared/rspack.config.ts @@ -0,0 +1,56 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { resolve } from 'node:path'; + +import { defineConfig } from '@rspack/cli'; + +const isProduction = process.env.NODE_ENV === 'production'; + +export default defineConfig({ + target: 'node', + mode: isProduction ? 'production' : 'development', + + stats: 'normal', + + entry: { + index: './src/index.ts', + 'file-scheme': './src/file-scheme.ts', + }, + + output: { + path: resolve(__dirname, 'out'), + filename: '[name].js', + libraryTarget: 'commonjs2', + clean: true, + }, + + resolve: { + extensions: ['.ts', '.js'], + }, + + module: { + rules: [ + { + test: /\.ts$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + }, + target: 'es2020', + }, + }, + }, + exclude: /node_modules/, + }, + ], + }, + externals: { + vscode: 'commonjs vscode', + }, + optimization: { + minimize: isProduction, + }, + devtool: isProduction ? false : 'source-map', +}); diff --git a/shared/src/file-scheme.ts b/shared/src/file-scheme.ts new file mode 100644 index 0000000..df1fc3f --- /dev/null +++ b/shared/src/file-scheme.ts @@ -0,0 +1,7 @@ +/** + * Schemes for file documents. + */ +export enum FileScheme { + File = 'file', + Untitled = 'untitled', +} diff --git a/shared/src/index.ts b/shared/src/index.ts new file mode 100644 index 0000000..d53090c --- /dev/null +++ b/shared/src/index.ts @@ -0,0 +1,4 @@ +// TODO: Add shared validation logic, schemas (e.g., Valibot), custom LSP protocol types, +// and other utilities that need to be consistent between client and server. + +export { FileScheme } from './file-scheme'; diff --git a/shared/test/.gitkeep b/shared/test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/shared/tsconfig.base.json b/shared/tsconfig.base.json new file mode 100644 index 0000000..900ed38 --- /dev/null +++ b/shared/tsconfig.base.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.base.json" +} diff --git a/shared/tsconfig.build.json b/shared/tsconfig.build.json new file mode 100644 index 0000000..aff8001 --- /dev/null +++ b/shared/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "out", + "rootDir": "src", + "declaration": true, + "emitDeclarationOnly": false, + "noEmit": false, + "types": ["node"] + }, + "include": ["src/**/*"] +} diff --git a/shared/tsconfig.json b/shared/tsconfig.json new file mode 100644 index 0000000..454417c --- /dev/null +++ b/shared/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ".eslintrc.cjs", + "vitest.config.ts", + "rspack.config.ts" + ], + "exclude": ["node_modules"] +} diff --git a/shared/vitest.config.ts b/shared/vitest.config.ts new file mode 100644 index 0000000..34aed49 --- /dev/null +++ b/shared/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + watch: false, + passWithNoTests: true, + coverage: { + include: [ + 'src/**/*.ts', + ], + }, + }, +}); diff --git a/syntaxes/.eslintrc.cjs b/syntaxes/.eslintrc.cjs new file mode 100644 index 0000000..7ca6754 --- /dev/null +++ b/syntaxes/.eslintrc.cjs @@ -0,0 +1,13 @@ +const path = require('node:path'); + +module.exports = { + extends: '../.eslintrc.cjs', + parserOptions: { + tsconfigRootDir: path.join(__dirname), + project: 'tsconfig.json', + }, + rules: { + // In this package we do not have real dependencies, all of them are dev dependencies + 'import/no-extraneous-dependencies': 'off', + }, +}; diff --git a/syntaxes/.lintstagedrc.js b/syntaxes/.lintstagedrc.js new file mode 100644 index 0000000..da27208 --- /dev/null +++ b/syntaxes/.lintstagedrc.js @@ -0,0 +1,35 @@ +/** @type {import('lint-staged').Configuration} */ +const path = require('node:path'); + +/** + * Make file path relative to the current working directory + * + * @param {string} file File path + * + * @returns {string} Relative path + */ +const makeRelative = (file) => path.relative(process.cwd(), file); + +module.exports = { + // run tests if the grammar file are changed + 'adblock.yaml-tmlanguage': 'vitest run', + '**/*.md': 'markdownlint', + '**/*.js': 'eslint --cache', + '**/*.ts': [ + // Type-check only the staged TS files while still honoring tsconfig + // Exclude config files that import build tools (they're checked by tsconfig.json) + (files) => { + const filesToCheck = files.filter(file => !file.includes('vitest.config.ts')); + return filesToCheck.length > 0 ? `tsc-files --noEmit ${filesToCheck.join(' ')}` : 'echo "No files to type-check"'; + }, + + // Run tests that are related to those changed files + (files) => { + const testableFiles = files.filter(file => !file.includes('vitest.config.ts')); + return testableFiles.length > 0 ? `vitest related --run ${testableFiles.map(makeRelative).join(' ')}` : 'echo "No test files"'; + }, + + // Lint the staged TS files + 'eslint --cache', + ], +}; diff --git a/syntaxes/package.json b/syntaxes/package.json new file mode 100644 index 0000000..11924b3 --- /dev/null +++ b/syntaxes/package.json @@ -0,0 +1,32 @@ +{ + "name": "@vscode-adblock-syntax/syntaxes", + "description": "TextMate grammars for Adblock/AdGuard/uBlock filters syntax.", + "version": "1.0.0", + "license": "MIT", + "author": "AdGuard Software Ltd.", + "private": true, + "scripts": { + "prebuild": "rimraf out", + "build": "tsx scripts/build.ts", + "test": "vitest", + "lint:code": "eslint . --cache --ext .ts --ext .js --ext .cjs", + "lint:md": "markdownlint . --ignore-path ../.markdownlintignore", + "lint": "pnpm run lint:code && pnpm run lint:md" + }, + "devDependencies": { + "@types/fs-extra": "catalog:", + "@types/node": "catalog:", + "@types/plist": "catalog:", + "@vitest/expect": "catalog:", + "chokidar": "catalog:", + "fs-extra": "catalog:", + "plist": "catalog:", + "rimraf": "catalog:", + "tsc-files": "catalog:", + "valibot": "catalog:", + "vitest": "catalog:", + "vscode-oniguruma": "catalog:", + "vscode-textmate": "catalog:", + "yaml": "catalog:" + } +} diff --git a/syntaxes/scripts/build.ts b/syntaxes/scripts/build.ts new file mode 100644 index 0000000..5e9dd71 --- /dev/null +++ b/syntaxes/scripts/build.ts @@ -0,0 +1,88 @@ +/* eslint-disable no-console */ +import { readFile, writeFile } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import chokidar from 'chokidar'; +import { ensureDir } from 'fs-extra'; +import { YAMLParseError } from 'yaml'; + +import { getErrorMessage } from '../utils/error'; +import { convertYamlToPlist } from '../utils/grammar-converter'; + +// eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const SOURCE_GRAMMAR_FILENAME = 'adblock.yaml-tmlanguage'; +const DEST_GRAMMAR_FILENAME = 'adblock.plist'; + +const SYNTAXES_FOLDER = join(__dirname, '..'); +const OUT_FOLDER = join(SYNTAXES_FOLDER, 'out'); + +const SOURCE_GRAMMAR_PATH = join(SYNTAXES_FOLDER, SOURCE_GRAMMAR_FILENAME); +const DEST_GRAMMAR_PATH = join(OUT_FOLDER, DEST_GRAMMAR_FILENAME); + +const args = process.argv.slice(2); + +const isProduction = process.env.NODE_ENV === 'production'; + +/** + * Builds the source grammar file into a PList representation. + * + * @param minify Whether to minify the output PList. Default is false. + * + * @throws If the source grammar file doesn't exist. + * @throws If the source grammar file is not a valid YAML file. + * @throws If cannot write the PList representation to the dist folder. + */ +async function buildGrammar(minify = false) { + // Read the raw YAML content from the grammar file + const rawYaml = await readFile(SOURCE_GRAMMAR_PATH, 'utf8'); + + // Convert the YAML content into a PList representation + const plistGrammar = convertYamlToPlist(rawYaml, minify); + + // Write the PList representation to the dist folder + await writeFile(DEST_GRAMMAR_PATH, plistGrammar); +} + +/** + * Builds the grammar, handling errors and logging progress. + */ +async function build() { + console.log('[grammar] build started'); + + try { + await ensureDir(OUT_FOLDER); + await buildGrammar(isProduction); + + // eslint-disable-next-line no-console + console.log(`Grammar file written to ${join(OUT_FOLDER, DEST_GRAMMAR_FILENAME)}`); + } catch (error: unknown) { + // https://eemeli.org/yaml/#errors + if (error instanceof YAMLParseError) { + const severity = error.name === 'YAMLParseError' ? 'error' : 'warn'; + const { line, col } = error.linePos![0]; + + console.error(`[${severity}] ${SOURCE_GRAMMAR_FILENAME}:${line}:${col}: ${error.message}`); + } else { + console.error(`[error] ${getErrorMessage(error)}`); + } + } + + // eslint-disable-next-line no-console + console.log('[grammar] build finished'); +} + +(async () => { + if (args.includes('--watch') || args.includes('-w')) { + await build(); + + chokidar.watch(SOURCE_GRAMMAR_PATH).on('change', async () => { + console.log(`[grammar] ${SOURCE_GRAMMAR_FILENAME} changed, rebuilding...`); + await build(); + }); + } else { + await build(); + } +})(); diff --git a/test/grammar/comments/agent.test.ts b/syntaxes/test/adblock/comments/agent.test.ts similarity index 58% rename from test/grammar/comments/agent.test.ts rename to syntaxes/test/adblock/comments/agent.test.ts index 4cb7d3d..62caa32 100644 --- a/test/grammar/comments/agent.test.ts +++ b/syntaxes/test/adblock/comments/agent.test.ts @@ -2,21 +2,20 @@ * @file Tests for the adblock agents. */ -import { BASE_SCOPE } from '../common/constants'; -import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; -import { expectTokens } from '../common/token-expectation'; +import { beforeAll, expect, test } from 'vitest'; -let tokenize: AdblockTokenizer; +import { BASE_SCOPE } from '../../../utils/constants'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; + +let tokenizer: AdblockTokenizer; -// Before running any tests, we should load the grammar and get the tokenizer beforeAll(async () => { - tokenize = await getAdblockTokenizer(); + tokenizer = await getAdblockTokenizer(); }); test('agents tokenization', () => { - expectTokens( - tokenize, - '[Adblock Plus 2.0]', + expect('[Adblock Plus 2.0]').toBeTokenizedProperly( + tokenizer, [ { fragment: '[', scopes: [BASE_SCOPE, 'punctuation.definition.array.start.adblock.agent'] }, { fragment: 'Adblock Plus', scopes: [BASE_SCOPE, 'constant.language.agent.adblocker.name'] }, diff --git a/test/grammar/comments/comment.test.ts b/syntaxes/test/adblock/comments/comment.test.ts similarity index 70% rename from test/grammar/comments/comment.test.ts rename to syntaxes/test/adblock/comments/comment.test.ts index 1cd45cf..7a818d1 100644 --- a/test/grammar/comments/comment.test.ts +++ b/syntaxes/test/adblock/comments/comment.test.ts @@ -1,33 +1,37 @@ /** * @file Tests for regular comments. */ +import { + beforeAll, + describe, + expect, + test, +} from 'vitest'; -import { BASE_SCOPE } from '../common/constants'; -import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; -import { expectTokens } from '../common/token-expectation'; +import { BASE_SCOPE } from '../../../utils/constants'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; -let tokenize: AdblockTokenizer; +let tokenizer: AdblockTokenizer; // Before running any tests, we should load the grammar and get the tokenizer beforeAll(async () => { - tokenize = await getAdblockTokenizer(); + tokenizer = await getAdblockTokenizer(); }); describe('test comments', () => { test('basic comments', () => { - let fragment = '! this is a comment'; - expectTokens( - tokenize, - fragment, - [{ fragment, scopes: [BASE_SCOPE, 'comment.line.exclamation-sign'] }], + expect('! this is a comment').toBeTokenizedProperly( + tokenizer, + [ + { fragment: '! this is a comment', scopes: [BASE_SCOPE, 'comment.line.exclamation-sign'] }, + ], ); - fragment = '# this is a hashtag comment'; - - expectTokens( - tokenize, - fragment, - [{ fragment, scopes: [BASE_SCOPE, 'comment.line.hashtag-sign'] }], + expect('# this is a hashtag comment').toBeTokenizedProperly( + tokenizer, + [ + { fragment: '# this is a hashtag comment', scopes: [BASE_SCOPE, 'comment.line.hashtag-sign'] }, + ], ); }); @@ -62,7 +66,7 @@ describe('test comments', () => { test.each(cosmeticRules)( "test that string is not a comment, but a cosmetic rule for case '%s'", (cosmeticRule) => { - const tokens = tokenize(cosmeticRule); + const tokens = tokenizer(cosmeticRule); expect(tokens.every(({ scopes }) => { return scopes.every((scope) => { diff --git a/test/grammar/comments/preprocessor.test.ts b/syntaxes/test/adblock/comments/preprocessor.test.ts similarity index 92% rename from test/grammar/comments/preprocessor.test.ts rename to syntaxes/test/adblock/comments/preprocessor.test.ts index a48f666..2764fab 100644 --- a/test/grammar/comments/preprocessor.test.ts +++ b/syntaxes/test/adblock/comments/preprocessor.test.ts @@ -2,15 +2,21 @@ * @file Tests for preprocessing directive comments. */ -import { BASE_SCOPE } from '../common/constants'; -import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; -import { expectTokens } from '../common/token-expectation'; +import { + beforeAll, + describe, + expect, + test, +} from 'vitest'; -let tokenize: AdblockTokenizer; +import { BASE_SCOPE } from '../../../utils/constants'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; + +let tokenizer: AdblockTokenizer; // Before running any tests, we should load the grammar and get the tokenizer beforeAll(async () => { - tokenize = await getAdblockTokenizer(); + tokenizer = await getAdblockTokenizer(); }); describe('Preprocessor directive comments', () => { @@ -61,7 +67,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for valid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); test.each([ @@ -94,7 +100,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for invalid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); }); @@ -108,7 +114,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for valid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); test.each([ @@ -120,7 +126,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for invalid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); }); @@ -134,7 +140,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for valid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); test.each([ @@ -146,7 +152,7 @@ describe('Preprocessor directive comments', () => { ], }, ])('should work for invalid case \'$actual\'', ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); }); @@ -202,7 +208,7 @@ describe('Preprocessor directive comments', () => { ], }, ])("valid: '$actual'", ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); test.each([ @@ -231,7 +237,7 @@ describe('Preprocessor directive comments', () => { ], }, ])("invalid case '$actual'", ({ actual, expected }) => { - expectTokens(tokenize, actual, expected); + expect(actual).toBeTokenizedProperly(tokenizer, expected); }); }); diff --git a/test/grammar/cosmetic/js-inject.test.ts b/syntaxes/test/adblock/cosmetic/js-inject.test.ts similarity index 69% rename from test/grammar/cosmetic/js-inject.test.ts rename to syntaxes/test/adblock/cosmetic/js-inject.test.ts index f325e7e..a05057f 100644 --- a/test/grammar/cosmetic/js-inject.test.ts +++ b/syntaxes/test/adblock/cosmetic/js-inject.test.ts @@ -1,22 +1,26 @@ /** * @file Tests for JS injection rules. */ +import { + beforeAll, + describe, + expect, + test, +} from 'vitest'; -import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; -import { expectTokens } from '../common/token-expectation'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; -let tokenize: AdblockTokenizer; +let tokenizer: AdblockTokenizer; // Before running any tests, we should load the grammar and get the tokenizer beforeAll(async () => { - tokenize = await getAdblockTokenizer(); + tokenizer = await getAdblockTokenizer(); }); describe('JS injection rules', () => { test('should tokenize valid JS injections', () => { - expectTokens( - tokenize, - '#%#window.hello = 1', + expect('#%#window.hello = 1').toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: 'window.hello = 1', scopes: ['text.adblock', 'source.js'] }, @@ -27,9 +31,8 @@ describe('JS injection rules', () => { test('should detect invalid cases', () => { // Unclosed scriptlet call. Since it's not closed, it's not matches as a scriptlet call, // but #%# is "stronger" than scriptlet injection, and we shouldn't tokenize it as a JS comment - expectTokens( - tokenize, - '#%#//scriptlet(\'a\',', + expect('#%#//scriptlet(\'a\',').toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet(\'a\',', scopes: ['text.adblock', 'invalid.illegal'] }, diff --git a/test/grammar/cosmetic/scriptlet.test.ts b/syntaxes/test/adblock/cosmetic/scriptlet.test.ts similarity index 81% rename from test/grammar/cosmetic/scriptlet.test.ts rename to syntaxes/test/adblock/cosmetic/scriptlet.test.ts index 14a07ed..3a564bc 100644 --- a/test/grammar/cosmetic/scriptlet.test.ts +++ b/syntaxes/test/adblock/cosmetic/scriptlet.test.ts @@ -1,24 +1,28 @@ /** * @file Tests for scriptlets rules. */ +import { + beforeAll, + describe, + expect, + test, +} from 'vitest'; -import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; -import { expectTokens } from '../common/token-expectation'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; -let tokenize: AdblockTokenizer; +let tokenizer: AdblockTokenizer; // Before running any tests, we should load the grammar and get the tokenizer beforeAll(async () => { - tokenize = await getAdblockTokenizer(); + tokenizer = await getAdblockTokenizer(); }); describe('scriptlet rules', () => { describe('valid', () => { test('blocking', () => { // single quoted arguments - expectTokens( - tokenize, - "#%#//scriptlet('foo', 'bar')", + expect("#%#//scriptlet('foo', 'bar')").toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -31,9 +35,8 @@ describe('scriptlet rules', () => { ); // double quoted arguments - expectTokens( - tokenize, - '#%#//scriptlet("foo", "bar")', + expect('#%#//scriptlet("foo", "bar")').toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -46,9 +49,8 @@ describe('scriptlet rules', () => { ); // should handle if the argument contain a different quote type - expectTokens( - tokenize, - '#%#//scriptlet("foo\'bar")', + expect('#%#//scriptlet("foo\'bar")').toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -60,9 +62,8 @@ describe('scriptlet rules', () => { }); test('exception for specific scriptlet', () => { - expectTokens( - tokenize, - "#@%#//scriptlet('foo')", + expect("#@%#//scriptlet('foo')").toBeTokenizedProperly( + tokenizer, [ { fragment: '#@%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -74,9 +75,8 @@ describe('scriptlet rules', () => { }); test('exception for all scriptlets', () => { - expectTokens( - tokenize, - '#@%#//scriptlet()', + expect('#@%#//scriptlet()').toBeTokenizedProperly( + tokenizer, [ { fragment: '#@%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -85,9 +85,8 @@ describe('scriptlet rules', () => { ], ); - expectTokens( - tokenize, - '#@%#//scriptlet( )', + expect('#@%#//scriptlet( )').toBeTokenizedProperly( + tokenizer, [ { fragment: '#@%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet', scopes: ['text.adblock', 'entity.name.function.adblock'] }, @@ -101,10 +100,9 @@ describe('scriptlet rules', () => { describe('invalid', () => { test('blocking', () => { - expectTokens( - tokenize, - // blocking scriptlet rule cannot be used without any arguments - '#%#//scriptlet()', + // blocking scriptlet rule cannot be used without any arguments + expect('#%#//scriptlet()').toBeTokenizedProperly( + tokenizer, [ { fragment: '#%#', scopes: ['text.adblock', 'keyword.control.adblock'] }, { fragment: '//scriptlet()', scopes: ['text.adblock', 'invalid.illegal'] }, diff --git a/syntaxes/test/setup/custom-matchers/expect-tokenization.ts b/syntaxes/test/setup/custom-matchers/expect-tokenization.ts new file mode 100644 index 0000000..b77b98a --- /dev/null +++ b/syntaxes/test/setup/custom-matchers/expect-tokenization.ts @@ -0,0 +1,115 @@ +import { type SyncExpectationResult } from '@vitest/expect'; +import * as v from 'valibot'; +import { expect } from 'vitest'; + +import { getErrorMessage } from '../../../utils/error'; +import { type AdblockTokenizer } from '../../../utils/get-adblock-tokenizer'; +import { isArraysEqual } from '../../../utils/utils'; + +const expectedTokenSchema = v.object({ + fragment: v.string(), + scopes: v.array(v.string()), +}); + +const expectedTokensSchema = v.array(expectedTokenSchema); + +type ExpectedTokenSchema = v.InferInput; + +const receivedSchema = v.string(); + +type ReceivedSchema = v.InferInput; + +/** + * Helper function to check rule conversion. + * + * @param received Received parameter from expect(). + * @param tokenizer Tokenizer function. + * @param expectedTokens Expected tokens. + * + * @returns Matcher result. + */ +const toBeTokenizedProperly = ( + received: unknown, + tokenizer: AdblockTokenizer, + expectedTokens: ExpectedTokenSchema, +): SyncExpectationResult => { + // Validate the received parameter + let receivedParsed: ReceivedSchema; + + try { + receivedParsed = v.parse(receivedSchema, received); + } catch (error: unknown) { + return { + pass: false, + message: () => `Received parameter validation failed with error: ${getErrorMessage(error)}`, + }; + } + + // Merging fragments should give us the original source + const mergedFragments = expectedTokens.map((token) => token.fragment).join(''); + + if (mergedFragments !== receivedParsed) { + return { + pass: false, + message: () => 'The merged fragments do not match the source, so the expectation is invalid', + }; + } + + // Tokenize the source + const tokens = tokenizer(receivedParsed); + + // Check that the number of tokens matches the number of expected tokens + if (tokens.length !== expectedTokens.length) { + return { + pass: false, + message: () => `Expected ${expectedTokens.length} tokens, but got ${tokens.length}`, + }; + } + + let offset = 0; + + // Check that each token matches the expected token + for (let i = 0; i < tokens.length; i += 1) { + const endOffset = offset + expectedTokens[i].fragment.length; + + // Check location + if (tokens[i].startIndex !== offset) { + return { + pass: false, + // eslint-disable-next-line max-len, @typescript-eslint/no-loop-func + message: () => `Expected token ${i} to start at offset ${offset}, but it starts at offset ${tokens[i].startIndex}`, + }; + } + + if (tokens[i].endIndex !== endOffset) { + return { + pass: false, + // eslint-disable-next-line max-len, @typescript-eslint/no-loop-func + message: () => `Expected token ${i} to end at offset ${endOffset}, but it ends at offset ${tokens[i].endIndex}`, + }; + } + + if (!isArraysEqual(tokens[i].scopes, expectedTokens[i].scopes)) { + return { + pass: false, + // eslint-disable-next-line max-len, @typescript-eslint/no-loop-func + message: () => `Expected token ${i} to have scopes [${expectedTokens[i].scopes.join(', ')}], but got [${tokens[i].scopes.join(', ')}]`, + }; + } + + // Update the offset + offset = endOffset; + } + + return { + pass: true, + message: () => 'Tokenization succeeded', + }; +}; + +// Extend Vitest's expect() with the custom matcher +expect.extend({ + toBeTokenizedProperly, +}); + +export type ToBeTokenizedProperly = typeof toBeTokenizedProperly; diff --git a/syntaxes/test/setup/custom-matchers/index.ts b/syntaxes/test/setup/custom-matchers/index.ts new file mode 100644 index 0000000..2f45adb --- /dev/null +++ b/syntaxes/test/setup/custom-matchers/index.ts @@ -0,0 +1,6 @@ +/** + * @file Custom Vitest matchers entry point. + * + * @see https://vitest.dev/guide/extending-matchers#extending-matchers + */ +import './expect-tokenization'; diff --git a/syntaxes/tsconfig.base.json b/syntaxes/tsconfig.base.json new file mode 100644 index 0000000..5691a2f --- /dev/null +++ b/syntaxes/tsconfig.base.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "types": ["./typings/vitest-custom.d.ts", "node"] + } +} diff --git a/syntaxes/tsconfig.build.json b/syntaxes/tsconfig.build.json new file mode 100644 index 0000000..8bff08d --- /dev/null +++ b/syntaxes/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "out", + "rootDir": "src", + "declaration": true, + "emitDeclarationOnly": true, + "noEmit": false, + "types": ["node"] + }, + "include": ["src/**/*"] +} diff --git a/syntaxes/tsconfig.json b/syntaxes/tsconfig.json new file mode 100644 index 0000000..00ec24c --- /dev/null +++ b/syntaxes/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ".eslintrc.cjs", + "vitest.config.ts", + "scripts/**/*.ts", + "scripts/.eslintrc.cjs" + ], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/syntaxes/typings/vitest-custom.d.ts b/syntaxes/typings/vitest-custom.d.ts new file mode 100644 index 0000000..7666f48 --- /dev/null +++ b/syntaxes/typings/vitest-custom.d.ts @@ -0,0 +1,26 @@ +/** + * @file Custom types for Vitest to extend `expect` function with custom matchers. + * + * @see https://vitest.dev/guide/extending-matchers#extending-matchers + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import 'vitest'; + +import { type ToBeTokenizedProperly } from '../test/setup/custom-matchers/expect-tokenization'; + +// Note: first argument is passed to `expect`, so we need to remove it +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type RemoveFirstArg = T extends (arg0: any, ...args: infer U) => infer R ? (...args: U) => R : never; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +interface CustomMatchers { + toBeTokenizedProperly: RemoveFirstArg; +} + +declare module 'vitest' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-explicit-any + interface Assertion extends CustomMatchers {} + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface AsymmetricMatchersContaining extends CustomMatchers {} +} diff --git a/test/grammar/common/README.md b/syntaxes/utils/README.md similarity index 100% rename from test/grammar/common/README.md rename to syntaxes/utils/README.md diff --git a/test/grammar/common/adblock-grammar-loader.ts b/syntaxes/utils/adblock-grammar-loader.ts similarity index 85% rename from test/grammar/common/adblock-grammar-loader.ts rename to syntaxes/utils/adblock-grammar-loader.ts index 71b9a06..aff0d42 100644 --- a/test/grammar/common/adblock-grammar-loader.ts +++ b/syntaxes/utils/adblock-grammar-loader.ts @@ -8,12 +8,12 @@ import { join } from 'node:path'; import { loadWASM, OnigScanner, OnigString } from 'vscode-oniguruma'; import { type IGrammar, parseRawGrammar, Registry } from 'vscode-textmate'; -import { convertYamlToPlist } from '../../../tools/grammar-converter'; +import { convertYamlToPlist } from './grammar-converter'; /** * Source file path for the grammar. */ -const ADBLOCK_GRAMMAR_PATH = join(__dirname, '../../../', 'syntaxes/adblock.yaml-tmlanguage'); +const ADBLOCK_GRAMMAR_PATH = join(__dirname, '../', 'adblock.yaml-tmlanguage'); /** * Scope name for the adblock grammar. @@ -28,12 +28,12 @@ const JS_GRAMMAR_SCOPE = 'source.js'; /** * Dummy grammar for JavaScript (raw). */ -const DUMMY_JS_GRAMMAR = `{ - "name": "JavaScript", - "scopeName": "source.js", - "patterns": [], - "repository": {} -}`; +const DUMMY_JS_GRAMMAR = JSON.stringify({ + name: 'JavaScript', + scopeName: 'source.js', + patterns: [], + repository: {}, +}); /** * Fake file name for the dummy JavaScript grammar. @@ -57,7 +57,7 @@ export async function loadAdblockGrammar(): Promise { // Load the wasm library for the oniguruma regex engine // eslint-disable-next-line max-len - const wasmBin = (await readFile(join(__dirname, '../../../', 'node_modules/vscode-oniguruma/release/onig.wasm'))).buffer; + const wasmBin = await readFile(join(__dirname, '../', 'node_modules/vscode-oniguruma/release/onig.wasm')); const vscodeOnigurumaLib = loadWASM(wasmBin).then(() => { return { createOnigScanner(patterns: string[]) { return new OnigScanner(patterns); }, diff --git a/test/grammar/common/constants.ts b/syntaxes/utils/constants.ts similarity index 100% rename from test/grammar/common/constants.ts rename to syntaxes/utils/constants.ts diff --git a/tools/utils/error.ts b/syntaxes/utils/error.ts similarity index 100% rename from tools/utils/error.ts rename to syntaxes/utils/error.ts diff --git a/test/grammar/common/get-adblock-tokenizer.ts b/syntaxes/utils/get-adblock-tokenizer.ts similarity index 100% rename from test/grammar/common/get-adblock-tokenizer.ts rename to syntaxes/utils/get-adblock-tokenizer.ts diff --git a/tools/grammar-converter.ts b/syntaxes/utils/grammar-converter.ts similarity index 65% rename from tools/grammar-converter.ts rename to syntaxes/utils/grammar-converter.ts index 4c9a534..fa47855 100644 --- a/tools/grammar-converter.ts +++ b/syntaxes/utils/grammar-converter.ts @@ -1,19 +1,20 @@ -import { build } from 'plist'; +import plist from 'plist'; import { parse } from 'yaml'; /** * Converts a YAML grammar file into a PList representation. * * @param yamlContent Raw YAML content from the grammar file. + * @param minify Whether to minify the output PList. Default is false. * * @returns PList representation of the grammar. * * @throws If the YAML content is syntactically invalid. */ -export function convertYamlToPlist(yamlContent: string): string { +export function convertYamlToPlist(yamlContent: string, minify = false): string { // Parse the YAML content into a JavaScript object const grammar = parse(yamlContent); // Convert the JavaScript object into a PList representation - return build(grammar); + return plist.build(grammar, { pretty: !minify }); } diff --git a/test/grammar/common/utils.ts b/syntaxes/utils/utils.ts similarity index 100% rename from test/grammar/common/utils.ts rename to syntaxes/utils/utils.ts diff --git a/syntaxes/vitest.config.ts b/syntaxes/vitest.config.ts new file mode 100644 index 0000000..ca1f3c3 --- /dev/null +++ b/syntaxes/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + setupFiles: [ + './test/setup/custom-matchers/index.ts', + ], + watch: false, + }, +}); diff --git a/test/grammar/TODO.md b/test/grammar/TODO.md deleted file mode 100644 index a606f79..0000000 --- a/test/grammar/TODO.md +++ /dev/null @@ -1,9 +0,0 @@ -# TODO - -Currently, the testing logic is implemented, but most of the tests are not yet -written. - -- [x] Implement testing logic for the syntax highlighter (TMLanguage) -- [ ] Tests for comment rules -- [ ] Tests for cosmetic rules -- [ ] Tests for network rules diff --git a/test/grammar/common/token-expectation.ts b/test/grammar/common/token-expectation.ts deleted file mode 100644 index 766f69a..0000000 --- a/test/grammar/common/token-expectation.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { type AdblockTokenizer } from './get-adblock-tokenizer'; -import { isArraysEqual } from './utils'; - -/** - * Represents a token that is expected to be found in the source code. - */ -export interface ExpectedToken { - fragment: string; - scopes: string[]; -} - -/** - * Checks if the source code is tokenized as expected. This function - * gives a very convenient way to check if the tokenizer is working as - * expected and using it is enough in most cases. - * - * BEWARE: You should specify the whole source code as fragments, not - * just the parts that you want to check. If you don't specify the whole - * source code, then this function will throw an error because the - * fragments don't match the source code. - * - * It will automatically calculates the location of each token - * based on the fragments. If the location of a token doesn't match - * the expected location, then this function will throw an error. - * - * @param tokenize Tokenizer function. - * @param source Source code to tokenize. - * @param expectedTokens Expected tokens. - * - * @throws If the merged fragments don't match the source code. - * @throws If the number of tokens doesn't match the number of expected tokens. - * @throws If the location of a token doesn't match the expected location. - * @throws If the scopes of a token don't match the expected scopes. - * @throws If the fragment of a token doesn't match the expected fragment. - */ -export function expectTokens(tokenize: AdblockTokenizer, source: string, expectedTokens: ExpectedToken[]): void { - // Merging fragments should give us the original source - const mergedFragments = expectedTokens.map((token) => token.fragment).join(''); - - if (mergedFragments !== source) { - throw new Error('The merged fragments do not match the source, so the expectation is invalid'); - } - - // Tokenize the source - const tokens = tokenize(source); - - // Check that the number of tokens matches the number of expected tokens - if (tokens.length !== expectedTokens.length) { - throw new Error(`Expected ${expectedTokens.length} tokens, but got ${tokens.length}`); - } - - let offset = 0; - - // Check that each token matches the expected token - for (let i = 0; i < tokens.length; i += 1) { - const endOffset = offset + expectedTokens[i].fragment.length; - - // Check location - if (tokens[i].startIndex !== offset) { - throw new Error( - // eslint-disable-next-line max-len - `Expected token ${i} to start at offset ${offset}, but it starts at offset ${tokens[i].startIndex}`, - ); - } - - if (tokens[i].endIndex !== endOffset) { - throw new Error( - // eslint-disable-next-line max-len - `Expected token ${i} to end at offset ${endOffset}, but it ends at offset ${tokens[i].endIndex}`, - ); - } - - if (!isArraysEqual(tokens[i].scopes, expectedTokens[i].scopes)) { - throw new Error( - // eslint-disable-next-line max-len - `Expected token ${i} to have scopes [${expectedTokens[i].scopes.join(', ')}], but got [${tokens[i].scopes.join(', ')}]`, - ); - } - - // Update the offset - offset = endOffset; - } -} diff --git a/test/static/aglint/.aglintignore b/test/static/aglint/.aglintignore index 447901d..d628299 100644 --- a/test/static/aglint/.aglintignore +++ b/test/static/aglint/.aglintignore @@ -1,2 +1,2 @@ -list2.txt -/ignored-folder +list2.txt +/ignored-folder diff --git a/test/static/aglint/.aglintrc.yml b/test/static/aglint/.aglintrc.yml index a595d2b..01e9bf0 100644 --- a/test/static/aglint/.aglintrc.yml +++ b/test/static/aglint/.aglintrc.yml @@ -1,11 +1,12 @@ -root: true -syntax: ['AdGuard'] -extends: - - aglint:recommended -rules: - max-css-selectors: [warn, { maxSelectors: 1 }] - no-excluded-rules: - - error - - excludedRegExpPatterns: - # Do not forget to escape special regex characters - - example\.com\/bad\/query\/ +root: true +platforms: + - adg_any +extends: + - aglint:recommended +rules: + max-css-selectors: [warn, { maxSelectors: 1 }] + no-excluded-rules: + - error + - excludedRegExpPatterns: + # Do not forget to escape special regex characters + - example\.com\/bad\/query\/ diff --git a/test/static/aglint/custom-config-1/.aglintrc.yml b/test/static/aglint/custom-config-1/.aglintrc.yml index 055bd2c..0d67c06 100644 --- a/test/static/aglint/custom-config-1/.aglintrc.yml +++ b/test/static/aglint/custom-config-1/.aglintrc.yml @@ -1,3 +1,3 @@ -rules: - # Disable linter rule - max-css-selectors: off \ No newline at end of file +rules: + # Disable linter rule + max-css-selectors: off diff --git a/test/static/aglint/custom-config-1/list4.txt b/test/static/aglint/custom-config-1/list4.txt index 46accee..ff64c7c 100644 --- a/test/static/aglint/custom-config-1/list4.txt +++ b/test/static/aglint/custom-config-1/list4.txt @@ -1,4 +1,4 @@ -! By default, AGLint warns about multiple selectors in a single rule, -! but in this folder we disabled this rule in the config file, so -! it should not warn about it. -example.com##.ad1, .ad2 +! By default, AGLint warns about multiple selectors in a single rule, +! but in this folder we disabled this rule in the config file, so +! it should not warn about it. +example.com##.ad1, .ad2 diff --git a/test/static/aglint/custom-config-2/.aglintrc.yml b/test/static/aglint/custom-config-2/.aglintrc.yml index 6a78750..1e083a9 100644 --- a/test/static/aglint/custom-config-2/.aglintrc.yml +++ b/test/static/aglint/custom-config-2/.aglintrc.yml @@ -1,3 +1,3 @@ -rules: - # Change linter rule severity - max-css-selectors: [error, { maxSelectors: 1 }] \ No newline at end of file +rules: + # Change linter rule severity + max-css-selectors: [error, { maxSelectors: 1 }] diff --git a/test/static/aglint/custom-config-2/list5.txt b/test/static/aglint/custom-config-2/list5.txt index 2e6fa36..b90987a 100644 --- a/test/static/aglint/custom-config-2/list5.txt +++ b/test/static/aglint/custom-config-2/list5.txt @@ -1,4 +1,4 @@ -! By default, AGLint warns about multiple selectors in a single rule, -! but in this folder we modified the rule severity to error, so -! it should be reported as an error. -example.com##.ad1, .ad2 +! By default, AGLint warns about multiple selectors in a single rule, +! but in this folder we modified the rule severity to error, so +! it should be reported as an error. +example.com##.ad1, .ad2 diff --git a/test/static/aglint/demo.txt b/test/static/aglint/demo.txt index a30dbac..d5df231 100644 --- a/test/static/aglint/demo.txt +++ b/test/static/aglint/demo.txt @@ -1,32 +1,32 @@ -! By default, AGLint should show a warning for multiple selectors in a single rule -example.com##.ad1, .ad2 - -! But not if the rule is disabled: - -! aglint-disable-next-line max-css-selectors -example.com##.ad1, .ad2 - -! Syntax error: -example.com#%#//scriptlet("aaa", - -! Unsupported CSS pseudo-class -##:hsa-text() - -! Invalid modifier -||example.com^$specifichide -||example.com^$referrerpolicy=~origin - -! Excluded rule -example.com/bad/query/ - -! Duplicated CSS property -#$#div { color: red; color: red; } - -! Same property with different values -#$#div { color: red; color: blue; } - -! Invalid declaration -#$#div { display: foo; } - -! Invalid declaration -##div:style(display: foo; color: bar; color: bar;) +! By default, AGLint should show a warning for multiple selectors in a single rule +example.com##.ad1, .ad2 + +! But not if the rule is disabled: + +! aglint-disable-next-line max-css-selectors +example.com##.ad1, .ad2 + +! Syntax error: +example.com#%#//scriptlet("aaa", + +! Unsupported CSS pseudo-class +##:hsa-text() + +! Invalid modifier +||example.com^$specifichide +||example.com^$referrerpolicy=~origin + +! Excluded rule +example.com/bad/query/ + +! Duplicated CSS property +#$#div { color: red; color: red; } + +! Same property with different values +#$#div { color: red; color: blue; } + +! Invalid declaration +#$#div { display: foo; } + +! Invalid declaration +##div:style(display: foo; color: bar; color: bar;) diff --git a/test/static/aglint/ignored-folder/list6.txt b/test/static/aglint/ignored-folder/list6.txt index 65170d9..40667a1 100644 --- a/test/static/aglint/ignored-folder/list6.txt +++ b/test/static/aglint/ignored-folder/list6.txt @@ -1,2 +1,2 @@ -! Should ignore this rule, because the whole folder is ignored -example.com##+js( +! Should ignore this rule, because the whole folder is ignored +example.com##+js( diff --git a/test/static/aglint/ignored-folder/list7.txt b/test/static/aglint/ignored-folder/list7.txt index 016de6c..dd85c7e 100644 --- a/test/static/aglint/ignored-folder/list7.txt +++ b/test/static/aglint/ignored-folder/list7.txt @@ -1,2 +1,2 @@ -! Should ignore this rule, because the whole folder is ignored -example.com#%#//scriptlet("aaa +! Should ignore this rule, because the whole folder is ignored +example.com#%#//scriptlet("aaa diff --git a/test/static/aglint/list1.txt b/test/static/aglint/list1.txt index c9462ef..867fa60 100644 --- a/test/static/aglint/list1.txt +++ b/test/static/aglint/list1.txt @@ -1,15 +1,15 @@ -! Every rule is valid in this file - -example.com##.ad -example.com##section + div -||example.org^$third-party -||example.net^$third-party,domain=example.com -/ad-*.js$domain=example.com - -!#if (adguard_app_mac || adguard_app_windows || adguard_app_android) -example.com##.ad1 -||example.com^$referrerpolicy=same-origin -||example.org^$permissions=autoplay=() -!#else -example.com##.ad2 -!#endif +! Every rule is valid in this file + +example.com##.ad +example.com##section + div +||example.org^$third-party +||example.net^$third-party,domain=example.com +/ad-*.js$domain=example.com + +!#if (adguard_app_mac || adguard_app_windows || adguard_app_android) +example.com##.ad1 +||example.com^$referrerpolicy=same-origin +||example.org^$permissions=autoplay=() +!#else +example.com##.ad2 +!#endif diff --git a/test/static/aglint/list2.txt b/test/static/aglint/list2.txt index cf8fb55..3686d7c 100644 --- a/test/static/aglint/list2.txt +++ b/test/static/aglint/list2.txt @@ -1,3 +1,3 @@ -! This error should be ignored, because the file -! is listed in the .aglintignore file. -example.com###.wrong-selector +! This error should be ignored, because the file +! is listed in the .aglintignore file. +example.com###.wrong-selector diff --git a/test/static/aglint/list3.txt b/test/static/aglint/list3.txt index 52ee086..9083fb7 100644 --- a/test/static/aglint/list3.txt +++ b/test/static/aglint/list3.txt @@ -1,33 +1,33 @@ -! By default, AGLint should show a warning for multiple selectors in a single rule -example.com##.ad1, .ad2 - -! But not if the rule is disabled: - -! aglint-disable-next-line max-css-selectors -example.com##.ad1, .ad2 - -! Syntax error: -example.com###.a -example.com#%#//scriptlet("aaa", - -! Test disabling and enabling - -! aglint-disable -! This rule should not be reported -example.com##... -! aglint-enable -! This rule should be reported -example.com##... - -! invalid modifier -||example.com^$specifichide -||example.com^$referrerpolicy=~origin - -! excluded rule -example.com/bad/query/ - -! Invalid declaration -#$#div { display: foo; color: bar; } - -! Duplicated declaration -#$#div { display: none; display: none; } +! By default, AGLint should show a warning for multiple selectors in a single rule +example.com##.ad1, .ad2 + +! But not if the rule is disabled: + +! aglint-disable-next-line max-css-selectors +example.com##.ad1, .ad2 + +! Syntax error: +example.com###.a +example.com#%#//scriptlet("aaa", + +! Test disabling and enabling + +! aglint-disable +! This rule should not be reported +example.com##... +! aglint-enable +! This rule should be reported +example.com##... + +! invalid modifier +||example.com^$specifichide +||example.com^$referrerpolicy=~origin + +! excluded rule +example.com/bad/query/ + +! Invalid declaration +#$#div { display: foo; color: bar; } + +! Duplicated declaration +#$#div { display: none; display: none; } diff --git a/test/static/aglint/package.json b/test/static/aglint/package.json index 08b2620..30e7429 100644 --- a/test/static/aglint/package.json +++ b/test/static/aglint/package.json @@ -1,5 +1,9 @@ { "name": "aglint-test-project", + "private": true, + "scripts": { + "tsc": "echo 'Test fixture - no TypeScript files to compile'" + }, "dependencies": { "@adguard/aglint": "catalog:" } diff --git a/test/static/multi-root-workspace/project-1/.aglintrc.yml b/test/static/multi-root-workspace/project-1/.aglintrc.yml index ff87c3a..8dc36f7 100644 --- a/test/static/multi-root-workspace/project-1/.aglintrc.yml +++ b/test/static/multi-root-workspace/project-1/.aglintrc.yml @@ -1,3 +1,3 @@ -root: true -extends: - - aglint:recommended +root: true +extends: + - aglint:recommended diff --git a/test/static/multi-root-workspace/project-2/.aglintrc.yml b/test/static/multi-root-workspace/project-2/.aglintrc.yml index ff87c3a..8dc36f7 100644 --- a/test/static/multi-root-workspace/project-2/.aglintrc.yml +++ b/test/static/multi-root-workspace/project-2/.aglintrc.yml @@ -1,3 +1,3 @@ -root: true -extends: - - aglint:recommended +root: true +extends: + - aglint:recommended diff --git a/tools/.eslintrc.cjs b/tools/.eslintrc.cjs new file mode 100644 index 0000000..fb10704 --- /dev/null +++ b/tools/.eslintrc.cjs @@ -0,0 +1,9 @@ +const path = require('node:path'); + +module.exports = { + extends: '../.eslintrc.cjs', + parserOptions: { + tsconfigRootDir: path.join(__dirname), + project: 'tsconfig.json', + }, +}; diff --git a/tools/changelog-extractor.ts b/tools/changelog-extractor.ts deleted file mode 100644 index 463c83f..0000000 --- a/tools/changelog-extractor.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @file Changelog extractor. - * - * @see {@link https://keepachangelog.com/en/1.1.0/ | Keep a Changelog} - * - * @note Run with: node -r esbuild-register tools/changelog-extractor.ts - */ - -import { readFile, writeFile } from 'node:fs/promises'; -import path from 'node:path'; - -import { Command } from 'commander'; -import escapeStringRegexp from 'escape-string-regexp'; -import { ensureDir } from 'fs-extra'; -import remarkInlineLinks from 'remark-inline-links'; -import remarkParse from 'remark-parse'; -import { type Root } from 'remark-parse/lib'; -import remarkStringify, { type Options as StringifyOptions } from 'remark-stringify'; -import { unified } from 'unified'; - -const EMPTY = ''; -const HYPHEN = '-'; - -const UPPER_LEVEL = '../'; -const OUT_FOLDER = 'out'; - -const INPUT_FILE = 'CHANGELOG.md'; -const OUTPUT_FILE = 'TEMP_CHANGES.md'; - -// TODO: Read project data from package.json, e.g. project name and make them available via variables, like {name} -const inputFilePath = path.join(__dirname, UPPER_LEVEL, INPUT_FILE); -const outputFolderPath = path.join(__dirname, UPPER_LEVEL, OUT_FOLDER); -const outputFilePath = path.join(outputFolderPath, OUTPUT_FILE); - -/** - * Options for the remark-stringify plugin. - */ -const serializationOptions: StringifyOptions = { - bullet: HYPHEN, -}; - -/** - * Options for the extractRelease transformer. - */ -interface ExtractOptions { - /** - * Fallback text if the version number is not found in the changelog. - */ - fallback?: string; -} - -/** - * A simple helper function that parses the markdown document into an AST. - * - * @param md Markdown document as string. - * - * @returns Root node of the parsed markdown document (AST). - */ -const parseMd = (md: string): Root => { - return unified() // create a new processor - .use(remarkParse) // parse the markdown document - .use(remarkInlineLinks) // convert [text][link-definition] cases to [text](link) where possible - .parse(md); // parse the fallback text to a node -}; - -/** - * Extracts the release from the markdown document. - * - * @param version Version number what we are looking for, e.g. 1.0.0. - * @param options Extract options. - * - * @returns Transformer function. - */ -const extractRelease = (version: string, options: ExtractOptions = {}) => { - return (tree: Root) => { - // Transformer function should return a Root node that passes to the next transformer in the chain (if any) - const root: Root = { - type: 'root', - children: [], - }; - - // Prepare nodes - const fallback = parseMd(options.fallback || EMPTY); // always present, at least as an empty string - - // String should start with the version number, and should be followed by a space or the end of the string. - // For example: - // - ## 1.0.0 - // - ## 1.0.0 (2020-01-01) - // - ## 1.0.0 - 2020-01-01 - // - ## [1.0.0](link) - // - etc. - // TODO: Improve this regexp, if needed - const VERSION_RE = new RegExp(`^${escapeStringRegexp(version)}(\\s|$)`); - - // It is enough to traverse the first level of the tree - for (let i = 0; i < tree.children.length; i += 1) { - const node = tree.children[i]; - - // Find the first 2. level heading which includes the version number what we are looking for - // like: ## 1.0.0 - if (node.type === 'heading' && node.depth === 2) { - if ( - // ## 1.0.0 - (node.children[0]?.type === 'text' && node.children[0]?.value?.match(VERSION_RE)) - // ## [1.0.0](link) - || ( - node.children[0]?.type === 'link' - && node.children[0]?.children[0]?.type === 'text' - && node.children[0]?.children[0]?.value?.match(VERSION_RE) - ) - ) { - // Find the next 2. level heading or the end of the document, and add all nodes between them to the - // root node - for (let j = i + 1; j < tree.children.length; j += 1) { - const nextNode = tree.children[j]; - - if (nextNode.type === 'heading' && nextNode.depth === 2) { - break; - } - - root.children.push(nextNode); - } - } - } - } - - // If the root node has no children, return the fallback node - return root.children.length > 0 ? root : fallback; - }; -}; - -const options = new Command() - .requiredOption('-e, --extract ', 'Version number what we want to extract') - .option( - '-f, --fallback ', - 'Fallback text if the version number is not found', - 'See [CHANGELOG.md](./CHANGELOG.md) for the list of changes.', - ) - .parse(process.argv) - .opts(); - -const main = async () => { - const output = await unified() // create a new processor - .use(remarkParse) // parse the markdown document - .use(remarkInlineLinks) // convert [text][link-definition] cases to [text](link) where possible - .use(extractRelease, options.extract, options) // extract & transform the release text, if any - .use(remarkStringify, serializationOptions) // serialize the node to markdown - .process(await readFile(inputFilePath)); // process the input file - - // Create the output folder, if not exists - await ensureDir(outputFolderPath); - - await writeFile(outputFilePath, output.toString()); -}; - -main(); diff --git a/tools/grammar-builder.ts b/tools/grammar-builder.ts deleted file mode 100644 index 4f849aa..0000000 --- a/tools/grammar-builder.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file This is a very simple script that builds the grammar file to PList. - */ - -import { join } from 'node:path'; - -import { - exists, - mkdir, - readFile, - writeFile, -} from 'fs-extra'; -import { YAMLParseError } from 'yaml'; - -import { convertYamlToPlist } from './grammar-converter'; -import { getErrorMessage } from './utils/error'; - -const SOURCE_GRAMMAR_FILE = 'adblock.yaml-tmlanguage'; -const DEST_GRAMMAR_FILE = 'adblock.plist'; - -const SYNTAXES_FOLDER = join(__dirname, '..', 'syntaxes'); -const OUT_FOLDER = join(SYNTAXES_FOLDER, 'out'); - -/** - * Creates the out folder if it doesn't exist. - */ -async function createOutFolder() { - // If the dist folder doesn't exist, create it - if (!(await exists(OUT_FOLDER))) { - await mkdir(OUT_FOLDER); - } -} - -/** - * Builds the source grammar file into a PList representation. - * - * @throws If the source grammar file doesn't exist. - * @throws If the source grammar file is not a valid YAML file. - * @throws If cannot write the PList representation to the dist folder. - */ -async function buildGrammar() { - // Read the raw YAML content from the grammar file - const rawYaml = await readFile(join(SYNTAXES_FOLDER, SOURCE_GRAMMAR_FILE), 'utf8'); - - // Convert the YAML content into a PList representation - const plistGrammar = convertYamlToPlist(rawYaml); - - // Write the PList representation to the dist folder - await writeFile(join(OUT_FOLDER, DEST_GRAMMAR_FILE), plistGrammar); -} - -/** - * Main function that runs the script. - */ -async function main() { - // eslint-disable-next-line no-console - console.log('[grammar] build started'); - - try { - await createOutFolder(); - await buildGrammar(); - - // eslint-disable-next-line no-console - console.log(`Grammar file written to ${join(OUT_FOLDER, DEST_GRAMMAR_FILE)}`); - } catch (error: unknown) { - // https://eemeli.org/yaml/#errors - if (error instanceof YAMLParseError) { - const severity = error.name === 'YAMLParseError' ? 'error' : 'warn'; - const { line, col } = error.linePos![0]; - - // eslint-disable-next-line no-console - console.error(`[${severity}] ${SOURCE_GRAMMAR_FILE}:${line}:${col}: ${error.message}`); - } else { - // eslint-disable-next-line no-console - console.error(`[error] ${getErrorMessage(error)}`); - } - } - - // eslint-disable-next-line no-console - console.log('[grammar] build finished'); -} - -main(); diff --git a/tools/package.json b/tools/package.json new file mode 100644 index 0000000..e37719e --- /dev/null +++ b/tools/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vscode-adblock-syntax/tools", + "version": "1.0.0", + "private": true, + "description": "Build and utility scripts for vscode-adblock-syntax" +} diff --git a/tools/tsconfig.json b/tools/tsconfig.json new file mode 100644 index 0000000..6febbd2 --- /dev/null +++ b/tools/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "target": "ES2020", + "lib": ["ES2020"], + "outDir": "../out/tools", + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": true + }, + "include": ["*.ts", ".eslintrc.cjs"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..caf62c7 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "types": ["node"], + "resolveJsonModule": true, + "allowJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "isolatedModules": true, + "rootDir": "./" + } +} diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json deleted file mode 100644 index af718fd..0000000 --- a/tsconfig.eslint.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": [ - ".eslintrc.cjs", - "client/**/*.ts", - "jest.config.ts", - "server/**/*.ts", - "test/**/*.ts", - "tools/**/*.ts", - "tools/**/*.mjs", - "server/.eslintrc.cjs" - ] -} diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index ff265fb..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "module": "CommonJS", - "target": "es2020", - "lib": ["es2020"], - "outDir": "out", - "rootDir": "src", - "sourceMap": true, - "baseUrl": ".", - "esModuleInterop": true, - "skipLibCheck": true - }, - "include": ["src"], - "exclude": ["node_modules", ".vscode-test"], - "references": [ - { - "path": "./client" - }, - { - "path": "./server" - } - ], - "ts-node": { - "swc": true, - "compilerOptions": { - "module": "CommonJS" - } - } -}