├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.js ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── eslint.config.js ├── package.json ├── pnpm-lock.yaml ├── src ├── configs │ ├── index.ts │ └── recommended.ts ├── index.ts └── rules │ ├── __tests__ │ ├── fixtures │ │ ├── file.ts │ │ └── tsconfig.json │ └── utils.ts │ ├── index.ts │ ├── no-object-assign-mutation │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ ├── no-object-assign │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ ├── no-type-assertion │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ ├── no-unsafe-object-enum-method │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ ├── no-unsafe-object-property-check │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ ├── no-unsafe-object-property-overwrite │ ├── README.md │ ├── index.spec.ts │ └── index.ts │ └── utils.ts ├── tsconfig.build.json ├── tsconfig.json └── vitest.config.js /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | pull_request: 5 | release: 6 | types: 7 | - created 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: 14 | - '20' 15 | - '22' 16 | - '24' 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: pnpm/action-setup@v4 20 | with: 21 | version: 10 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | cache: 'pnpm' 26 | - run: pnpm install 27 | - run: pnpm format:check 28 | - run: pnpm lint:check 29 | - run: pnpm typecheck 30 | - run: pnpm test 31 | - run: pnpm build 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /lib 2 | 3 | ### https://raw.github.com/github/gitignore/ce5da10a3a43c4dd8bd9572eda17c0a37ee0eac1/Node.gitignore 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | .pnpm-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variable files 80 | .env 81 | .env.development.local 82 | .env.test.local 83 | .env.production.local 84 | .env.local 85 | 86 | # parcel-bundler cache (https://parceljs.org/) 87 | .cache 88 | .parcel-cache 89 | 90 | # Next.js build output 91 | .next 92 | out 93 | 94 | # Nuxt.js build / generate output 95 | .nuxt 96 | dist 97 | 98 | # Gatsby files 99 | .cache/ 100 | # Comment in the public line in if your project uses Gatsby and not Next.js 101 | # https://nextjs.org/blog/next-9-1#public-directory-support 102 | # public 103 | 104 | # vuepress build output 105 | .vuepress/dist 106 | 107 | # vuepress v2.x temp and cache directory 108 | .temp 109 | .cache 110 | 111 | # Docusaurus cache and generated files 112 | .docusaurus 113 | 114 | # Serverless directories 115 | .serverless/ 116 | 117 | # FuseBox cache 118 | .fusebox/ 119 | 120 | # DynamoDB Local files 121 | .dynamodb/ 122 | 123 | # TernJS port file 124 | .tern-port 125 | 126 | # Stores VSCode versions used for testing VSCode extensions 127 | .vscode-test 128 | 129 | # yarn v2 130 | .yarn/cache 131 | .yarn/unplugged 132 | .yarn/build-state.yml 133 | .yarn/install-state.gz 134 | .pnp.* 135 | 136 | 137 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.json 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: false, 7 | quoteProps: "as-needed", 8 | jsxSingleQuote: false, 9 | trailingComma: "all", 10 | bracketSpacing: true, 11 | bracketSameLine: false, 12 | objectWrap: "preserve", 13 | arrowParens: "always", 14 | endOfLine: "lf", 15 | experimentalTernaries: true, 16 | experimentalOperatorPosition: "start", 17 | }; 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.10.0 (2025-06-07) 2 | 3 | - Upgrade dependencies 4 | - Add suggestion fixer for `no-unsafe-object-property-overwrite` 5 | - Add `no-object-assign-mutation` rule, which replaces `no-object-assign` 6 | - Deprecate `no-object-assign` rule 7 | - Use `no-object-assign-mutation` and [`prefer-object-spread`](https://eslint.org/docs/latest/rules/prefer-object-spread) instead 8 | - **BREAKING** The package is now Pure ESM 9 | - **BREAKING** Update recommended config 10 | - Replace `no-object-assign` with `no-object-assign-mutation` 11 | - **BREAKING** Remove [`eslint-define-config`](https://github.com/eslint-types/eslint-define-config) support 12 | 13 | ## 0.9.4 (2025-04-29) 14 | 15 | - Upgrade dependencies 16 | 17 | ## 0.9.3 (2025-02-09) 18 | 19 | - Upgrade dependencies 20 | 21 | ## 0.9.2 (2024-11-23) 22 | 23 | - Upgrade dependencies 24 | 25 | ## 0.9.1 (2024-10-26) 26 | 27 | - Upgrade dependencies 28 | - Add name for the recommended config 29 | - Fix ordering in the `exports` field of `package.json` 30 | 31 | ## 0.9.0 (2024-08-04) 32 | 33 | - **BREAKING** The minimum supported version of typescript-eslint is now `8.0.0` 34 | - Upgrade typescript-eslint to v8 35 | 36 | ## 0.8.3 (2024-07-08) 37 | 38 | - Upgrade dependencies 39 | 40 | ## 0.8.2 (2024-06-20) 41 | 42 | - Fix CJS interop issue 43 | 44 | ## 0.8.1 (2024-06-19) 45 | 46 | - `no-unsafe-object-property-overwrite`: Fix false positive for conditionals 47 | - Upgrade dependencies 48 | 49 | ## 0.8.0 (2024-03-16) 50 | 51 | - Upgrade typescript-eslint to 7.2.x to support TypeScript 5.4 52 | - Change how the plugin and its type are exported to improve compatibility with `@types/eslint` 53 | - Shortly, the plugin type is now compatible with `ESLint.Plugin` 54 | - Move [`eslint-define-config`](https://github.com/eslint-types/eslint-define-config) support to a submodule `@susisu/eslint-plugin-safe-typescript/define-config-support` 55 | 56 | ## 0.7.0 (2024-02-15) 57 | 58 | - Upgrade typescript-eslint to v7 59 | - `no-type-assertion`: Add support for angle bracket style type assertions like `x` 60 | 61 | ## 0.6.1 (2024-02-11) 62 | 63 | - Refactor how the module augmentation for eslint-define-config is exported 64 | 65 | ## 0.6.0 (2024-02-11) 66 | 67 | - Provide rule option types for [`eslint-define-config`](https://github.com/eslint-types/eslint-define-config) 68 | 69 | ## 0.5.3 (2024-02-10) 70 | 71 | - Upgrade dependencies 72 | - Add docs for flat config 73 | 74 | ## 0.5.2 (2023-12-16) 75 | 76 | - Add default export for ESM 77 | 78 | ## 0.5.1 (2023-12-03) 79 | 80 | - Fix `types` were missing in the `exports` field 81 | 82 | ## 0.5.0 (2023-12-03) 83 | 84 | - **BREAKING** Drop support for Node.js 16 85 | - Type declarations are now included again 86 | - It would never be used in the previous config format (`.eslintrc`), but will be useful in the new flat config format. 87 | - The package is now ESM/CJS dual 88 | - Upgrade dependencies 89 | 90 | ## 0.4.1 (2023-07-16) 91 | 92 | - Fix peerDependencies was not updated 93 | 94 | ## 0.4.0 (2023-07-16) 95 | 96 | - Upgrade typescript to 5.1 97 | - **BREAKING** Upgrade typescript-eslint to 6.0 98 | - **BREAKING** Type declarations are no longer included in the distribution 99 | 100 | ## 0.3.5 (2023-03-17) 101 | 102 | - Upgrade dependencies 103 | - Upgrade TypeScript to 5.0 104 | 105 | ## 0.3.4 (2022-12-04) 106 | 107 | - Upgrade TypeScript to 4.9 108 | 109 | ## 0.3.3 (2022-10-02) 110 | 111 | - Upgrade dependencies 112 | - Update message of `no-type-assertion` 113 | 114 | ## 0.3.2 (2022-09-02) 115 | 116 | - Upgrade dependencies 117 | 118 | ## 0.3.1 (2022-08-11) 119 | 120 | - Upgrade dependencies 121 | 122 | ## 0.3.0 (2022-07-13) 123 | 124 | - Add `no-type-assertion` rule 125 | - **BREAKING** Add `no-type-assertion` rule to the recommended config 126 | 127 | ## 0.2.2 (2022-05-06) 128 | 129 | - Upgrade dependencies 130 | 131 | ## 0.2.1 (2022-03-21) 132 | 133 | - Fix `no-object-assign` was not exported 134 | 135 | ## 0.2.0 (2022-03-21) 136 | 137 | - Add `allowIndexSignatures` option to `no-unsafe-object-property-overwrite` rule 138 | - Add `no-object-assign` rule 139 | - **BREAKING** Add `no-object-assign` rule to the recommended config 140 | 141 | ## 0.1.0 (2022-03-06) 142 | 143 | - First release 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (http://opensource.org/licenses/mit-license.php) 2 | 3 | Copyright (c) 2022-2025 Susisu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @susisu/eslint-plugin-safe-typescript 2 | 3 | [![CI](https://github.com/susisu/eslint-plugin-safe-typescript/workflows/CI/badge.svg)](https://github.com/susisu/eslint-plugin-safe-typescript/actions?query=workflow%3ACI) 4 | 5 | An [ESLint](https://eslint.org) plugin that makes your TypeScript code safer 6 | 7 | ## Installation 8 | 9 | This plugin requires [TypeScript](https://www.typescriptlang.org/) and [typescript-eslint](https://typescript-eslint.io/). 10 | If you haven't installed them in your project, follow the guide on typescript-eslint's [Getting Started](https://typescript-eslint.io/getting-started) page. 11 | 12 | Once you're ready, install this plugin: 13 | 14 | ``` shell 15 | # npm 16 | npm i --save-dev @susisu/eslint-plugin-safe-typescript 17 | # yarn 18 | yarn add -D @susisu/eslint-plugin-safe-typescript 19 | # pnpm 20 | pnpm add -D @susisu/eslint-plugin-safe-typescript 21 | ``` 22 | 23 | ## Configuration 24 | 25 | 1. Enable typescript-eslint parser 26 | 2. Add `@susisu/eslint-plugin-safe-typescript` to plugins 27 | 3. (Optional) Add `parserOptions.project` if you enable rules that use type information. 28 | 29 | `eslint.config.js`: 30 | 31 | ``` js 32 | import tsEslint from "typescript-eslint"; 33 | import safeTsPlugin from "@susisu/eslint-plugin-safe-typescript"; 34 | 35 | export default [ 36 | { 37 | languageOptions: { 38 | parser: tsEslint.parser, // (1) 39 | parserOptions: { 40 | project: true, // (3) 41 | }, 42 | }, 43 | plugins: { 44 | "@susisu/safe-typescript": safeTsPlugin, // (2) 45 | }, 46 | rules: { 47 | "@susisu/safe-typescript/no-object-assign": "error", 48 | }, 49 | }, 50 | ]; 51 | ``` 52 | 53 | `.eslintrc`: 54 | 55 | ``` json 56 | { 57 | "parser": "@typescript-eslint/parser", // (1) 58 | "parserOptions": { 59 | "project": true // (3) 60 | }, 61 | "plugins": ["@susisu/safe-typescript"], // (2) 62 | "rules": { 63 | "@susisu/safe-typescript/no-object-assign": "error" 64 | } 65 | } 66 | ``` 67 | 68 | ## Recommended configuration 69 | 70 | This plugin also provides a configuration set for the recommended rules (see [Rules](#rules) for which rules are recommended). 71 | 72 | Since some rules in the recommended configuration require type information, `parserOptions.project` must be set in your config. 73 | 74 | `eslint.config.js` 75 | 76 | ``` js 77 | export default [ 78 | safeTsPlugin.configs.recommended, 79 | // or extend in `rules` 80 | // { 81 | // rules: { 82 | // ...safeTsPlugin.configs.recommended.rules, 83 | // }, 84 | // }, 85 | ]; 86 | ``` 87 | 88 | `eslintrc` 89 | 90 | ``` json 91 | { 92 | "extends": ["plugin:@susisu/safe-typescript/recommended"] 93 | } 94 | ``` 95 | 96 | ## Rules 97 | 98 | ✅ = recommended, 🔧 = fixable, 💡 = has suggestions, 💭 = requires type information 99 | 100 | | Name | Description | ✅ | 🔧 | 💭 | 101 | | --- | --- | --- | --- | --- | 102 | | [`no-object-assign-mutation`](https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/no-object-assign-mutation/README.md) | Disallow mutations using `Object.assign()`. | ✅ | | | 103 | | [`no-type-assertion`](https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/no-type-assertion/README.md) | Disallow type assertions like `x as T`. | ✅ | | | 104 | | [`no-unsafe-object-enum-method`](https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/no-unsafe-object-enum-method/README.md) | Disallow possibly unsafe property enumeration methods of `Object`. | ✅ | | 💭 | 105 | | [`no-unsafe-object-property-check`](https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/no-unsafe-object-property-check/README.md) | Disallow possibly unsafe property checks of object. | ✅ | | 💭 | 106 | | [`no-unsafe-object-property-overwrite`](https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/no-unsafe-object-property-overwrite/README.md) | Disallow possibly unsafe overwrites of object properties. | ✅ | 💡 | 💭 | 107 | 108 | ## Contributing 109 | 110 | Issues and PRs are welcome! 111 | Feel free to open issues if you have any problems or ideas. 112 | 113 | ## License 114 | 115 | [MIT License](http://opensource.org/licenses/mit-license.php) 116 | 117 | ## Author 118 | 119 | Susisu ([GitHub](https://github.com/susisu), [Twitter](https://twitter.com/susisu2413)) 120 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { config } from "@susisu/eslint-config"; 2 | import eslintPluginPlugin from "eslint-plugin-eslint-plugin"; 3 | import vitestPlugin from "@vitest/eslint-plugin"; 4 | import globals from "globals"; 5 | 6 | export default config( 7 | { 8 | tsconfigRootDir: import.meta.dirname, 9 | }, 10 | { 11 | plugins: { 12 | "eslint-plugin": eslintPluginPlugin, 13 | vitest: vitestPlugin, 14 | }, 15 | }, 16 | { 17 | files: ["src/**/*.ts"], 18 | languageOptions: { 19 | globals: { 20 | ...globals.es2023, 21 | ...globals.node, 22 | }, 23 | }, 24 | rules: { 25 | ...eslintPluginPlugin.configs.recommended.rules, 26 | }, 27 | }, 28 | { 29 | files: ["src/**/*.spec.ts", "src/**/__tests__/**/*.ts"], 30 | languageOptions: { 31 | globals: { 32 | ...vitestPlugin.environments.env.globals, 33 | }, 34 | }, 35 | rules: { 36 | ...vitestPlugin.configs.recommended.rules, 37 | }, 38 | }, 39 | { 40 | files: ["*.js"], 41 | languageOptions: { 42 | globals: { 43 | ...globals.es2023, 44 | ...globals.node, 45 | }, 46 | }, 47 | }, 48 | ); 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@susisu/eslint-plugin-safe-typescript", 3 | "version": "0.10.0", 4 | "description": "ESLint plugin that makes your TypeScript code safer", 5 | "repository": "https://github.com/susisu/eslint-plugin-safe-typescript.git", 6 | "author": "Susisu ", 7 | "license": "MIT", 8 | "type": "module", 9 | "sideEffects": false, 10 | "files": [ 11 | "lib", 12 | "src", 13 | "!src/**/*.{test,spec}.{ts,tsx}", 14 | "!src/**/__tests__" 15 | ], 16 | "main": "lib/index.js", 17 | "types": "lib/index.d.ts", 18 | "exports": { 19 | ".": { 20 | "import": { 21 | "types": "./lib/index.d.ts", 22 | "default": "./lib/index.js" 23 | } 24 | } 25 | }, 26 | "scripts": { 27 | "format": "prettier --write '*.js' src", 28 | "format:check": "prettier --check '*.js' src", 29 | "lint": "eslint --fix '*.js' src", 30 | "lint:check": "eslint '*.js' src", 31 | "test": "vitest run --coverage", 32 | "test:dev": "vitest dev --coverage.enabled --coverage.reporter=text", 33 | "typecheck": "tsc -p tsconfig.json --noEmit", 34 | "build": "tsc --build tsconfig.build.json", 35 | "clean": "run-s clean:tsc clean:rm", 36 | "clean:tsc": "tsc --build tsconfig.build.json --clean", 37 | "clean:rm": "rimraf lib", 38 | "prepublishOnly": "run-s clean format:check lint:check typecheck test build" 39 | }, 40 | "dependencies": { 41 | "@typescript-eslint/utils": "^8.33.1" 42 | }, 43 | "peerDependencies": { 44 | "@typescript-eslint/parser": "^8.0.0", 45 | "eslint": "^9.10.0", 46 | "typescript": "*", 47 | "typescript-eslint": "^8.0.0" 48 | }, 49 | "peerDependenciesMeta": { 50 | "@typescript-eslint/parser": { 51 | "optional": true 52 | }, 53 | "typescript-eslint": { 54 | "optional": true 55 | } 56 | }, 57 | "devDependencies": { 58 | "@qnighy/dedent": "^0.1.1", 59 | "@susisu/eslint-config": "^0.0.97", 60 | "@types/node": "^22.15.30", 61 | "@typescript-eslint/parser": "^8.33.1", 62 | "@typescript-eslint/rule-tester": "^8.33.1", 63 | "@vitest/coverage-v8": "^3.2.2", 64 | "@vitest/eslint-plugin": "^1.2.1", 65 | "eslint": "^9.28.0", 66 | "eslint-plugin-eslint-plugin": "^6.4.0", 67 | "globals": "^16.2.0", 68 | "npm-run-all2": "^8.0.4", 69 | "prettier": "^3.5.3", 70 | "rimraf": "^6.0.1", 71 | "typescript": "~5.8.3", 72 | "vitest": "^3.2.2" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@typescript-eslint/utils': 12 | specifier: ^8.33.1 13 | version: 8.33.1(eslint@9.28.0)(typescript@5.8.3) 14 | typescript-eslint: 15 | specifier: ^8.0.0 16 | version: 8.33.1(eslint@9.28.0)(typescript@5.8.3) 17 | devDependencies: 18 | '@qnighy/dedent': 19 | specifier: ^0.1.1 20 | version: 0.1.1 21 | '@susisu/eslint-config': 22 | specifier: ^0.0.97 23 | version: 0.0.97(eslint@9.28.0)(typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3))(typescript@5.8.3) 24 | '@types/node': 25 | specifier: ^22.15.30 26 | version: 22.15.30 27 | '@typescript-eslint/parser': 28 | specifier: ^8.33.1 29 | version: 8.33.1(eslint@9.28.0)(typescript@5.8.3) 30 | '@typescript-eslint/rule-tester': 31 | specifier: ^8.33.1 32 | version: 8.33.1(eslint@9.28.0)(typescript@5.8.3) 33 | '@vitest/coverage-v8': 34 | specifier: ^3.2.2 35 | version: 3.2.2(vitest@3.2.2(@types/node@22.15.30)(yaml@2.5.1)) 36 | '@vitest/eslint-plugin': 37 | specifier: ^1.2.1 38 | version: 1.2.1(eslint@9.28.0)(typescript@5.8.3)(vitest@3.2.2(@types/node@22.15.30)(yaml@2.5.1)) 39 | eslint: 40 | specifier: ^9.28.0 41 | version: 9.28.0 42 | eslint-plugin-eslint-plugin: 43 | specifier: ^6.4.0 44 | version: 6.4.0(eslint@9.28.0) 45 | globals: 46 | specifier: ^16.2.0 47 | version: 16.2.0 48 | npm-run-all2: 49 | specifier: ^8.0.4 50 | version: 8.0.4 51 | prettier: 52 | specifier: ^3.5.3 53 | version: 3.5.3 54 | rimraf: 55 | specifier: ^6.0.1 56 | version: 6.0.1 57 | typescript: 58 | specifier: ~5.8.3 59 | version: 5.8.3 60 | vitest: 61 | specifier: ^3.2.2 62 | version: 3.2.2(@types/node@22.15.30)(yaml@2.5.1) 63 | 64 | packages: 65 | 66 | '@ampproject/remapping@2.3.0': 67 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 68 | engines: {node: '>=6.0.0'} 69 | 70 | '@babel/helper-string-parser@7.27.1': 71 | resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 72 | engines: {node: '>=6.9.0'} 73 | 74 | '@babel/helper-validator-identifier@7.27.1': 75 | resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 76 | engines: {node: '>=6.9.0'} 77 | 78 | '@babel/parser@7.27.5': 79 | resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} 80 | engines: {node: '>=6.0.0'} 81 | hasBin: true 82 | 83 | '@babel/types@7.27.6': 84 | resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} 85 | engines: {node: '>=6.9.0'} 86 | 87 | '@bcoe/v8-coverage@1.0.2': 88 | resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} 89 | engines: {node: '>=18'} 90 | 91 | '@esbuild/aix-ppc64@0.25.5': 92 | resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} 93 | engines: {node: '>=18'} 94 | cpu: [ppc64] 95 | os: [aix] 96 | 97 | '@esbuild/android-arm64@0.25.5': 98 | resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} 99 | engines: {node: '>=18'} 100 | cpu: [arm64] 101 | os: [android] 102 | 103 | '@esbuild/android-arm@0.25.5': 104 | resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} 105 | engines: {node: '>=18'} 106 | cpu: [arm] 107 | os: [android] 108 | 109 | '@esbuild/android-x64@0.25.5': 110 | resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} 111 | engines: {node: '>=18'} 112 | cpu: [x64] 113 | os: [android] 114 | 115 | '@esbuild/darwin-arm64@0.25.5': 116 | resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} 117 | engines: {node: '>=18'} 118 | cpu: [arm64] 119 | os: [darwin] 120 | 121 | '@esbuild/darwin-x64@0.25.5': 122 | resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} 123 | engines: {node: '>=18'} 124 | cpu: [x64] 125 | os: [darwin] 126 | 127 | '@esbuild/freebsd-arm64@0.25.5': 128 | resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} 129 | engines: {node: '>=18'} 130 | cpu: [arm64] 131 | os: [freebsd] 132 | 133 | '@esbuild/freebsd-x64@0.25.5': 134 | resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} 135 | engines: {node: '>=18'} 136 | cpu: [x64] 137 | os: [freebsd] 138 | 139 | '@esbuild/linux-arm64@0.25.5': 140 | resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} 141 | engines: {node: '>=18'} 142 | cpu: [arm64] 143 | os: [linux] 144 | 145 | '@esbuild/linux-arm@0.25.5': 146 | resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} 147 | engines: {node: '>=18'} 148 | cpu: [arm] 149 | os: [linux] 150 | 151 | '@esbuild/linux-ia32@0.25.5': 152 | resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} 153 | engines: {node: '>=18'} 154 | cpu: [ia32] 155 | os: [linux] 156 | 157 | '@esbuild/linux-loong64@0.25.5': 158 | resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} 159 | engines: {node: '>=18'} 160 | cpu: [loong64] 161 | os: [linux] 162 | 163 | '@esbuild/linux-mips64el@0.25.5': 164 | resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} 165 | engines: {node: '>=18'} 166 | cpu: [mips64el] 167 | os: [linux] 168 | 169 | '@esbuild/linux-ppc64@0.25.5': 170 | resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} 171 | engines: {node: '>=18'} 172 | cpu: [ppc64] 173 | os: [linux] 174 | 175 | '@esbuild/linux-riscv64@0.25.5': 176 | resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} 177 | engines: {node: '>=18'} 178 | cpu: [riscv64] 179 | os: [linux] 180 | 181 | '@esbuild/linux-s390x@0.25.5': 182 | resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} 183 | engines: {node: '>=18'} 184 | cpu: [s390x] 185 | os: [linux] 186 | 187 | '@esbuild/linux-x64@0.25.5': 188 | resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} 189 | engines: {node: '>=18'} 190 | cpu: [x64] 191 | os: [linux] 192 | 193 | '@esbuild/netbsd-arm64@0.25.5': 194 | resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} 195 | engines: {node: '>=18'} 196 | cpu: [arm64] 197 | os: [netbsd] 198 | 199 | '@esbuild/netbsd-x64@0.25.5': 200 | resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} 201 | engines: {node: '>=18'} 202 | cpu: [x64] 203 | os: [netbsd] 204 | 205 | '@esbuild/openbsd-arm64@0.25.5': 206 | resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} 207 | engines: {node: '>=18'} 208 | cpu: [arm64] 209 | os: [openbsd] 210 | 211 | '@esbuild/openbsd-x64@0.25.5': 212 | resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} 213 | engines: {node: '>=18'} 214 | cpu: [x64] 215 | os: [openbsd] 216 | 217 | '@esbuild/sunos-x64@0.25.5': 218 | resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} 219 | engines: {node: '>=18'} 220 | cpu: [x64] 221 | os: [sunos] 222 | 223 | '@esbuild/win32-arm64@0.25.5': 224 | resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} 225 | engines: {node: '>=18'} 226 | cpu: [arm64] 227 | os: [win32] 228 | 229 | '@esbuild/win32-ia32@0.25.5': 230 | resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} 231 | engines: {node: '>=18'} 232 | cpu: [ia32] 233 | os: [win32] 234 | 235 | '@esbuild/win32-x64@0.25.5': 236 | resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} 237 | engines: {node: '>=18'} 238 | cpu: [x64] 239 | os: [win32] 240 | 241 | '@eslint-community/eslint-utils@4.7.0': 242 | resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} 243 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 244 | peerDependencies: 245 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 246 | 247 | '@eslint-community/regexpp@4.12.1': 248 | resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 249 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 250 | 251 | '@eslint/config-array@0.20.0': 252 | resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} 253 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 254 | 255 | '@eslint/config-helpers@0.2.2': 256 | resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} 257 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 258 | 259 | '@eslint/core@0.14.0': 260 | resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} 261 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 262 | 263 | '@eslint/eslintrc@3.3.1': 264 | resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 265 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 266 | 267 | '@eslint/js@9.28.0': 268 | resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} 269 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 270 | 271 | '@eslint/object-schema@2.1.6': 272 | resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 273 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 274 | 275 | '@eslint/plugin-kit@0.3.1': 276 | resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} 277 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 278 | 279 | '@humanfs/core@0.19.1': 280 | resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 281 | engines: {node: '>=18.18.0'} 282 | 283 | '@humanfs/node@0.16.6': 284 | resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} 285 | engines: {node: '>=18.18.0'} 286 | 287 | '@humanwhocodes/module-importer@1.0.1': 288 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 289 | engines: {node: '>=12.22'} 290 | 291 | '@humanwhocodes/retry@0.3.1': 292 | resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 293 | engines: {node: '>=18.18'} 294 | 295 | '@humanwhocodes/retry@0.4.3': 296 | resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} 297 | engines: {node: '>=18.18'} 298 | 299 | '@isaacs/cliui@8.0.2': 300 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 301 | engines: {node: '>=12'} 302 | 303 | '@istanbuljs/schema@0.1.3': 304 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} 305 | engines: {node: '>=8'} 306 | 307 | '@jridgewell/gen-mapping@0.3.8': 308 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 309 | engines: {node: '>=6.0.0'} 310 | 311 | '@jridgewell/resolve-uri@3.1.2': 312 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 313 | engines: {node: '>=6.0.0'} 314 | 315 | '@jridgewell/set-array@1.2.1': 316 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 317 | engines: {node: '>=6.0.0'} 318 | 319 | '@jridgewell/sourcemap-codec@1.5.0': 320 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 321 | 322 | '@jridgewell/trace-mapping@0.3.25': 323 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 324 | 325 | '@nodelib/fs.scandir@2.1.5': 326 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 327 | engines: {node: '>= 8'} 328 | 329 | '@nodelib/fs.stat@2.0.5': 330 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 331 | engines: {node: '>= 8'} 332 | 333 | '@nodelib/fs.walk@1.2.8': 334 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 335 | engines: {node: '>= 8'} 336 | 337 | '@pkgjs/parseargs@0.11.0': 338 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 339 | engines: {node: '>=14'} 340 | 341 | '@qnighy/dedent@0.1.1': 342 | resolution: {integrity: sha512-1TogcOCQlxSL4fS2n3jUtwoTHIlXJN3cw3FmQKSdmVpbVr03gKeXTEskPxqqMT24xkid59bEGv4ZB6oUQqq2fw==} 343 | 344 | '@rollup/rollup-android-arm-eabi@4.42.0': 345 | resolution: {integrity: sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==} 346 | cpu: [arm] 347 | os: [android] 348 | 349 | '@rollup/rollup-android-arm64@4.42.0': 350 | resolution: {integrity: sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==} 351 | cpu: [arm64] 352 | os: [android] 353 | 354 | '@rollup/rollup-darwin-arm64@4.42.0': 355 | resolution: {integrity: sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==} 356 | cpu: [arm64] 357 | os: [darwin] 358 | 359 | '@rollup/rollup-darwin-x64@4.42.0': 360 | resolution: {integrity: sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==} 361 | cpu: [x64] 362 | os: [darwin] 363 | 364 | '@rollup/rollup-freebsd-arm64@4.42.0': 365 | resolution: {integrity: sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==} 366 | cpu: [arm64] 367 | os: [freebsd] 368 | 369 | '@rollup/rollup-freebsd-x64@4.42.0': 370 | resolution: {integrity: sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==} 371 | cpu: [x64] 372 | os: [freebsd] 373 | 374 | '@rollup/rollup-linux-arm-gnueabihf@4.42.0': 375 | resolution: {integrity: sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==} 376 | cpu: [arm] 377 | os: [linux] 378 | 379 | '@rollup/rollup-linux-arm-musleabihf@4.42.0': 380 | resolution: {integrity: sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==} 381 | cpu: [arm] 382 | os: [linux] 383 | 384 | '@rollup/rollup-linux-arm64-gnu@4.42.0': 385 | resolution: {integrity: sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==} 386 | cpu: [arm64] 387 | os: [linux] 388 | 389 | '@rollup/rollup-linux-arm64-musl@4.42.0': 390 | resolution: {integrity: sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==} 391 | cpu: [arm64] 392 | os: [linux] 393 | 394 | '@rollup/rollup-linux-loongarch64-gnu@4.42.0': 395 | resolution: {integrity: sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==} 396 | cpu: [loong64] 397 | os: [linux] 398 | 399 | '@rollup/rollup-linux-powerpc64le-gnu@4.42.0': 400 | resolution: {integrity: sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==} 401 | cpu: [ppc64] 402 | os: [linux] 403 | 404 | '@rollup/rollup-linux-riscv64-gnu@4.42.0': 405 | resolution: {integrity: sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==} 406 | cpu: [riscv64] 407 | os: [linux] 408 | 409 | '@rollup/rollup-linux-riscv64-musl@4.42.0': 410 | resolution: {integrity: sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==} 411 | cpu: [riscv64] 412 | os: [linux] 413 | 414 | '@rollup/rollup-linux-s390x-gnu@4.42.0': 415 | resolution: {integrity: sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==} 416 | cpu: [s390x] 417 | os: [linux] 418 | 419 | '@rollup/rollup-linux-x64-gnu@4.42.0': 420 | resolution: {integrity: sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==} 421 | cpu: [x64] 422 | os: [linux] 423 | 424 | '@rollup/rollup-linux-x64-musl@4.42.0': 425 | resolution: {integrity: sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==} 426 | cpu: [x64] 427 | os: [linux] 428 | 429 | '@rollup/rollup-win32-arm64-msvc@4.42.0': 430 | resolution: {integrity: sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==} 431 | cpu: [arm64] 432 | os: [win32] 433 | 434 | '@rollup/rollup-win32-ia32-msvc@4.42.0': 435 | resolution: {integrity: sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==} 436 | cpu: [ia32] 437 | os: [win32] 438 | 439 | '@rollup/rollup-win32-x64-msvc@4.42.0': 440 | resolution: {integrity: sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==} 441 | cpu: [x64] 442 | os: [win32] 443 | 444 | '@stylistic/eslint-plugin@4.4.1': 445 | resolution: {integrity: sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ==} 446 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 447 | peerDependencies: 448 | eslint: '>=9.0.0' 449 | 450 | '@susisu/eslint-config@0.0.97': 451 | resolution: {integrity: sha512-6j4I2+v3BVo3fEZHDGw0ddl+6Kc1qOesAk/qUhytvxfg6K08e+TENcqz0ddo1gv8J31m+ekvQxSkLZ8w4B2w5Q==} 452 | peerDependencies: 453 | eslint: ^9.19.0 454 | 455 | '@susisu/eslint-plugin-safe-typescript@0.9.4': 456 | resolution: {integrity: sha512-mG3hea82ybJCz+F07Wwcp6QZHuROPud9M8VgTN4+7H4A5KRYM1Gn5ZvJXqnslQgID8mkafu8tSzgn4zjtNpi0w==} 457 | peerDependencies: 458 | '@typescript-eslint/parser': ^8.0.0 459 | eslint: ^9.10.0 460 | typescript: '*' 461 | typescript-eslint: ^8.0.0 462 | peerDependenciesMeta: 463 | '@typescript-eslint/parser': 464 | optional: true 465 | typescript-eslint: 466 | optional: true 467 | 468 | '@types/chai@5.2.2': 469 | resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} 470 | 471 | '@types/deep-eql@4.0.2': 472 | resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} 473 | 474 | '@types/estree@1.0.7': 475 | resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 476 | 477 | '@types/estree@1.0.8': 478 | resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 479 | 480 | '@types/json-schema@7.0.15': 481 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 482 | 483 | '@types/node@22.15.30': 484 | resolution: {integrity: sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==} 485 | 486 | '@typescript-eslint/eslint-plugin@8.33.1': 487 | resolution: {integrity: sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==} 488 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 489 | peerDependencies: 490 | '@typescript-eslint/parser': ^8.33.1 491 | eslint: ^8.57.0 || ^9.0.0 492 | typescript: '>=4.8.4 <5.9.0' 493 | 494 | '@typescript-eslint/parser@8.33.1': 495 | resolution: {integrity: sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==} 496 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 497 | peerDependencies: 498 | eslint: ^8.57.0 || ^9.0.0 499 | typescript: '>=4.8.4 <5.9.0' 500 | 501 | '@typescript-eslint/project-service@8.33.1': 502 | resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==} 503 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 504 | peerDependencies: 505 | typescript: '>=4.8.4 <5.9.0' 506 | 507 | '@typescript-eslint/rule-tester@8.33.1': 508 | resolution: {integrity: sha512-tI5sR91lmeq9c3AN3b9YQH2koToOTQq0+x04CaVXludVX3eV2s7ZneqQ/nXgoG4VzWzVada8r49UXV5aa9g9fQ==} 509 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 510 | peerDependencies: 511 | eslint: ^8.57.0 || ^9.0.0 512 | 513 | '@typescript-eslint/scope-manager@8.33.1': 514 | resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} 515 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 516 | 517 | '@typescript-eslint/tsconfig-utils@8.33.1': 518 | resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} 519 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 520 | peerDependencies: 521 | typescript: '>=4.8.4 <5.9.0' 522 | 523 | '@typescript-eslint/type-utils@8.33.1': 524 | resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==} 525 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 526 | peerDependencies: 527 | eslint: ^8.57.0 || ^9.0.0 528 | typescript: '>=4.8.4 <5.9.0' 529 | 530 | '@typescript-eslint/types@8.33.1': 531 | resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==} 532 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 533 | 534 | '@typescript-eslint/typescript-estree@8.33.1': 535 | resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} 536 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 537 | peerDependencies: 538 | typescript: '>=4.8.4 <5.9.0' 539 | 540 | '@typescript-eslint/utils@8.33.1': 541 | resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} 542 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 543 | peerDependencies: 544 | eslint: ^8.57.0 || ^9.0.0 545 | typescript: '>=4.8.4 <5.9.0' 546 | 547 | '@typescript-eslint/visitor-keys@8.33.1': 548 | resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==} 549 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 550 | 551 | '@vitest/coverage-v8@3.2.2': 552 | resolution: {integrity: sha512-RVAi5xnqedSKvaoQyCTWvncMk8eYZcTTOsLK7XmnfOEvdGP/O/upA0/MA8Ss+Qs++mj0GcSRi/whR0S5iBPpTQ==} 553 | peerDependencies: 554 | '@vitest/browser': 3.2.2 555 | vitest: 3.2.2 556 | peerDependenciesMeta: 557 | '@vitest/browser': 558 | optional: true 559 | 560 | '@vitest/eslint-plugin@1.2.1': 561 | resolution: {integrity: sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==} 562 | peerDependencies: 563 | eslint: '>= 8.57.0' 564 | typescript: '>= 5.0.0' 565 | vitest: '*' 566 | peerDependenciesMeta: 567 | typescript: 568 | optional: true 569 | vitest: 570 | optional: true 571 | 572 | '@vitest/expect@3.2.2': 573 | resolution: {integrity: sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==} 574 | 575 | '@vitest/mocker@3.2.2': 576 | resolution: {integrity: sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==} 577 | peerDependencies: 578 | msw: ^2.4.9 579 | vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 580 | peerDependenciesMeta: 581 | msw: 582 | optional: true 583 | vite: 584 | optional: true 585 | 586 | '@vitest/pretty-format@3.2.2': 587 | resolution: {integrity: sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==} 588 | 589 | '@vitest/runner@3.2.2': 590 | resolution: {integrity: sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==} 591 | 592 | '@vitest/snapshot@3.2.2': 593 | resolution: {integrity: sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==} 594 | 595 | '@vitest/spy@3.2.2': 596 | resolution: {integrity: sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==} 597 | 598 | '@vitest/utils@3.2.2': 599 | resolution: {integrity: sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==} 600 | 601 | acorn-jsx@5.3.2: 602 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 603 | peerDependencies: 604 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 605 | 606 | acorn@8.14.1: 607 | resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 608 | engines: {node: '>=0.4.0'} 609 | hasBin: true 610 | 611 | ajv@6.12.6: 612 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 613 | 614 | ansi-regex@5.0.1: 615 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 616 | engines: {node: '>=8'} 617 | 618 | ansi-regex@6.1.0: 619 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 620 | engines: {node: '>=12'} 621 | 622 | ansi-styles@4.3.0: 623 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 624 | engines: {node: '>=8'} 625 | 626 | ansi-styles@6.2.1: 627 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 628 | engines: {node: '>=12'} 629 | 630 | argparse@2.0.1: 631 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 632 | 633 | assertion-error@2.0.1: 634 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 635 | engines: {node: '>=12'} 636 | 637 | ast-v8-to-istanbul@0.3.3: 638 | resolution: {integrity: sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw==} 639 | 640 | balanced-match@1.0.2: 641 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 642 | 643 | brace-expansion@1.1.11: 644 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 645 | 646 | brace-expansion@2.0.1: 647 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 648 | 649 | braces@3.0.3: 650 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 651 | engines: {node: '>=8'} 652 | 653 | cac@6.7.14: 654 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 655 | engines: {node: '>=8'} 656 | 657 | callsites@3.1.0: 658 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 659 | engines: {node: '>=6'} 660 | 661 | chai@5.2.0: 662 | resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} 663 | engines: {node: '>=12'} 664 | 665 | chalk@4.1.2: 666 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 667 | engines: {node: '>=10'} 668 | 669 | check-error@2.1.1: 670 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 671 | engines: {node: '>= 16'} 672 | 673 | color-convert@2.0.1: 674 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 675 | engines: {node: '>=7.0.0'} 676 | 677 | color-name@1.1.4: 678 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 679 | 680 | concat-map@0.0.1: 681 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 682 | 683 | cross-spawn@7.0.6: 684 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 685 | engines: {node: '>= 8'} 686 | 687 | debug@4.4.1: 688 | resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 689 | engines: {node: '>=6.0'} 690 | peerDependencies: 691 | supports-color: '*' 692 | peerDependenciesMeta: 693 | supports-color: 694 | optional: true 695 | 696 | deep-eql@5.0.2: 697 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 698 | engines: {node: '>=6'} 699 | 700 | deep-is@0.1.4: 701 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 702 | 703 | eastasianwidth@0.2.0: 704 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 705 | 706 | emoji-regex@8.0.0: 707 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 708 | 709 | emoji-regex@9.2.2: 710 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 711 | 712 | es-module-lexer@1.7.0: 713 | resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} 714 | 715 | esbuild@0.25.5: 716 | resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} 717 | engines: {node: '>=18'} 718 | hasBin: true 719 | 720 | escape-string-regexp@4.0.0: 721 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 722 | engines: {node: '>=10'} 723 | 724 | eslint-config-prettier@10.1.5: 725 | resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==} 726 | hasBin: true 727 | peerDependencies: 728 | eslint: '>=7.0.0' 729 | 730 | eslint-plugin-eslint-plugin@6.4.0: 731 | resolution: {integrity: sha512-X94/hr7DnckX68wE6Qqeo3DsZndZSclfoewjwD249yG5z2EAOl3UGUohLIgOpmbUjcFv6AlfW3wxBnOiWkS1Iw==} 732 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 733 | peerDependencies: 734 | eslint: '>=8.23.0' 735 | 736 | eslint-scope@8.3.0: 737 | resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} 738 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 739 | 740 | eslint-visitor-keys@3.4.3: 741 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 742 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 743 | 744 | eslint-visitor-keys@4.2.0: 745 | resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 746 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 747 | 748 | eslint@9.28.0: 749 | resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} 750 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 751 | hasBin: true 752 | peerDependencies: 753 | jiti: '*' 754 | peerDependenciesMeta: 755 | jiti: 756 | optional: true 757 | 758 | espree@10.3.0: 759 | resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} 760 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 761 | 762 | esquery@1.6.0: 763 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 764 | engines: {node: '>=0.10'} 765 | 766 | esrecurse@4.3.0: 767 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 768 | engines: {node: '>=4.0'} 769 | 770 | estraverse@5.3.0: 771 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 772 | engines: {node: '>=4.0'} 773 | 774 | estree-walker@3.0.3: 775 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 776 | 777 | esutils@2.0.3: 778 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 779 | engines: {node: '>=0.10.0'} 780 | 781 | expect-type@1.2.1: 782 | resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} 783 | engines: {node: '>=12.0.0'} 784 | 785 | fast-deep-equal@3.1.3: 786 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 787 | 788 | fast-glob@3.3.3: 789 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 790 | engines: {node: '>=8.6.0'} 791 | 792 | fast-json-stable-stringify@2.1.0: 793 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 794 | 795 | fast-levenshtein@2.0.6: 796 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 797 | 798 | fastq@1.19.1: 799 | resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 800 | 801 | fdir@6.4.5: 802 | resolution: {integrity: sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==} 803 | peerDependencies: 804 | picomatch: ^3 || ^4 805 | peerDependenciesMeta: 806 | picomatch: 807 | optional: true 808 | 809 | file-entry-cache@8.0.0: 810 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 811 | engines: {node: '>=16.0.0'} 812 | 813 | fill-range@7.1.1: 814 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 815 | engines: {node: '>=8'} 816 | 817 | find-up@5.0.0: 818 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 819 | engines: {node: '>=10'} 820 | 821 | flat-cache@4.0.1: 822 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 823 | engines: {node: '>=16'} 824 | 825 | flatted@3.3.3: 826 | resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 827 | 828 | foreground-child@3.3.1: 829 | resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 830 | engines: {node: '>=14'} 831 | 832 | fsevents@2.3.3: 833 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 834 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 835 | os: [darwin] 836 | 837 | glob-parent@5.1.2: 838 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 839 | engines: {node: '>= 6'} 840 | 841 | glob-parent@6.0.2: 842 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 843 | engines: {node: '>=10.13.0'} 844 | 845 | glob@10.4.5: 846 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 847 | hasBin: true 848 | 849 | glob@11.0.2: 850 | resolution: {integrity: sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==} 851 | engines: {node: 20 || >=22} 852 | hasBin: true 853 | 854 | globals@14.0.0: 855 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 856 | engines: {node: '>=18'} 857 | 858 | globals@16.2.0: 859 | resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==} 860 | engines: {node: '>=18'} 861 | 862 | graphemer@1.4.0: 863 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 864 | 865 | has-flag@4.0.0: 866 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 867 | engines: {node: '>=8'} 868 | 869 | html-escaper@2.0.2: 870 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} 871 | 872 | ignore@5.3.2: 873 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 874 | engines: {node: '>= 4'} 875 | 876 | ignore@7.0.5: 877 | resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} 878 | engines: {node: '>= 4'} 879 | 880 | import-fresh@3.3.1: 881 | resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 882 | engines: {node: '>=6'} 883 | 884 | imurmurhash@0.1.4: 885 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 886 | engines: {node: '>=0.8.19'} 887 | 888 | is-extglob@2.1.1: 889 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 890 | engines: {node: '>=0.10.0'} 891 | 892 | is-fullwidth-code-point@3.0.0: 893 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 894 | engines: {node: '>=8'} 895 | 896 | is-glob@4.0.3: 897 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 898 | engines: {node: '>=0.10.0'} 899 | 900 | is-number@7.0.0: 901 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 902 | engines: {node: '>=0.12.0'} 903 | 904 | isexe@2.0.0: 905 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 906 | 907 | isexe@3.1.1: 908 | resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} 909 | engines: {node: '>=16'} 910 | 911 | istanbul-lib-coverage@3.2.2: 912 | resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} 913 | engines: {node: '>=8'} 914 | 915 | istanbul-lib-report@3.0.1: 916 | resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} 917 | engines: {node: '>=10'} 918 | 919 | istanbul-lib-source-maps@5.0.6: 920 | resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} 921 | engines: {node: '>=10'} 922 | 923 | istanbul-reports@3.1.7: 924 | resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} 925 | engines: {node: '>=8'} 926 | 927 | jackspeak@3.4.3: 928 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 929 | 930 | jackspeak@4.1.1: 931 | resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} 932 | engines: {node: 20 || >=22} 933 | 934 | js-tokens@9.0.1: 935 | resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} 936 | 937 | js-yaml@4.1.0: 938 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 939 | hasBin: true 940 | 941 | json-buffer@3.0.1: 942 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 943 | 944 | json-parse-even-better-errors@4.0.0: 945 | resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==} 946 | engines: {node: ^18.17.0 || >=20.5.0} 947 | 948 | json-schema-traverse@0.4.1: 949 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 950 | 951 | json-stable-stringify-without-jsonify@1.0.1: 952 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 953 | 954 | keyv@4.5.4: 955 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 956 | 957 | levn@0.4.1: 958 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 959 | engines: {node: '>= 0.8.0'} 960 | 961 | locate-path@6.0.0: 962 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 963 | engines: {node: '>=10'} 964 | 965 | lodash.merge@4.6.2: 966 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 967 | 968 | loupe@3.1.3: 969 | resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} 970 | 971 | lru-cache@10.4.3: 972 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 973 | 974 | lru-cache@11.1.0: 975 | resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} 976 | engines: {node: 20 || >=22} 977 | 978 | magic-string@0.30.17: 979 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 980 | 981 | magicast@0.3.5: 982 | resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} 983 | 984 | make-dir@4.0.0: 985 | resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} 986 | engines: {node: '>=10'} 987 | 988 | memorystream@0.3.1: 989 | resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} 990 | engines: {node: '>= 0.10.0'} 991 | 992 | merge2@1.4.1: 993 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 994 | engines: {node: '>= 8'} 995 | 996 | micromatch@4.0.8: 997 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 998 | engines: {node: '>=8.6'} 999 | 1000 | minimatch@10.0.1: 1001 | resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} 1002 | engines: {node: 20 || >=22} 1003 | 1004 | minimatch@3.1.2: 1005 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1006 | 1007 | minimatch@9.0.5: 1008 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1009 | engines: {node: '>=16 || 14 >=14.17'} 1010 | 1011 | minipass@7.1.2: 1012 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1013 | engines: {node: '>=16 || 14 >=14.17'} 1014 | 1015 | ms@2.1.3: 1016 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1017 | 1018 | nanoid@3.3.11: 1019 | resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 1020 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1021 | hasBin: true 1022 | 1023 | natural-compare@1.4.0: 1024 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1025 | 1026 | npm-normalize-package-bin@4.0.0: 1027 | resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} 1028 | engines: {node: ^18.17.0 || >=20.5.0} 1029 | 1030 | npm-run-all2@8.0.4: 1031 | resolution: {integrity: sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==} 1032 | engines: {node: ^20.5.0 || >=22.0.0, npm: '>= 10'} 1033 | hasBin: true 1034 | 1035 | optionator@0.9.4: 1036 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 1037 | engines: {node: '>= 0.8.0'} 1038 | 1039 | p-limit@3.1.0: 1040 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1041 | engines: {node: '>=10'} 1042 | 1043 | p-locate@5.0.0: 1044 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1045 | engines: {node: '>=10'} 1046 | 1047 | package-json-from-dist@1.0.1: 1048 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1049 | 1050 | parent-module@1.0.1: 1051 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1052 | engines: {node: '>=6'} 1053 | 1054 | path-exists@4.0.0: 1055 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1056 | engines: {node: '>=8'} 1057 | 1058 | path-key@3.1.1: 1059 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1060 | engines: {node: '>=8'} 1061 | 1062 | path-scurry@1.11.1: 1063 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1064 | engines: {node: '>=16 || 14 >=14.18'} 1065 | 1066 | path-scurry@2.0.0: 1067 | resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} 1068 | engines: {node: 20 || >=22} 1069 | 1070 | pathe@2.0.3: 1071 | resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1072 | 1073 | pathval@2.0.0: 1074 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1075 | engines: {node: '>= 14.16'} 1076 | 1077 | picocolors@1.1.1: 1078 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1079 | 1080 | picomatch@2.3.1: 1081 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1082 | engines: {node: '>=8.6'} 1083 | 1084 | picomatch@4.0.2: 1085 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1086 | engines: {node: '>=12'} 1087 | 1088 | pidtree@0.6.0: 1089 | resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} 1090 | engines: {node: '>=0.10'} 1091 | hasBin: true 1092 | 1093 | postcss@8.5.4: 1094 | resolution: {integrity: sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==} 1095 | engines: {node: ^10 || ^12 || >=14} 1096 | 1097 | prelude-ls@1.2.1: 1098 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1099 | engines: {node: '>= 0.8.0'} 1100 | 1101 | prettier@3.5.3: 1102 | resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} 1103 | engines: {node: '>=14'} 1104 | hasBin: true 1105 | 1106 | punycode@2.3.1: 1107 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1108 | engines: {node: '>=6'} 1109 | 1110 | queue-microtask@1.2.3: 1111 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1112 | 1113 | read-package-json-fast@4.0.0: 1114 | resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==} 1115 | engines: {node: ^18.17.0 || >=20.5.0} 1116 | 1117 | resolve-from@4.0.0: 1118 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1119 | engines: {node: '>=4'} 1120 | 1121 | reusify@1.1.0: 1122 | resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1123 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1124 | 1125 | rimraf@6.0.1: 1126 | resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} 1127 | engines: {node: 20 || >=22} 1128 | hasBin: true 1129 | 1130 | rollup@4.42.0: 1131 | resolution: {integrity: sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==} 1132 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1133 | hasBin: true 1134 | 1135 | run-parallel@1.2.0: 1136 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1137 | 1138 | semver@7.7.2: 1139 | resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 1140 | engines: {node: '>=10'} 1141 | hasBin: true 1142 | 1143 | shebang-command@2.0.0: 1144 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1145 | engines: {node: '>=8'} 1146 | 1147 | shebang-regex@3.0.0: 1148 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1149 | engines: {node: '>=8'} 1150 | 1151 | shell-quote@1.8.3: 1152 | resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} 1153 | engines: {node: '>= 0.4'} 1154 | 1155 | siginfo@2.0.0: 1156 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1157 | 1158 | signal-exit@4.1.0: 1159 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1160 | engines: {node: '>=14'} 1161 | 1162 | source-map-js@1.2.1: 1163 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1164 | engines: {node: '>=0.10.0'} 1165 | 1166 | stackback@0.0.2: 1167 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1168 | 1169 | std-env@3.9.0: 1170 | resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} 1171 | 1172 | string-width@4.2.3: 1173 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1174 | engines: {node: '>=8'} 1175 | 1176 | string-width@5.1.2: 1177 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1178 | engines: {node: '>=12'} 1179 | 1180 | strip-ansi@6.0.1: 1181 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1182 | engines: {node: '>=8'} 1183 | 1184 | strip-ansi@7.1.0: 1185 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1186 | engines: {node: '>=12'} 1187 | 1188 | strip-json-comments@3.1.1: 1189 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1190 | engines: {node: '>=8'} 1191 | 1192 | supports-color@7.2.0: 1193 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1194 | engines: {node: '>=8'} 1195 | 1196 | test-exclude@7.0.1: 1197 | resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} 1198 | engines: {node: '>=18'} 1199 | 1200 | tinybench@2.9.0: 1201 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1202 | 1203 | tinyexec@0.3.2: 1204 | resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} 1205 | 1206 | tinyglobby@0.2.14: 1207 | resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} 1208 | engines: {node: '>=12.0.0'} 1209 | 1210 | tinypool@1.1.0: 1211 | resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} 1212 | engines: {node: ^18.0.0 || >=20.0.0} 1213 | 1214 | tinyrainbow@2.0.0: 1215 | resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} 1216 | engines: {node: '>=14.0.0'} 1217 | 1218 | tinyspy@4.0.3: 1219 | resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} 1220 | engines: {node: '>=14.0.0'} 1221 | 1222 | to-regex-range@5.0.1: 1223 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1224 | engines: {node: '>=8.0'} 1225 | 1226 | ts-api-utils@2.1.0: 1227 | resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1228 | engines: {node: '>=18.12'} 1229 | peerDependencies: 1230 | typescript: '>=4.8.4' 1231 | 1232 | type-check@0.4.0: 1233 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1234 | engines: {node: '>= 0.8.0'} 1235 | 1236 | typescript-eslint@8.33.1: 1237 | resolution: {integrity: sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==} 1238 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1239 | peerDependencies: 1240 | eslint: ^8.57.0 || ^9.0.0 1241 | typescript: '>=4.8.4 <5.9.0' 1242 | 1243 | typescript@5.8.3: 1244 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1245 | engines: {node: '>=14.17'} 1246 | hasBin: true 1247 | 1248 | undici-types@6.21.0: 1249 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1250 | 1251 | uri-js@4.4.1: 1252 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1253 | 1254 | vite-node@3.2.2: 1255 | resolution: {integrity: sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==} 1256 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1257 | hasBin: true 1258 | 1259 | vite@6.3.5: 1260 | resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} 1261 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1262 | hasBin: true 1263 | peerDependencies: 1264 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1265 | jiti: '>=1.21.0' 1266 | less: '*' 1267 | lightningcss: ^1.21.0 1268 | sass: '*' 1269 | sass-embedded: '*' 1270 | stylus: '*' 1271 | sugarss: '*' 1272 | terser: ^5.16.0 1273 | tsx: ^4.8.1 1274 | yaml: ^2.4.2 1275 | peerDependenciesMeta: 1276 | '@types/node': 1277 | optional: true 1278 | jiti: 1279 | optional: true 1280 | less: 1281 | optional: true 1282 | lightningcss: 1283 | optional: true 1284 | sass: 1285 | optional: true 1286 | sass-embedded: 1287 | optional: true 1288 | stylus: 1289 | optional: true 1290 | sugarss: 1291 | optional: true 1292 | terser: 1293 | optional: true 1294 | tsx: 1295 | optional: true 1296 | yaml: 1297 | optional: true 1298 | 1299 | vitest@3.2.2: 1300 | resolution: {integrity: sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==} 1301 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1302 | hasBin: true 1303 | peerDependencies: 1304 | '@edge-runtime/vm': '*' 1305 | '@types/debug': ^4.1.12 1306 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1307 | '@vitest/browser': 3.2.2 1308 | '@vitest/ui': 3.2.2 1309 | happy-dom: '*' 1310 | jsdom: '*' 1311 | peerDependenciesMeta: 1312 | '@edge-runtime/vm': 1313 | optional: true 1314 | '@types/debug': 1315 | optional: true 1316 | '@types/node': 1317 | optional: true 1318 | '@vitest/browser': 1319 | optional: true 1320 | '@vitest/ui': 1321 | optional: true 1322 | happy-dom: 1323 | optional: true 1324 | jsdom: 1325 | optional: true 1326 | 1327 | which@2.0.2: 1328 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1329 | engines: {node: '>= 8'} 1330 | hasBin: true 1331 | 1332 | which@5.0.0: 1333 | resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} 1334 | engines: {node: ^18.17.0 || >=20.5.0} 1335 | hasBin: true 1336 | 1337 | why-is-node-running@2.3.0: 1338 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1339 | engines: {node: '>=8'} 1340 | hasBin: true 1341 | 1342 | word-wrap@1.2.5: 1343 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1344 | engines: {node: '>=0.10.0'} 1345 | 1346 | wrap-ansi@7.0.0: 1347 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1348 | engines: {node: '>=10'} 1349 | 1350 | wrap-ansi@8.1.0: 1351 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1352 | engines: {node: '>=12'} 1353 | 1354 | yaml@2.5.1: 1355 | resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} 1356 | engines: {node: '>= 14'} 1357 | hasBin: true 1358 | 1359 | yocto-queue@0.1.0: 1360 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1361 | engines: {node: '>=10'} 1362 | 1363 | snapshots: 1364 | 1365 | '@ampproject/remapping@2.3.0': 1366 | dependencies: 1367 | '@jridgewell/gen-mapping': 0.3.8 1368 | '@jridgewell/trace-mapping': 0.3.25 1369 | 1370 | '@babel/helper-string-parser@7.27.1': {} 1371 | 1372 | '@babel/helper-validator-identifier@7.27.1': {} 1373 | 1374 | '@babel/parser@7.27.5': 1375 | dependencies: 1376 | '@babel/types': 7.27.6 1377 | 1378 | '@babel/types@7.27.6': 1379 | dependencies: 1380 | '@babel/helper-string-parser': 7.27.1 1381 | '@babel/helper-validator-identifier': 7.27.1 1382 | 1383 | '@bcoe/v8-coverage@1.0.2': {} 1384 | 1385 | '@esbuild/aix-ppc64@0.25.5': 1386 | optional: true 1387 | 1388 | '@esbuild/android-arm64@0.25.5': 1389 | optional: true 1390 | 1391 | '@esbuild/android-arm@0.25.5': 1392 | optional: true 1393 | 1394 | '@esbuild/android-x64@0.25.5': 1395 | optional: true 1396 | 1397 | '@esbuild/darwin-arm64@0.25.5': 1398 | optional: true 1399 | 1400 | '@esbuild/darwin-x64@0.25.5': 1401 | optional: true 1402 | 1403 | '@esbuild/freebsd-arm64@0.25.5': 1404 | optional: true 1405 | 1406 | '@esbuild/freebsd-x64@0.25.5': 1407 | optional: true 1408 | 1409 | '@esbuild/linux-arm64@0.25.5': 1410 | optional: true 1411 | 1412 | '@esbuild/linux-arm@0.25.5': 1413 | optional: true 1414 | 1415 | '@esbuild/linux-ia32@0.25.5': 1416 | optional: true 1417 | 1418 | '@esbuild/linux-loong64@0.25.5': 1419 | optional: true 1420 | 1421 | '@esbuild/linux-mips64el@0.25.5': 1422 | optional: true 1423 | 1424 | '@esbuild/linux-ppc64@0.25.5': 1425 | optional: true 1426 | 1427 | '@esbuild/linux-riscv64@0.25.5': 1428 | optional: true 1429 | 1430 | '@esbuild/linux-s390x@0.25.5': 1431 | optional: true 1432 | 1433 | '@esbuild/linux-x64@0.25.5': 1434 | optional: true 1435 | 1436 | '@esbuild/netbsd-arm64@0.25.5': 1437 | optional: true 1438 | 1439 | '@esbuild/netbsd-x64@0.25.5': 1440 | optional: true 1441 | 1442 | '@esbuild/openbsd-arm64@0.25.5': 1443 | optional: true 1444 | 1445 | '@esbuild/openbsd-x64@0.25.5': 1446 | optional: true 1447 | 1448 | '@esbuild/sunos-x64@0.25.5': 1449 | optional: true 1450 | 1451 | '@esbuild/win32-arm64@0.25.5': 1452 | optional: true 1453 | 1454 | '@esbuild/win32-ia32@0.25.5': 1455 | optional: true 1456 | 1457 | '@esbuild/win32-x64@0.25.5': 1458 | optional: true 1459 | 1460 | '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0)': 1461 | dependencies: 1462 | eslint: 9.28.0 1463 | eslint-visitor-keys: 3.4.3 1464 | 1465 | '@eslint-community/regexpp@4.12.1': {} 1466 | 1467 | '@eslint/config-array@0.20.0': 1468 | dependencies: 1469 | '@eslint/object-schema': 2.1.6 1470 | debug: 4.4.1 1471 | minimatch: 3.1.2 1472 | transitivePeerDependencies: 1473 | - supports-color 1474 | 1475 | '@eslint/config-helpers@0.2.2': {} 1476 | 1477 | '@eslint/core@0.14.0': 1478 | dependencies: 1479 | '@types/json-schema': 7.0.15 1480 | 1481 | '@eslint/eslintrc@3.3.1': 1482 | dependencies: 1483 | ajv: 6.12.6 1484 | debug: 4.4.1 1485 | espree: 10.3.0 1486 | globals: 14.0.0 1487 | ignore: 5.3.2 1488 | import-fresh: 3.3.1 1489 | js-yaml: 4.1.0 1490 | minimatch: 3.1.2 1491 | strip-json-comments: 3.1.1 1492 | transitivePeerDependencies: 1493 | - supports-color 1494 | 1495 | '@eslint/js@9.28.0': {} 1496 | 1497 | '@eslint/object-schema@2.1.6': {} 1498 | 1499 | '@eslint/plugin-kit@0.3.1': 1500 | dependencies: 1501 | '@eslint/core': 0.14.0 1502 | levn: 0.4.1 1503 | 1504 | '@humanfs/core@0.19.1': {} 1505 | 1506 | '@humanfs/node@0.16.6': 1507 | dependencies: 1508 | '@humanfs/core': 0.19.1 1509 | '@humanwhocodes/retry': 0.3.1 1510 | 1511 | '@humanwhocodes/module-importer@1.0.1': {} 1512 | 1513 | '@humanwhocodes/retry@0.3.1': {} 1514 | 1515 | '@humanwhocodes/retry@0.4.3': {} 1516 | 1517 | '@isaacs/cliui@8.0.2': 1518 | dependencies: 1519 | string-width: 5.1.2 1520 | string-width-cjs: string-width@4.2.3 1521 | strip-ansi: 7.1.0 1522 | strip-ansi-cjs: strip-ansi@6.0.1 1523 | wrap-ansi: 8.1.0 1524 | wrap-ansi-cjs: wrap-ansi@7.0.0 1525 | 1526 | '@istanbuljs/schema@0.1.3': {} 1527 | 1528 | '@jridgewell/gen-mapping@0.3.8': 1529 | dependencies: 1530 | '@jridgewell/set-array': 1.2.1 1531 | '@jridgewell/sourcemap-codec': 1.5.0 1532 | '@jridgewell/trace-mapping': 0.3.25 1533 | 1534 | '@jridgewell/resolve-uri@3.1.2': {} 1535 | 1536 | '@jridgewell/set-array@1.2.1': {} 1537 | 1538 | '@jridgewell/sourcemap-codec@1.5.0': {} 1539 | 1540 | '@jridgewell/trace-mapping@0.3.25': 1541 | dependencies: 1542 | '@jridgewell/resolve-uri': 3.1.2 1543 | '@jridgewell/sourcemap-codec': 1.5.0 1544 | 1545 | '@nodelib/fs.scandir@2.1.5': 1546 | dependencies: 1547 | '@nodelib/fs.stat': 2.0.5 1548 | run-parallel: 1.2.0 1549 | 1550 | '@nodelib/fs.stat@2.0.5': {} 1551 | 1552 | '@nodelib/fs.walk@1.2.8': 1553 | dependencies: 1554 | '@nodelib/fs.scandir': 2.1.5 1555 | fastq: 1.19.1 1556 | 1557 | '@pkgjs/parseargs@0.11.0': 1558 | optional: true 1559 | 1560 | '@qnighy/dedent@0.1.1': {} 1561 | 1562 | '@rollup/rollup-android-arm-eabi@4.42.0': 1563 | optional: true 1564 | 1565 | '@rollup/rollup-android-arm64@4.42.0': 1566 | optional: true 1567 | 1568 | '@rollup/rollup-darwin-arm64@4.42.0': 1569 | optional: true 1570 | 1571 | '@rollup/rollup-darwin-x64@4.42.0': 1572 | optional: true 1573 | 1574 | '@rollup/rollup-freebsd-arm64@4.42.0': 1575 | optional: true 1576 | 1577 | '@rollup/rollup-freebsd-x64@4.42.0': 1578 | optional: true 1579 | 1580 | '@rollup/rollup-linux-arm-gnueabihf@4.42.0': 1581 | optional: true 1582 | 1583 | '@rollup/rollup-linux-arm-musleabihf@4.42.0': 1584 | optional: true 1585 | 1586 | '@rollup/rollup-linux-arm64-gnu@4.42.0': 1587 | optional: true 1588 | 1589 | '@rollup/rollup-linux-arm64-musl@4.42.0': 1590 | optional: true 1591 | 1592 | '@rollup/rollup-linux-loongarch64-gnu@4.42.0': 1593 | optional: true 1594 | 1595 | '@rollup/rollup-linux-powerpc64le-gnu@4.42.0': 1596 | optional: true 1597 | 1598 | '@rollup/rollup-linux-riscv64-gnu@4.42.0': 1599 | optional: true 1600 | 1601 | '@rollup/rollup-linux-riscv64-musl@4.42.0': 1602 | optional: true 1603 | 1604 | '@rollup/rollup-linux-s390x-gnu@4.42.0': 1605 | optional: true 1606 | 1607 | '@rollup/rollup-linux-x64-gnu@4.42.0': 1608 | optional: true 1609 | 1610 | '@rollup/rollup-linux-x64-musl@4.42.0': 1611 | optional: true 1612 | 1613 | '@rollup/rollup-win32-arm64-msvc@4.42.0': 1614 | optional: true 1615 | 1616 | '@rollup/rollup-win32-ia32-msvc@4.42.0': 1617 | optional: true 1618 | 1619 | '@rollup/rollup-win32-x64-msvc@4.42.0': 1620 | optional: true 1621 | 1622 | '@stylistic/eslint-plugin@4.4.1(eslint@9.28.0)(typescript@5.8.3)': 1623 | dependencies: 1624 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1625 | eslint: 9.28.0 1626 | eslint-visitor-keys: 4.2.0 1627 | espree: 10.3.0 1628 | estraverse: 5.3.0 1629 | picomatch: 4.0.2 1630 | transitivePeerDependencies: 1631 | - supports-color 1632 | - typescript 1633 | 1634 | '@susisu/eslint-config@0.0.97(eslint@9.28.0)(typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3))(typescript@5.8.3)': 1635 | dependencies: 1636 | '@eslint/config-helpers': 0.2.2 1637 | '@stylistic/eslint-plugin': 4.4.1(eslint@9.28.0)(typescript@5.8.3) 1638 | '@susisu/eslint-plugin-safe-typescript': 0.9.4(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3))(typescript@5.8.3) 1639 | '@typescript-eslint/eslint-plugin': 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3) 1640 | '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1641 | eslint: 9.28.0 1642 | eslint-config-prettier: 10.1.5(eslint@9.28.0) 1643 | transitivePeerDependencies: 1644 | - supports-color 1645 | - typescript 1646 | - typescript-eslint 1647 | 1648 | '@susisu/eslint-plugin-safe-typescript@0.9.4(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3))(typescript@5.8.3)': 1649 | dependencies: 1650 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1651 | eslint: 9.28.0 1652 | typescript: 5.8.3 1653 | optionalDependencies: 1654 | '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1655 | typescript-eslint: 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1656 | transitivePeerDependencies: 1657 | - supports-color 1658 | 1659 | '@types/chai@5.2.2': 1660 | dependencies: 1661 | '@types/deep-eql': 4.0.2 1662 | 1663 | '@types/deep-eql@4.0.2': {} 1664 | 1665 | '@types/estree@1.0.7': {} 1666 | 1667 | '@types/estree@1.0.8': {} 1668 | 1669 | '@types/json-schema@7.0.15': {} 1670 | 1671 | '@types/node@22.15.30': 1672 | dependencies: 1673 | undici-types: 6.21.0 1674 | 1675 | '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3)': 1676 | dependencies: 1677 | '@eslint-community/regexpp': 4.12.1 1678 | '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1679 | '@typescript-eslint/scope-manager': 8.33.1 1680 | '@typescript-eslint/type-utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1681 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1682 | '@typescript-eslint/visitor-keys': 8.33.1 1683 | eslint: 9.28.0 1684 | graphemer: 1.4.0 1685 | ignore: 7.0.5 1686 | natural-compare: 1.4.0 1687 | ts-api-utils: 2.1.0(typescript@5.8.3) 1688 | typescript: 5.8.3 1689 | transitivePeerDependencies: 1690 | - supports-color 1691 | 1692 | '@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3)': 1693 | dependencies: 1694 | '@typescript-eslint/scope-manager': 8.33.1 1695 | '@typescript-eslint/types': 8.33.1 1696 | '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) 1697 | '@typescript-eslint/visitor-keys': 8.33.1 1698 | debug: 4.4.1 1699 | eslint: 9.28.0 1700 | typescript: 5.8.3 1701 | transitivePeerDependencies: 1702 | - supports-color 1703 | 1704 | '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': 1705 | dependencies: 1706 | '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) 1707 | '@typescript-eslint/types': 8.33.1 1708 | debug: 4.4.1 1709 | typescript: 5.8.3 1710 | transitivePeerDependencies: 1711 | - supports-color 1712 | 1713 | '@typescript-eslint/rule-tester@8.33.1(eslint@9.28.0)(typescript@5.8.3)': 1714 | dependencies: 1715 | '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1716 | '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) 1717 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1718 | ajv: 6.12.6 1719 | eslint: 9.28.0 1720 | json-stable-stringify-without-jsonify: 1.0.1 1721 | lodash.merge: 4.6.2 1722 | semver: 7.7.2 1723 | transitivePeerDependencies: 1724 | - supports-color 1725 | - typescript 1726 | 1727 | '@typescript-eslint/scope-manager@8.33.1': 1728 | dependencies: 1729 | '@typescript-eslint/types': 8.33.1 1730 | '@typescript-eslint/visitor-keys': 8.33.1 1731 | 1732 | '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': 1733 | dependencies: 1734 | typescript: 5.8.3 1735 | 1736 | '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0)(typescript@5.8.3)': 1737 | dependencies: 1738 | '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) 1739 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1740 | debug: 4.4.1 1741 | eslint: 9.28.0 1742 | ts-api-utils: 2.1.0(typescript@5.8.3) 1743 | typescript: 5.8.3 1744 | transitivePeerDependencies: 1745 | - supports-color 1746 | 1747 | '@typescript-eslint/types@8.33.1': {} 1748 | 1749 | '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': 1750 | dependencies: 1751 | '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) 1752 | '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) 1753 | '@typescript-eslint/types': 8.33.1 1754 | '@typescript-eslint/visitor-keys': 8.33.1 1755 | debug: 4.4.1 1756 | fast-glob: 3.3.3 1757 | is-glob: 4.0.3 1758 | minimatch: 9.0.5 1759 | semver: 7.7.2 1760 | ts-api-utils: 2.1.0(typescript@5.8.3) 1761 | typescript: 5.8.3 1762 | transitivePeerDependencies: 1763 | - supports-color 1764 | 1765 | '@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3)': 1766 | dependencies: 1767 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) 1768 | '@typescript-eslint/scope-manager': 8.33.1 1769 | '@typescript-eslint/types': 8.33.1 1770 | '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) 1771 | eslint: 9.28.0 1772 | typescript: 5.8.3 1773 | transitivePeerDependencies: 1774 | - supports-color 1775 | 1776 | '@typescript-eslint/visitor-keys@8.33.1': 1777 | dependencies: 1778 | '@typescript-eslint/types': 8.33.1 1779 | eslint-visitor-keys: 4.2.0 1780 | 1781 | '@vitest/coverage-v8@3.2.2(vitest@3.2.2(@types/node@22.15.30)(yaml@2.5.1))': 1782 | dependencies: 1783 | '@ampproject/remapping': 2.3.0 1784 | '@bcoe/v8-coverage': 1.0.2 1785 | ast-v8-to-istanbul: 0.3.3 1786 | debug: 4.4.1 1787 | istanbul-lib-coverage: 3.2.2 1788 | istanbul-lib-report: 3.0.1 1789 | istanbul-lib-source-maps: 5.0.6 1790 | istanbul-reports: 3.1.7 1791 | magic-string: 0.30.17 1792 | magicast: 0.3.5 1793 | std-env: 3.9.0 1794 | test-exclude: 7.0.1 1795 | tinyrainbow: 2.0.0 1796 | vitest: 3.2.2(@types/node@22.15.30)(yaml@2.5.1) 1797 | transitivePeerDependencies: 1798 | - supports-color 1799 | 1800 | '@vitest/eslint-plugin@1.2.1(eslint@9.28.0)(typescript@5.8.3)(vitest@3.2.2(@types/node@22.15.30)(yaml@2.5.1))': 1801 | dependencies: 1802 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 1803 | eslint: 9.28.0 1804 | optionalDependencies: 1805 | typescript: 5.8.3 1806 | vitest: 3.2.2(@types/node@22.15.30)(yaml@2.5.1) 1807 | transitivePeerDependencies: 1808 | - supports-color 1809 | 1810 | '@vitest/expect@3.2.2': 1811 | dependencies: 1812 | '@types/chai': 5.2.2 1813 | '@vitest/spy': 3.2.2 1814 | '@vitest/utils': 3.2.2 1815 | chai: 5.2.0 1816 | tinyrainbow: 2.0.0 1817 | 1818 | '@vitest/mocker@3.2.2(vite@6.3.5(@types/node@22.15.30)(yaml@2.5.1))': 1819 | dependencies: 1820 | '@vitest/spy': 3.2.2 1821 | estree-walker: 3.0.3 1822 | magic-string: 0.30.17 1823 | optionalDependencies: 1824 | vite: 6.3.5(@types/node@22.15.30)(yaml@2.5.1) 1825 | 1826 | '@vitest/pretty-format@3.2.2': 1827 | dependencies: 1828 | tinyrainbow: 2.0.0 1829 | 1830 | '@vitest/runner@3.2.2': 1831 | dependencies: 1832 | '@vitest/utils': 3.2.2 1833 | pathe: 2.0.3 1834 | 1835 | '@vitest/snapshot@3.2.2': 1836 | dependencies: 1837 | '@vitest/pretty-format': 3.2.2 1838 | magic-string: 0.30.17 1839 | pathe: 2.0.3 1840 | 1841 | '@vitest/spy@3.2.2': 1842 | dependencies: 1843 | tinyspy: 4.0.3 1844 | 1845 | '@vitest/utils@3.2.2': 1846 | dependencies: 1847 | '@vitest/pretty-format': 3.2.2 1848 | loupe: 3.1.3 1849 | tinyrainbow: 2.0.0 1850 | 1851 | acorn-jsx@5.3.2(acorn@8.14.1): 1852 | dependencies: 1853 | acorn: 8.14.1 1854 | 1855 | acorn@8.14.1: {} 1856 | 1857 | ajv@6.12.6: 1858 | dependencies: 1859 | fast-deep-equal: 3.1.3 1860 | fast-json-stable-stringify: 2.1.0 1861 | json-schema-traverse: 0.4.1 1862 | uri-js: 4.4.1 1863 | 1864 | ansi-regex@5.0.1: {} 1865 | 1866 | ansi-regex@6.1.0: {} 1867 | 1868 | ansi-styles@4.3.0: 1869 | dependencies: 1870 | color-convert: 2.0.1 1871 | 1872 | ansi-styles@6.2.1: {} 1873 | 1874 | argparse@2.0.1: {} 1875 | 1876 | assertion-error@2.0.1: {} 1877 | 1878 | ast-v8-to-istanbul@0.3.3: 1879 | dependencies: 1880 | '@jridgewell/trace-mapping': 0.3.25 1881 | estree-walker: 3.0.3 1882 | js-tokens: 9.0.1 1883 | 1884 | balanced-match@1.0.2: {} 1885 | 1886 | brace-expansion@1.1.11: 1887 | dependencies: 1888 | balanced-match: 1.0.2 1889 | concat-map: 0.0.1 1890 | 1891 | brace-expansion@2.0.1: 1892 | dependencies: 1893 | balanced-match: 1.0.2 1894 | 1895 | braces@3.0.3: 1896 | dependencies: 1897 | fill-range: 7.1.1 1898 | 1899 | cac@6.7.14: {} 1900 | 1901 | callsites@3.1.0: {} 1902 | 1903 | chai@5.2.0: 1904 | dependencies: 1905 | assertion-error: 2.0.1 1906 | check-error: 2.1.1 1907 | deep-eql: 5.0.2 1908 | loupe: 3.1.3 1909 | pathval: 2.0.0 1910 | 1911 | chalk@4.1.2: 1912 | dependencies: 1913 | ansi-styles: 4.3.0 1914 | supports-color: 7.2.0 1915 | 1916 | check-error@2.1.1: {} 1917 | 1918 | color-convert@2.0.1: 1919 | dependencies: 1920 | color-name: 1.1.4 1921 | 1922 | color-name@1.1.4: {} 1923 | 1924 | concat-map@0.0.1: {} 1925 | 1926 | cross-spawn@7.0.6: 1927 | dependencies: 1928 | path-key: 3.1.1 1929 | shebang-command: 2.0.0 1930 | which: 2.0.2 1931 | 1932 | debug@4.4.1: 1933 | dependencies: 1934 | ms: 2.1.3 1935 | 1936 | deep-eql@5.0.2: {} 1937 | 1938 | deep-is@0.1.4: {} 1939 | 1940 | eastasianwidth@0.2.0: {} 1941 | 1942 | emoji-regex@8.0.0: {} 1943 | 1944 | emoji-regex@9.2.2: {} 1945 | 1946 | es-module-lexer@1.7.0: {} 1947 | 1948 | esbuild@0.25.5: 1949 | optionalDependencies: 1950 | '@esbuild/aix-ppc64': 0.25.5 1951 | '@esbuild/android-arm': 0.25.5 1952 | '@esbuild/android-arm64': 0.25.5 1953 | '@esbuild/android-x64': 0.25.5 1954 | '@esbuild/darwin-arm64': 0.25.5 1955 | '@esbuild/darwin-x64': 0.25.5 1956 | '@esbuild/freebsd-arm64': 0.25.5 1957 | '@esbuild/freebsd-x64': 0.25.5 1958 | '@esbuild/linux-arm': 0.25.5 1959 | '@esbuild/linux-arm64': 0.25.5 1960 | '@esbuild/linux-ia32': 0.25.5 1961 | '@esbuild/linux-loong64': 0.25.5 1962 | '@esbuild/linux-mips64el': 0.25.5 1963 | '@esbuild/linux-ppc64': 0.25.5 1964 | '@esbuild/linux-riscv64': 0.25.5 1965 | '@esbuild/linux-s390x': 0.25.5 1966 | '@esbuild/linux-x64': 0.25.5 1967 | '@esbuild/netbsd-arm64': 0.25.5 1968 | '@esbuild/netbsd-x64': 0.25.5 1969 | '@esbuild/openbsd-arm64': 0.25.5 1970 | '@esbuild/openbsd-x64': 0.25.5 1971 | '@esbuild/sunos-x64': 0.25.5 1972 | '@esbuild/win32-arm64': 0.25.5 1973 | '@esbuild/win32-ia32': 0.25.5 1974 | '@esbuild/win32-x64': 0.25.5 1975 | 1976 | escape-string-regexp@4.0.0: {} 1977 | 1978 | eslint-config-prettier@10.1.5(eslint@9.28.0): 1979 | dependencies: 1980 | eslint: 9.28.0 1981 | 1982 | eslint-plugin-eslint-plugin@6.4.0(eslint@9.28.0): 1983 | dependencies: 1984 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) 1985 | eslint: 9.28.0 1986 | estraverse: 5.3.0 1987 | 1988 | eslint-scope@8.3.0: 1989 | dependencies: 1990 | esrecurse: 4.3.0 1991 | estraverse: 5.3.0 1992 | 1993 | eslint-visitor-keys@3.4.3: {} 1994 | 1995 | eslint-visitor-keys@4.2.0: {} 1996 | 1997 | eslint@9.28.0: 1998 | dependencies: 1999 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) 2000 | '@eslint-community/regexpp': 4.12.1 2001 | '@eslint/config-array': 0.20.0 2002 | '@eslint/config-helpers': 0.2.2 2003 | '@eslint/core': 0.14.0 2004 | '@eslint/eslintrc': 3.3.1 2005 | '@eslint/js': 9.28.0 2006 | '@eslint/plugin-kit': 0.3.1 2007 | '@humanfs/node': 0.16.6 2008 | '@humanwhocodes/module-importer': 1.0.1 2009 | '@humanwhocodes/retry': 0.4.3 2010 | '@types/estree': 1.0.8 2011 | '@types/json-schema': 7.0.15 2012 | ajv: 6.12.6 2013 | chalk: 4.1.2 2014 | cross-spawn: 7.0.6 2015 | debug: 4.4.1 2016 | escape-string-regexp: 4.0.0 2017 | eslint-scope: 8.3.0 2018 | eslint-visitor-keys: 4.2.0 2019 | espree: 10.3.0 2020 | esquery: 1.6.0 2021 | esutils: 2.0.3 2022 | fast-deep-equal: 3.1.3 2023 | file-entry-cache: 8.0.0 2024 | find-up: 5.0.0 2025 | glob-parent: 6.0.2 2026 | ignore: 5.3.2 2027 | imurmurhash: 0.1.4 2028 | is-glob: 4.0.3 2029 | json-stable-stringify-without-jsonify: 1.0.1 2030 | lodash.merge: 4.6.2 2031 | minimatch: 3.1.2 2032 | natural-compare: 1.4.0 2033 | optionator: 0.9.4 2034 | transitivePeerDependencies: 2035 | - supports-color 2036 | 2037 | espree@10.3.0: 2038 | dependencies: 2039 | acorn: 8.14.1 2040 | acorn-jsx: 5.3.2(acorn@8.14.1) 2041 | eslint-visitor-keys: 4.2.0 2042 | 2043 | esquery@1.6.0: 2044 | dependencies: 2045 | estraverse: 5.3.0 2046 | 2047 | esrecurse@4.3.0: 2048 | dependencies: 2049 | estraverse: 5.3.0 2050 | 2051 | estraverse@5.3.0: {} 2052 | 2053 | estree-walker@3.0.3: 2054 | dependencies: 2055 | '@types/estree': 1.0.8 2056 | 2057 | esutils@2.0.3: {} 2058 | 2059 | expect-type@1.2.1: {} 2060 | 2061 | fast-deep-equal@3.1.3: {} 2062 | 2063 | fast-glob@3.3.3: 2064 | dependencies: 2065 | '@nodelib/fs.stat': 2.0.5 2066 | '@nodelib/fs.walk': 1.2.8 2067 | glob-parent: 5.1.2 2068 | merge2: 1.4.1 2069 | micromatch: 4.0.8 2070 | 2071 | fast-json-stable-stringify@2.1.0: {} 2072 | 2073 | fast-levenshtein@2.0.6: {} 2074 | 2075 | fastq@1.19.1: 2076 | dependencies: 2077 | reusify: 1.1.0 2078 | 2079 | fdir@6.4.5(picomatch@4.0.2): 2080 | optionalDependencies: 2081 | picomatch: 4.0.2 2082 | 2083 | file-entry-cache@8.0.0: 2084 | dependencies: 2085 | flat-cache: 4.0.1 2086 | 2087 | fill-range@7.1.1: 2088 | dependencies: 2089 | to-regex-range: 5.0.1 2090 | 2091 | find-up@5.0.0: 2092 | dependencies: 2093 | locate-path: 6.0.0 2094 | path-exists: 4.0.0 2095 | 2096 | flat-cache@4.0.1: 2097 | dependencies: 2098 | flatted: 3.3.3 2099 | keyv: 4.5.4 2100 | 2101 | flatted@3.3.3: {} 2102 | 2103 | foreground-child@3.3.1: 2104 | dependencies: 2105 | cross-spawn: 7.0.6 2106 | signal-exit: 4.1.0 2107 | 2108 | fsevents@2.3.3: 2109 | optional: true 2110 | 2111 | glob-parent@5.1.2: 2112 | dependencies: 2113 | is-glob: 4.0.3 2114 | 2115 | glob-parent@6.0.2: 2116 | dependencies: 2117 | is-glob: 4.0.3 2118 | 2119 | glob@10.4.5: 2120 | dependencies: 2121 | foreground-child: 3.3.1 2122 | jackspeak: 3.4.3 2123 | minimatch: 9.0.5 2124 | minipass: 7.1.2 2125 | package-json-from-dist: 1.0.1 2126 | path-scurry: 1.11.1 2127 | 2128 | glob@11.0.2: 2129 | dependencies: 2130 | foreground-child: 3.3.1 2131 | jackspeak: 4.1.1 2132 | minimatch: 10.0.1 2133 | minipass: 7.1.2 2134 | package-json-from-dist: 1.0.1 2135 | path-scurry: 2.0.0 2136 | 2137 | globals@14.0.0: {} 2138 | 2139 | globals@16.2.0: {} 2140 | 2141 | graphemer@1.4.0: {} 2142 | 2143 | has-flag@4.0.0: {} 2144 | 2145 | html-escaper@2.0.2: {} 2146 | 2147 | ignore@5.3.2: {} 2148 | 2149 | ignore@7.0.5: {} 2150 | 2151 | import-fresh@3.3.1: 2152 | dependencies: 2153 | parent-module: 1.0.1 2154 | resolve-from: 4.0.0 2155 | 2156 | imurmurhash@0.1.4: {} 2157 | 2158 | is-extglob@2.1.1: {} 2159 | 2160 | is-fullwidth-code-point@3.0.0: {} 2161 | 2162 | is-glob@4.0.3: 2163 | dependencies: 2164 | is-extglob: 2.1.1 2165 | 2166 | is-number@7.0.0: {} 2167 | 2168 | isexe@2.0.0: {} 2169 | 2170 | isexe@3.1.1: {} 2171 | 2172 | istanbul-lib-coverage@3.2.2: {} 2173 | 2174 | istanbul-lib-report@3.0.1: 2175 | dependencies: 2176 | istanbul-lib-coverage: 3.2.2 2177 | make-dir: 4.0.0 2178 | supports-color: 7.2.0 2179 | 2180 | istanbul-lib-source-maps@5.0.6: 2181 | dependencies: 2182 | '@jridgewell/trace-mapping': 0.3.25 2183 | debug: 4.4.1 2184 | istanbul-lib-coverage: 3.2.2 2185 | transitivePeerDependencies: 2186 | - supports-color 2187 | 2188 | istanbul-reports@3.1.7: 2189 | dependencies: 2190 | html-escaper: 2.0.2 2191 | istanbul-lib-report: 3.0.1 2192 | 2193 | jackspeak@3.4.3: 2194 | dependencies: 2195 | '@isaacs/cliui': 8.0.2 2196 | optionalDependencies: 2197 | '@pkgjs/parseargs': 0.11.0 2198 | 2199 | jackspeak@4.1.1: 2200 | dependencies: 2201 | '@isaacs/cliui': 8.0.2 2202 | 2203 | js-tokens@9.0.1: {} 2204 | 2205 | js-yaml@4.1.0: 2206 | dependencies: 2207 | argparse: 2.0.1 2208 | 2209 | json-buffer@3.0.1: {} 2210 | 2211 | json-parse-even-better-errors@4.0.0: {} 2212 | 2213 | json-schema-traverse@0.4.1: {} 2214 | 2215 | json-stable-stringify-without-jsonify@1.0.1: {} 2216 | 2217 | keyv@4.5.4: 2218 | dependencies: 2219 | json-buffer: 3.0.1 2220 | 2221 | levn@0.4.1: 2222 | dependencies: 2223 | prelude-ls: 1.2.1 2224 | type-check: 0.4.0 2225 | 2226 | locate-path@6.0.0: 2227 | dependencies: 2228 | p-locate: 5.0.0 2229 | 2230 | lodash.merge@4.6.2: {} 2231 | 2232 | loupe@3.1.3: {} 2233 | 2234 | lru-cache@10.4.3: {} 2235 | 2236 | lru-cache@11.1.0: {} 2237 | 2238 | magic-string@0.30.17: 2239 | dependencies: 2240 | '@jridgewell/sourcemap-codec': 1.5.0 2241 | 2242 | magicast@0.3.5: 2243 | dependencies: 2244 | '@babel/parser': 7.27.5 2245 | '@babel/types': 7.27.6 2246 | source-map-js: 1.2.1 2247 | 2248 | make-dir@4.0.0: 2249 | dependencies: 2250 | semver: 7.7.2 2251 | 2252 | memorystream@0.3.1: {} 2253 | 2254 | merge2@1.4.1: {} 2255 | 2256 | micromatch@4.0.8: 2257 | dependencies: 2258 | braces: 3.0.3 2259 | picomatch: 2.3.1 2260 | 2261 | minimatch@10.0.1: 2262 | dependencies: 2263 | brace-expansion: 2.0.1 2264 | 2265 | minimatch@3.1.2: 2266 | dependencies: 2267 | brace-expansion: 1.1.11 2268 | 2269 | minimatch@9.0.5: 2270 | dependencies: 2271 | brace-expansion: 2.0.1 2272 | 2273 | minipass@7.1.2: {} 2274 | 2275 | ms@2.1.3: {} 2276 | 2277 | nanoid@3.3.11: {} 2278 | 2279 | natural-compare@1.4.0: {} 2280 | 2281 | npm-normalize-package-bin@4.0.0: {} 2282 | 2283 | npm-run-all2@8.0.4: 2284 | dependencies: 2285 | ansi-styles: 6.2.1 2286 | cross-spawn: 7.0.6 2287 | memorystream: 0.3.1 2288 | picomatch: 4.0.2 2289 | pidtree: 0.6.0 2290 | read-package-json-fast: 4.0.0 2291 | shell-quote: 1.8.3 2292 | which: 5.0.0 2293 | 2294 | optionator@0.9.4: 2295 | dependencies: 2296 | deep-is: 0.1.4 2297 | fast-levenshtein: 2.0.6 2298 | levn: 0.4.1 2299 | prelude-ls: 1.2.1 2300 | type-check: 0.4.0 2301 | word-wrap: 1.2.5 2302 | 2303 | p-limit@3.1.0: 2304 | dependencies: 2305 | yocto-queue: 0.1.0 2306 | 2307 | p-locate@5.0.0: 2308 | dependencies: 2309 | p-limit: 3.1.0 2310 | 2311 | package-json-from-dist@1.0.1: {} 2312 | 2313 | parent-module@1.0.1: 2314 | dependencies: 2315 | callsites: 3.1.0 2316 | 2317 | path-exists@4.0.0: {} 2318 | 2319 | path-key@3.1.1: {} 2320 | 2321 | path-scurry@1.11.1: 2322 | dependencies: 2323 | lru-cache: 10.4.3 2324 | minipass: 7.1.2 2325 | 2326 | path-scurry@2.0.0: 2327 | dependencies: 2328 | lru-cache: 11.1.0 2329 | minipass: 7.1.2 2330 | 2331 | pathe@2.0.3: {} 2332 | 2333 | pathval@2.0.0: {} 2334 | 2335 | picocolors@1.1.1: {} 2336 | 2337 | picomatch@2.3.1: {} 2338 | 2339 | picomatch@4.0.2: {} 2340 | 2341 | pidtree@0.6.0: {} 2342 | 2343 | postcss@8.5.4: 2344 | dependencies: 2345 | nanoid: 3.3.11 2346 | picocolors: 1.1.1 2347 | source-map-js: 1.2.1 2348 | 2349 | prelude-ls@1.2.1: {} 2350 | 2351 | prettier@3.5.3: {} 2352 | 2353 | punycode@2.3.1: {} 2354 | 2355 | queue-microtask@1.2.3: {} 2356 | 2357 | read-package-json-fast@4.0.0: 2358 | dependencies: 2359 | json-parse-even-better-errors: 4.0.0 2360 | npm-normalize-package-bin: 4.0.0 2361 | 2362 | resolve-from@4.0.0: {} 2363 | 2364 | reusify@1.1.0: {} 2365 | 2366 | rimraf@6.0.1: 2367 | dependencies: 2368 | glob: 11.0.2 2369 | package-json-from-dist: 1.0.1 2370 | 2371 | rollup@4.42.0: 2372 | dependencies: 2373 | '@types/estree': 1.0.7 2374 | optionalDependencies: 2375 | '@rollup/rollup-android-arm-eabi': 4.42.0 2376 | '@rollup/rollup-android-arm64': 4.42.0 2377 | '@rollup/rollup-darwin-arm64': 4.42.0 2378 | '@rollup/rollup-darwin-x64': 4.42.0 2379 | '@rollup/rollup-freebsd-arm64': 4.42.0 2380 | '@rollup/rollup-freebsd-x64': 4.42.0 2381 | '@rollup/rollup-linux-arm-gnueabihf': 4.42.0 2382 | '@rollup/rollup-linux-arm-musleabihf': 4.42.0 2383 | '@rollup/rollup-linux-arm64-gnu': 4.42.0 2384 | '@rollup/rollup-linux-arm64-musl': 4.42.0 2385 | '@rollup/rollup-linux-loongarch64-gnu': 4.42.0 2386 | '@rollup/rollup-linux-powerpc64le-gnu': 4.42.0 2387 | '@rollup/rollup-linux-riscv64-gnu': 4.42.0 2388 | '@rollup/rollup-linux-riscv64-musl': 4.42.0 2389 | '@rollup/rollup-linux-s390x-gnu': 4.42.0 2390 | '@rollup/rollup-linux-x64-gnu': 4.42.0 2391 | '@rollup/rollup-linux-x64-musl': 4.42.0 2392 | '@rollup/rollup-win32-arm64-msvc': 4.42.0 2393 | '@rollup/rollup-win32-ia32-msvc': 4.42.0 2394 | '@rollup/rollup-win32-x64-msvc': 4.42.0 2395 | fsevents: 2.3.3 2396 | 2397 | run-parallel@1.2.0: 2398 | dependencies: 2399 | queue-microtask: 1.2.3 2400 | 2401 | semver@7.7.2: {} 2402 | 2403 | shebang-command@2.0.0: 2404 | dependencies: 2405 | shebang-regex: 3.0.0 2406 | 2407 | shebang-regex@3.0.0: {} 2408 | 2409 | shell-quote@1.8.3: {} 2410 | 2411 | siginfo@2.0.0: {} 2412 | 2413 | signal-exit@4.1.0: {} 2414 | 2415 | source-map-js@1.2.1: {} 2416 | 2417 | stackback@0.0.2: {} 2418 | 2419 | std-env@3.9.0: {} 2420 | 2421 | string-width@4.2.3: 2422 | dependencies: 2423 | emoji-regex: 8.0.0 2424 | is-fullwidth-code-point: 3.0.0 2425 | strip-ansi: 6.0.1 2426 | 2427 | string-width@5.1.2: 2428 | dependencies: 2429 | eastasianwidth: 0.2.0 2430 | emoji-regex: 9.2.2 2431 | strip-ansi: 7.1.0 2432 | 2433 | strip-ansi@6.0.1: 2434 | dependencies: 2435 | ansi-regex: 5.0.1 2436 | 2437 | strip-ansi@7.1.0: 2438 | dependencies: 2439 | ansi-regex: 6.1.0 2440 | 2441 | strip-json-comments@3.1.1: {} 2442 | 2443 | supports-color@7.2.0: 2444 | dependencies: 2445 | has-flag: 4.0.0 2446 | 2447 | test-exclude@7.0.1: 2448 | dependencies: 2449 | '@istanbuljs/schema': 0.1.3 2450 | glob: 10.4.5 2451 | minimatch: 9.0.5 2452 | 2453 | tinybench@2.9.0: {} 2454 | 2455 | tinyexec@0.3.2: {} 2456 | 2457 | tinyglobby@0.2.14: 2458 | dependencies: 2459 | fdir: 6.4.5(picomatch@4.0.2) 2460 | picomatch: 4.0.2 2461 | 2462 | tinypool@1.1.0: {} 2463 | 2464 | tinyrainbow@2.0.0: {} 2465 | 2466 | tinyspy@4.0.3: {} 2467 | 2468 | to-regex-range@5.0.1: 2469 | dependencies: 2470 | is-number: 7.0.0 2471 | 2472 | ts-api-utils@2.1.0(typescript@5.8.3): 2473 | dependencies: 2474 | typescript: 5.8.3 2475 | 2476 | type-check@0.4.0: 2477 | dependencies: 2478 | prelude-ls: 1.2.1 2479 | 2480 | typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3): 2481 | dependencies: 2482 | '@typescript-eslint/eslint-plugin': 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3) 2483 | '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 2484 | '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) 2485 | eslint: 9.28.0 2486 | typescript: 5.8.3 2487 | transitivePeerDependencies: 2488 | - supports-color 2489 | 2490 | typescript@5.8.3: {} 2491 | 2492 | undici-types@6.21.0: {} 2493 | 2494 | uri-js@4.4.1: 2495 | dependencies: 2496 | punycode: 2.3.1 2497 | 2498 | vite-node@3.2.2(@types/node@22.15.30)(yaml@2.5.1): 2499 | dependencies: 2500 | cac: 6.7.14 2501 | debug: 4.4.1 2502 | es-module-lexer: 1.7.0 2503 | pathe: 2.0.3 2504 | vite: 6.3.5(@types/node@22.15.30)(yaml@2.5.1) 2505 | transitivePeerDependencies: 2506 | - '@types/node' 2507 | - jiti 2508 | - less 2509 | - lightningcss 2510 | - sass 2511 | - sass-embedded 2512 | - stylus 2513 | - sugarss 2514 | - supports-color 2515 | - terser 2516 | - tsx 2517 | - yaml 2518 | 2519 | vite@6.3.5(@types/node@22.15.30)(yaml@2.5.1): 2520 | dependencies: 2521 | esbuild: 0.25.5 2522 | fdir: 6.4.5(picomatch@4.0.2) 2523 | picomatch: 4.0.2 2524 | postcss: 8.5.4 2525 | rollup: 4.42.0 2526 | tinyglobby: 0.2.14 2527 | optionalDependencies: 2528 | '@types/node': 22.15.30 2529 | fsevents: 2.3.3 2530 | yaml: 2.5.1 2531 | 2532 | vitest@3.2.2(@types/node@22.15.30)(yaml@2.5.1): 2533 | dependencies: 2534 | '@types/chai': 5.2.2 2535 | '@vitest/expect': 3.2.2 2536 | '@vitest/mocker': 3.2.2(vite@6.3.5(@types/node@22.15.30)(yaml@2.5.1)) 2537 | '@vitest/pretty-format': 3.2.2 2538 | '@vitest/runner': 3.2.2 2539 | '@vitest/snapshot': 3.2.2 2540 | '@vitest/spy': 3.2.2 2541 | '@vitest/utils': 3.2.2 2542 | chai: 5.2.0 2543 | debug: 4.4.1 2544 | expect-type: 1.2.1 2545 | magic-string: 0.30.17 2546 | pathe: 2.0.3 2547 | picomatch: 4.0.2 2548 | std-env: 3.9.0 2549 | tinybench: 2.9.0 2550 | tinyexec: 0.3.2 2551 | tinyglobby: 0.2.14 2552 | tinypool: 1.1.0 2553 | tinyrainbow: 2.0.0 2554 | vite: 6.3.5(@types/node@22.15.30)(yaml@2.5.1) 2555 | vite-node: 3.2.2(@types/node@22.15.30)(yaml@2.5.1) 2556 | why-is-node-running: 2.3.0 2557 | optionalDependencies: 2558 | '@types/node': 22.15.30 2559 | transitivePeerDependencies: 2560 | - jiti 2561 | - less 2562 | - lightningcss 2563 | - msw 2564 | - sass 2565 | - sass-embedded 2566 | - stylus 2567 | - sugarss 2568 | - supports-color 2569 | - terser 2570 | - tsx 2571 | - yaml 2572 | 2573 | which@2.0.2: 2574 | dependencies: 2575 | isexe: 2.0.0 2576 | 2577 | which@5.0.0: 2578 | dependencies: 2579 | isexe: 3.1.1 2580 | 2581 | why-is-node-running@2.3.0: 2582 | dependencies: 2583 | siginfo: 2.0.0 2584 | stackback: 0.0.2 2585 | 2586 | word-wrap@1.2.5: {} 2587 | 2588 | wrap-ansi@7.0.0: 2589 | dependencies: 2590 | ansi-styles: 4.3.0 2591 | string-width: 4.2.3 2592 | strip-ansi: 6.0.1 2593 | 2594 | wrap-ansi@8.1.0: 2595 | dependencies: 2596 | ansi-styles: 6.2.1 2597 | string-width: 5.1.2 2598 | strip-ansi: 7.1.0 2599 | 2600 | yaml@2.5.1: 2601 | optional: true 2602 | 2603 | yocto-queue@0.1.0: {} 2604 | -------------------------------------------------------------------------------- /src/configs/index.ts: -------------------------------------------------------------------------------- 1 | import type { ESLint } from "eslint"; 2 | import recommended from "./recommended.js"; 3 | 4 | const configs = { 5 | recommended, 6 | } satisfies ESLint.Plugin["configs"]; 7 | 8 | export default configs; 9 | -------------------------------------------------------------------------------- /src/configs/recommended.ts: -------------------------------------------------------------------------------- 1 | import type { ESLint, Linter } from "eslint"; 2 | 3 | const config: ESLint.ConfigData & Linter.Config = { 4 | name: "@susisu/safe-typescript/recommended", 5 | rules: { 6 | "@susisu/safe-typescript/no-object-assign-mutation": "error", 7 | "@susisu/safe-typescript/no-type-assertion": "error", 8 | "@susisu/safe-typescript/no-unsafe-object-enum-method": "error", 9 | "@susisu/safe-typescript/no-unsafe-object-property-check": "error", 10 | "@susisu/safe-typescript/no-unsafe-object-property-overwrite": "error", 11 | }, 12 | }; 13 | 14 | export default config; 15 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { ESLint } from "eslint"; 2 | import rules from "./rules/index.js"; 3 | import configs from "./configs/index.js"; 4 | 5 | const plugin = { 6 | rules, 7 | configs, 8 | } satisfies ESLint.Plugin; 9 | 10 | export default plugin; 11 | -------------------------------------------------------------------------------- /src/rules/__tests__/fixtures/file.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susisu/eslint-plugin-safe-typescript/a5dea5ab71ed27960943812cf4096b077cf0cc1e/src/rules/__tests__/fixtures/file.ts -------------------------------------------------------------------------------- /src/rules/__tests__/fixtures/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "esModuleInterop": true, 6 | "lib": ["esnext"], 7 | "jsx": "react-jsx", 8 | "strict": true 9 | }, 10 | "include": [ 11 | "file.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/rules/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | 3 | export function getFixturesDir(): string { 4 | return path.join(__dirname, "fixtures"); 5 | } 6 | -------------------------------------------------------------------------------- /src/rules/index.ts: -------------------------------------------------------------------------------- 1 | import type { ESLint, Rule } from "eslint"; 2 | import noObjectAssign from "./no-object-assign/index.js"; 3 | import noObjectAssignMutation from "./no-object-assign-mutation/index.js"; 4 | import noTypeAssertion from "./no-type-assertion/index.js"; 5 | import noUnsafeObjectEnumMethod from "./no-unsafe-object-enum-method/index.js"; 6 | import noUnsafeObjectPropertyCheck from "./no-unsafe-object-property-check/index.js"; 7 | import noUnsafeObjectPropertyOverwrite from "./no-unsafe-object-property-overwrite/index.js"; 8 | 9 | function asRuleModule(rule: unknown): Rule.RuleModule { 10 | // eslint-disable-next-line @susisu/safe-typescript/no-type-assertion 11 | return rule as Rule.RuleModule; 12 | } 13 | 14 | const rules = { 15 | "no-object-assign": asRuleModule(noObjectAssign), 16 | "no-object-assign-mutation": asRuleModule(noObjectAssignMutation), 17 | "no-type-assertion": asRuleModule(noTypeAssertion), 18 | "no-unsafe-object-enum-method": asRuleModule(noUnsafeObjectEnumMethod), 19 | "no-unsafe-object-property-check": asRuleModule(noUnsafeObjectPropertyCheck), 20 | "no-unsafe-object-property-overwrite": asRuleModule(noUnsafeObjectPropertyOverwrite), 21 | } satisfies ESLint.Plugin["rules"]; 22 | 23 | export default rules; 24 | -------------------------------------------------------------------------------- /src/rules/no-object-assign-mutation/README.md: -------------------------------------------------------------------------------- 1 | # `no-object-assign-mutation` 2 | 3 | Disallow mutations using `Object.assign()`. 4 | 5 | One possible use case of [`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) is to mutate an object by assigning properties. 6 | 7 | However, mutations using `Object.assign()` is possibly unsafe, because it mutates the object without knowing its type. 8 | For example, it may mutate properties that are marked as `readonly`, or internal properties that are not exposed. 9 | 10 | ## Examples 11 | 12 | 👎 Examples of incorrect code for this rule: 13 | 14 | ```ts 15 | Object.assign(x, y); 16 | ``` 17 | 18 | 👍 Examples of correct code for this rule: 19 | 20 | ```ts 21 | Object.assign({}, x); 22 | Object.assign(x); 23 | ``` 24 | 25 | Although the above code is correct, [the object spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) is always a better choice. 26 | You can enable [`prefer-object-spread`](https://eslint.org/docs/latest/rules/prefer-object-spread) to enforce the object spread syntax. 27 | 28 | ## When Not To Use It 29 | 30 | If you really want to mutate an object, disable this rule. 31 | -------------------------------------------------------------------------------- /src/rules/no-object-assign-mutation/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import rule from "./index.js"; 3 | 4 | const ruleTester = new RuleTester(); 5 | 6 | ruleTester.run("no-object-assign-mutation", rule, { 7 | valid: [`Object.assign`, `Object.assign({}, x)`, `Object.assign(x)`], 8 | invalid: [ 9 | { 10 | code: `Object.assign(x, y)`, 11 | errors: [ 12 | { 13 | messageId: "noMutation", 14 | line: 1, 15 | column: 1, 16 | }, 17 | ], 18 | }, 19 | ], 20 | }); 21 | -------------------------------------------------------------------------------- /src/rules/no-object-assign-mutation/index.ts: -------------------------------------------------------------------------------- 1 | import { AST_NODE_TYPES } from "@typescript-eslint/utils"; 2 | import { createRule, matchObjectMethodCall } from "../utils.js"; 3 | 4 | type Options = []; 5 | 6 | type MessageIds = "noMutation"; 7 | 8 | const rule = createRule({ 9 | name: "no-object-assign-mutation", 10 | meta: { 11 | type: "suggestion", 12 | docs: { 13 | description: "Disallow mutations using Object.assign()", 14 | }, 15 | messages: { 16 | noMutation: "Object.assign() mutates the first argument without knowing its type.", 17 | }, 18 | schema: [], 19 | }, 20 | defaultOptions: [], 21 | create: (context) => ({ 22 | CallExpression: (node) => { 23 | const method = matchObjectMethodCall(node); 24 | if (method !== "assign") { 25 | return; 26 | } 27 | if ( 28 | node.arguments.length >= 2 29 | && node.arguments[0].type !== AST_NODE_TYPES.ObjectExpression 30 | ) { 31 | context.report({ 32 | node, 33 | messageId: "noMutation", 34 | }); 35 | } 36 | }, 37 | }), 38 | }); 39 | 40 | export default rule; 41 | -------------------------------------------------------------------------------- /src/rules/no-object-assign/README.md: -------------------------------------------------------------------------------- 1 | # `no-object-assign` 2 | 3 | Disallow the use of `Object.assign()`. 4 | 5 | The possible usage of the [`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) method will be one of the following cases: 6 | 7 | 1. To copy an object. 8 | 2. To mutate an object by assigning properties. 9 | 10 | For the first case, [the object spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) is always the better choice. 11 | 12 | For the second case, it is possibly unsafe because `Object.assign()` mutates the object without knowing its type. 13 | For example, it may mutate properties that are marked as `readonly`, or internal properties that should not be exposed. 14 | 15 | ## Examples 16 | 17 | 👎 Examples of incorrect code for this rule: 18 | 19 | ```ts 20 | Object.assign({}, x); 21 | Object.assign(x, y); 22 | ``` 23 | 24 | 👍 Examples of correct code for this rule: 25 | 26 | ```ts 27 | Object.assign; 28 | ``` 29 | 30 | ## When Not To Use It 31 | 32 | If you really want to mutate an object, disable this rule. 33 | -------------------------------------------------------------------------------- /src/rules/no-object-assign/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import rule from "./index.js"; 3 | 4 | const ruleTester = new RuleTester(); 5 | 6 | ruleTester.run("no-object-assign", rule, { 7 | valid: [`Object.assign`], 8 | invalid: [ 9 | { 10 | code: `Object.assign({}, x)`, 11 | errors: [ 12 | { 13 | messageId: "noCopying", 14 | line: 1, 15 | column: 1, 16 | }, 17 | ], 18 | }, 19 | { 20 | code: `Object.assign(x)`, 21 | errors: [ 22 | { 23 | messageId: "noMutation", 24 | line: 1, 25 | column: 1, 26 | }, 27 | ], 28 | }, 29 | { 30 | code: `Object.assign(x, y)`, 31 | errors: [ 32 | { 33 | messageId: "noMutation", 34 | line: 1, 35 | column: 1, 36 | }, 37 | ], 38 | }, 39 | ], 40 | }); 41 | -------------------------------------------------------------------------------- /src/rules/no-object-assign/index.ts: -------------------------------------------------------------------------------- 1 | import { AST_NODE_TYPES } from "@typescript-eslint/utils"; 2 | import { createRule, matchObjectMethodCall } from "../utils.js"; 3 | 4 | type Options = []; 5 | 6 | type MessageIds = "noCopying" | "noMutation"; 7 | 8 | const rule = createRule({ 9 | name: "no-object-assign", 10 | meta: { 11 | deprecated: true, 12 | type: "suggestion", 13 | docs: { 14 | description: "Disallow the use of Object.assign()", 15 | }, 16 | messages: { 17 | noCopying: 18 | "Using Object.assign() to copy objects is not recommended. Use the object spread syntax instead.", 19 | noMutation: "Object.assign() mutates the first argument without knowing its type.", 20 | }, 21 | schema: [], 22 | }, 23 | defaultOptions: [], 24 | create: (context) => ({ 25 | CallExpression: (node) => { 26 | const method = matchObjectMethodCall(node); 27 | if (method !== "assign") { 28 | return; 29 | } 30 | if (node.arguments.length > 0 && node.arguments[0].type === AST_NODE_TYPES.ObjectExpression) { 31 | context.report({ 32 | node, 33 | messageId: "noCopying", 34 | }); 35 | } else { 36 | context.report({ 37 | node, 38 | messageId: "noMutation", 39 | }); 40 | } 41 | }, 42 | }), 43 | }); 44 | 45 | export default rule; 46 | -------------------------------------------------------------------------------- /src/rules/no-type-assertion/README.md: -------------------------------------------------------------------------------- 1 | # `no-type-assertion` 2 | 3 | Disallow type assertions like `x as T` and `x`. 4 | 5 | Because downcasting is allowed, type assertions are possibly unsafe. 6 | 7 | ```ts 8 | const obj = { foo: 42 } as { foo: number; bar: number }; 9 | obj.bar.toString(); // runtime error! 10 | ``` 11 | 12 | Although upcasting is still safe, you basically don't need to write type assertions for such cases. 13 | 14 | ## Examples 15 | 16 | 👎 Examples of incorrect code for this rule: 17 | 18 | ```ts 19 | const a = { foo: 42 } as { foo: number; bar: number }; 20 | const b = { foo: 42 } as never; 21 | // The following expressions are actually safe, but reported as incorrect. 22 | const c = { foo: 42 } as { foo: number }; 23 | const d = { foo: 42 } as {}; 24 | ``` 25 | 26 | ```ts 27 | const a = <{ foo: number; bar: number }>{ foo: 42 }; 28 | const b = { foo: 42 }; 29 | const c = <{ foo: number }>{ foo: 42 }; 30 | const d = <{}>{ foo: 42 }; 31 | ``` 32 | 33 | 👍 Examples of correct code for this rule: 34 | 35 | ```ts 36 | // `as const` is a special expression, and it's safe 37 | const x = { foo: 42 } as const; 38 | // `as unknown` is safe 39 | const y = { foo: 42 } as unknown; 40 | // `as any` is unsafe, but that is because of `any`, not `as` 41 | const z = { foo: 42 } as any; 42 | ``` 43 | 44 | ```ts 45 | const x = { foo: 42 }; 46 | const y = { foo: 42 }; 47 | const z = { foo: 42 }; 48 | ``` 49 | 50 | ## When Not To Use It 51 | 52 | If you use type assertions to avoid type checking intentionally, you may disable this rule. 53 | -------------------------------------------------------------------------------- /src/rules/no-type-assertion/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import rule from "./index.js"; 3 | 4 | const ruleTester = new RuleTester(); 5 | 6 | ruleTester.run("no-type-assertion", rule, { 7 | valid: [ 8 | `const x = { foo: 42 } as const`, 9 | `const x = { foo: 42 } as unknown`, 10 | `const x = { foo: 42 } as any`, 11 | `const x = { foo: 42 }`, 12 | `const x = { foo: 42 }`, 13 | `const x = { foo: 42 }`, 14 | ], 15 | invalid: [ 16 | { 17 | code: `const x = { foo: 42 } as { foo: number; bar: number }`, 18 | errors: [ 19 | { 20 | messageId: "noTypeAssertion", 21 | line: 1, 22 | column: 11, 23 | }, 24 | ], 25 | }, 26 | { 27 | code: `const x = { foo: 42 } as never`, 28 | errors: [ 29 | { 30 | messageId: "noTypeAssertion", 31 | line: 1, 32 | column: 11, 33 | }, 34 | ], 35 | }, 36 | { 37 | code: `const x = { foo: 42 } as { foo: number }`, 38 | errors: [ 39 | { 40 | messageId: "noTypeAssertion", 41 | line: 1, 42 | column: 11, 43 | }, 44 | ], 45 | }, 46 | { 47 | code: `const x = { foo: 42 } as {}`, 48 | errors: [ 49 | { 50 | messageId: "noTypeAssertion", 51 | line: 1, 52 | column: 11, 53 | }, 54 | ], 55 | }, 56 | { 57 | code: `const x = <{ foo: number; bar: number }>{ foo: 42 }`, 58 | errors: [ 59 | { 60 | messageId: "noTypeAssertion", 61 | line: 1, 62 | column: 11, 63 | }, 64 | ], 65 | }, 66 | { 67 | code: `const x = { foo: 42 }`, 68 | errors: [ 69 | { 70 | messageId: "noTypeAssertion", 71 | line: 1, 72 | column: 11, 73 | }, 74 | ], 75 | }, 76 | { 77 | code: `const x = <{ foo: number }>{ foo: 42 }`, 78 | errors: [ 79 | { 80 | messageId: "noTypeAssertion", 81 | line: 1, 82 | column: 11, 83 | }, 84 | ], 85 | }, 86 | { 87 | code: `const x = <{}>{ foo: 42 }`, 88 | errors: [ 89 | { 90 | messageId: "noTypeAssertion", 91 | line: 1, 92 | column: 11, 93 | }, 94 | ], 95 | }, 96 | ], 97 | }); 98 | -------------------------------------------------------------------------------- /src/rules/no-type-assertion/index.ts: -------------------------------------------------------------------------------- 1 | import type { TSESTree } from "@typescript-eslint/utils"; 2 | import { AST_NODE_TYPES } from "@typescript-eslint/utils"; 3 | import { createRule } from "../utils.js"; 4 | 5 | type Options = []; 6 | 7 | type MessageIds = "noTypeAssertion"; 8 | 9 | const rule = createRule({ 10 | name: "no-type-assertion", 11 | meta: { 12 | type: "suggestion", 13 | docs: { 14 | description: "Disallow type assertions", 15 | }, 16 | messages: { 17 | noTypeAssertion: "A type assertion `x as T` possibly involves unsafe downcasting.", 18 | }, 19 | schema: [], 20 | }, 21 | defaultOptions: [], 22 | create: (context) => { 23 | const check = (node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion): void => { 24 | const annotation = node.typeAnnotation; 25 | // `as const` is a safe expression 26 | if ( 27 | annotation.type === AST_NODE_TYPES.TSTypeReference 28 | && annotation.typeName.type === AST_NODE_TYPES.Identifier 29 | && annotation.typeName.name === "const" 30 | ) { 31 | return; 32 | } 33 | // `as unknown` is safe 34 | // `as any` is unsafe, but that is because of `any`, not `as` 35 | if ( 36 | annotation.type === AST_NODE_TYPES.TSUnknownKeyword 37 | || annotation.type === AST_NODE_TYPES.TSAnyKeyword 38 | ) { 39 | return; 40 | } 41 | context.report({ 42 | node, 43 | messageId: "noTypeAssertion", 44 | }); 45 | }; 46 | return { 47 | TSAsExpression: (node) => { 48 | check(node); 49 | }, 50 | TSTypeAssertion: (node) => { 51 | check(node); 52 | }, 53 | }; 54 | }, 55 | }); 56 | 57 | export default rule; 58 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-enum-method/README.md: -------------------------------------------------------------------------------- 1 | # `no-unsafe-object-enum-method` 2 | 3 | Disallow possibly unsafe property enumeration methods of `Object`. 4 | 5 | [`Object.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), [`Object.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values), and [`Object.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) enumerates an object's own properties, but it may contain properties that do not appear in the object's type. 6 | 7 | Suppose we have a type `Counts` and a function that reads it. 8 | 9 | ```ts 10 | type Counts = { 11 | foo: number; 12 | bar: number; 13 | baz: number; 14 | }; 15 | 16 | function myFunc(counts: Counts): void { 17 | const keys: string[] = Object.keys(counts); 18 | const values: number[] = Object.values(counts); 19 | const entries: [string, number][] = Object.entries(counts); 20 | // ... 21 | } 22 | ``` 23 | 24 | You can call `myFunc()` with an object that has additional properties. 25 | 26 | ```ts 27 | const countsWithMetadata = { 28 | foo: 1, 29 | bar: 2, 30 | baz: 3, 31 | metadata: "xxx", 32 | }; 33 | myFunc(countsWithMetadata); 34 | ``` 35 | 36 | Then the following problems will occur: 37 | 38 | - `keys` contains `"metadata"`, but people usually don't pay attention to it. 39 | - `values` contains `"xxx"`, but it is typed as `number[]`. 40 | - `entries` contains `["metadata", "xxx"]`, but it is typed as `[string, number][]`. 41 | 42 | To avoid these problems, enumerate only known properties of the object like below: 43 | 44 | ```ts 45 | const countKeys = ["foo", "bar", "baz"] as const; 46 | type CountKey = (typeof countKeys)[number]; 47 | // The same type as before 48 | type Counts = { [K in CountKey]: number }; 49 | 50 | function myFunc(counts: Counts): void { 51 | // Use only known keys of Counts i.e. countKeys 52 | const keys = countKeys; 53 | const values = countKeys.map((key) => counts[key]); 54 | const entrie = countKeys.map((key) => [key, counts[key]]); 55 | // ... 56 | } 57 | ``` 58 | 59 | ## Examples 60 | 61 | 👎 Examples of incorrect code for this rule: 62 | 63 | ```ts 64 | declare const counts: { foo: number; bar: number; baz: number }; 65 | Object.keys(counts); 66 | Object.values(counts); 67 | Object.entries(counts); 68 | ``` 69 | 70 | 👍 Examples of correct code for this rule: 71 | 72 | ```ts 73 | declare const anyValue: any; 74 | Object.keys(anyValue); 75 | Object.values(anyValue); 76 | Object.entries(anyValue); 77 | 78 | declare const nonPrimitiveValue: object; 79 | Object.keys(nonPrimitiveValue); 80 | Object.values(nonPrimitiveValue); 81 | Object.entries(nonPrimitiveValue); 82 | 83 | declare const dictionary: { [key: string]: number }; 84 | Object.keys(dictionary); 85 | Object.values(dictionary); 86 | Object.entries(dictionary); 87 | ``` 88 | 89 | ## Options 90 | 91 | ### `allowIndexSignatures` 92 | 93 | default = `true` 94 | 95 | When set to `true`, allows `Object.keys()`, `Object.values()`, and `Object.entries()` if the object's type has [index signatures](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) like `{ [key: string]: number }`. 96 | 97 | If the type has index signatures, enumerating properties is safe in most cases. 98 | However, there are still some cases where it becomes unsafe. 99 | For example: 100 | 101 | ```ts 102 | const countsWithMetadata = { 103 | foo: 1, 104 | bar: 2, 105 | baz: 3, 106 | metadata: "xxx", 107 | }; 108 | const counts: { foo: number; bar: number; baz: number } = countsWithMetadata; 109 | const dictionary: { [key: string]: number } = counts; 110 | 111 | // keys contains "metadata" that dictionary["metadata"] !== "number" 112 | const keys: string[] = Object.keys(dictionary); 113 | // values contains "xxx" 114 | const values: number[] = Object.values(dictionary); 115 | // entries contains ["metadata", "xxx"] 116 | const entries: [string, number][] = Object.entries(dictionary); 117 | ``` 118 | 119 | 👎 Examples of incorrect code for the `{ "allowIndexSignatures": false }` option: 120 | 121 | ```ts 122 | declare const dictionary: { [key: string]: number }; 123 | Object.keys(dictionary); 124 | Object.values(dictionary); 125 | Object.entries(dictionary); 126 | ``` 127 | 128 | ## When Not To Use It 129 | 130 | If you don't care about this kind of type safety, disable this rule. 131 | 132 | If it is ensured that the argument object does not contain unknown properties i.e. all the properties appear in its type, you can safely disable this rule for that specific case. 133 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-enum-method/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import { dedent } from "@qnighy/dedent"; 3 | import { getFixturesDir } from "../__tests__/utils.js"; 4 | import rule from "./index.js"; 5 | 6 | const ruleTester = new RuleTester({ 7 | languageOptions: { 8 | parserOptions: { 9 | tsconfigRootDir: getFixturesDir(), 10 | project: "./tsconfig.json", 11 | }, 12 | }, 13 | }); 14 | 15 | ruleTester.run("no-unsafe-object-enum-method", rule, { 16 | valid: [ 17 | // OK if all the argument's properties are known 18 | `Object.keys({ a: 0, b: 1, ...{ c: 2, d: 3, ...{ e: 4, f: 5 } } })`, 19 | // OK if the argument's type is any or non-primitive 20 | dedent`\ 21 | declare const x: any; 22 | Object.keys(x); 23 | `, 24 | dedent`\ 25 | declare const x: object; 26 | Object.keys(x); 27 | `, 28 | // OK if the argument's type has index signatures 29 | dedent`\ 30 | declare const x: { [key: string]: number }; 31 | Object.keys(x); 32 | `, 33 | dedent`\ 34 | declare const x: { [key: number]: number }; 35 | Object.keys(x); 36 | `, 37 | dedent`\ 38 | declare const x: { [key: symbol]: number }; 39 | Object.keys(x); 40 | `, 41 | ], 42 | invalid: [ 43 | // Error if the argument possibly has unknown properties 44 | { 45 | code: dedent`\ 46 | declare const x: { foo: number; bar: number }; 47 | Object.keys({ a: 0, b: 1, ...{ ...x, c: 1, d: 2 } }); 48 | `, 49 | errors: [ 50 | { 51 | messageId: "noEnumMethod", 52 | data: { method: "keys" }, 53 | line: 2, 54 | column: 1, 55 | }, 56 | ], 57 | }, 58 | { 59 | // In this case, the argument's type does not have index signatures, 60 | // and thus the argument has possibly unknown properties. 61 | code: dedent`\ 62 | declare const x: { [key: string]: number }; 63 | Object.keys({ a: 0, b: 1, ...{ ...x, c: 1, d: 2 } }); 64 | `, 65 | errors: [ 66 | { 67 | messageId: "noEnumMethod", 68 | data: { method: "keys" }, 69 | line: 2, 70 | column: 1, 71 | }, 72 | ], 73 | }, 74 | // Error if the argument's type does not have index signatures 75 | { 76 | code: dedent`\ 77 | declare const x: { foo: number; bar: number }; 78 | Object.keys(x); 79 | `, 80 | errors: [ 81 | { 82 | messageId: "noEnumMethod", 83 | data: { method: "keys" }, 84 | line: 2, 85 | column: 1, 86 | }, 87 | ], 88 | }, 89 | { 90 | code: dedent`\ 91 | declare const x: { foo: number; bar: number }; 92 | Object.values(x); 93 | `, 94 | errors: [ 95 | { 96 | messageId: "noEnumMethod", 97 | data: { method: "values" }, 98 | line: 2, 99 | column: 1, 100 | }, 101 | ], 102 | }, 103 | { 104 | code: dedent`\ 105 | declare const x: { foo: number; bar: number }; 106 | Object.entries(x); 107 | `, 108 | errors: [ 109 | { 110 | messageId: "noEnumMethod", 111 | data: { method: "entries" }, 112 | line: 2, 113 | column: 1, 114 | }, 115 | ], 116 | }, 117 | // Error if the argument's type has index signatures but it is disallowed by the option 118 | { 119 | code: dedent`\ 120 | declare const x: { [key: string]: number }; 121 | Object.keys(x); 122 | `, 123 | options: [{ allowIndexSignatures: false }], 124 | errors: [ 125 | { 126 | messageId: "noEnumMethod", 127 | data: { method: "keys" }, 128 | line: 2, 129 | column: 1, 130 | }, 131 | ], 132 | }, 133 | ], 134 | }); 135 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-enum-method/index.ts: -------------------------------------------------------------------------------- 1 | import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils"; 2 | import { 3 | createRule, 4 | hasIndexSignatures, 5 | isAnyType, 6 | isNonPrimitiveType, 7 | matchObjectMethodCall, 8 | possiblyContainsUnknownProperties, 9 | } from "../utils.js"; 10 | 11 | type Options = [ 12 | { 13 | allowIndexSignatures?: boolean; 14 | }, 15 | ]; 16 | 17 | type MessageIds = "noEnumMethod"; 18 | 19 | const rule = createRule({ 20 | name: "no-unsafe-object-enum-method", 21 | meta: { 22 | type: "suggestion", 23 | docs: { 24 | description: "Disallow possibly unsafe property enumeration methods of Object", 25 | requiresTypeChecking: true, 26 | }, 27 | messages: { 28 | noEnumMethod: 29 | "Object.{{method}}() possibly enumerates unknown properties. Consider enumerating only known properties of the object.", 30 | }, 31 | schema: [ 32 | { 33 | type: "object", 34 | additionalProperties: false, 35 | properties: { 36 | allowIndexSignatures: { 37 | type: "boolean", 38 | }, 39 | }, 40 | }, 41 | ], 42 | }, 43 | defaultOptions: [ 44 | { 45 | allowIndexSignatures: true, 46 | }, 47 | ], 48 | create: (context, [options]) => { 49 | const services = ESLintUtils.getParserServices(context); 50 | const checker = services.program.getTypeChecker(); 51 | return { 52 | CallExpression: (node) => { 53 | const method = matchObjectMethodCall(node); 54 | if (!isObjectEnumMethod(method)) { 55 | return; 56 | } 57 | const arg = node.arguments.length > 0 ? node.arguments[0] : undefined; 58 | if (!arg) { 59 | return; 60 | } 61 | // We do not consider the following cases: 62 | // - Object.keys(...[{ a: 0, b: 1 }]) 63 | // - declare const x: { [key: string]: number }; Object.keys(...[x]) 64 | if (arg.type !== AST_NODE_TYPES.SpreadElement) { 65 | // Safe if only contains known properties. 66 | if (!possiblyContainsUnknownProperties(arg)) { 67 | return; 68 | } 69 | const tsArgType = services.getTypeAtLocation(arg); 70 | // The enumeration methods work propertly for the any and non-primitive types. 71 | if (isAnyType(tsArgType) || isNonPrimitiveType(tsArgType)) { 72 | return; 73 | } 74 | // Mostly safe if the argument has index signatures. 75 | if (options.allowIndexSignatures && hasIndexSignatures(checker, tsArgType)) { 76 | return; 77 | } 78 | } 79 | context.report({ 80 | node, 81 | messageId: "noEnumMethod", 82 | data: { method }, 83 | }); 84 | }, 85 | }; 86 | }, 87 | }); 88 | 89 | const objectEnumMethods = ["keys", "values", "entries"] as const; 90 | type ObjectEnumMethod = (typeof objectEnumMethods)[number]; 91 | 92 | function isObjectEnumMethod(value: unknown): value is ObjectEnumMethod { 93 | return objectEnumMethods.some((method) => method === value); 94 | } 95 | 96 | export default rule; 97 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-check/README.md: -------------------------------------------------------------------------------- 1 | # `no-unsafe-object-property-check` 2 | 3 | Disallow possibly unsafe property checks of object. 4 | 5 | [The `in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in) can narrow types, but it is not always safe. 6 | 7 | For example, suppose we have a union type `Data` and a function that reads it. 8 | 9 | ```ts 10 | type Data = { foo: number } | { bar: string }; 11 | 12 | function myFunc(data: Data): void { 13 | if ("foo" in data) { 14 | const foo: number = data.foo; 15 | // ... 16 | } else { 17 | const bar: string = data.bar; 18 | // ... 19 | } 20 | } 21 | ``` 22 | 23 | Since the `in` operator narrows the type of `data`, we can access `data.foo` and `data.bar`. 24 | 25 | However, you can call `myFunc()` like below, as the argument matches the `{ bar: string }` case. 26 | 27 | ```ts 28 | const myData = { foo: "xxx", bar: "yyy" }; 29 | myFunc(myData); 30 | ``` 31 | 32 | It's clear that this does not work correctly, because `myData` is treated as `{ foo: number }` in the function. 33 | 34 | To remedy this, you should define `Data` as a [discriminated (tagged) union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions), and use the tag to narrow the type of `data`. 35 | 36 | ```ts 37 | type Data = { type: "foo"; value: number } | { type: "bar"; value: string }; 38 | 39 | function myFunc(data: Data): void { 40 | if (data.type === "foo") { 41 | const foo: number = data.value; 42 | // ... 43 | } else { 44 | const bar: string = data.value; 45 | // ... 46 | } 47 | } 48 | ``` 49 | 50 | ## Examples 51 | 52 | 👎 Examples of incorrect code for this rule: 53 | 54 | ```ts 55 | declare const counts: { foo: number } | { bar: string }; 56 | "foo" in counts; 57 | ``` 58 | 59 | 👍 Examples of correct code for this rule: 60 | 61 | ```ts 62 | declare const anyValue: any; 63 | "foo" in anyValue; 64 | 65 | declare const nonPrimitiveValue: object; 66 | "foo" in nonPrimitiveValue; 67 | 68 | declare const dictionary: { [key: string]: number }; 69 | "foo" in dictionary; 70 | ``` 71 | 72 | ## When Not To Use It 73 | 74 | If you don't care about this kind of type safety, disable this rule. 75 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-check/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import { dedent } from "@qnighy/dedent"; 3 | import { getFixturesDir } from "../__tests__/utils.js"; 4 | import rule from "./index.js"; 5 | 6 | const ruleTester = new RuleTester({ 7 | languageOptions: { 8 | parserOptions: { 9 | tsconfigRootDir: getFixturesDir(), 10 | project: "./tsconfig.json", 11 | }, 12 | }, 13 | }); 14 | 15 | ruleTester.run("no-unsafe-object-property-check", rule, { 16 | valid: [ 17 | // OK for any and non-primitive values 18 | dedent`\ 19 | declare const x: any; 20 | "a" in x; 21 | `, 22 | dedent`\ 23 | declare const x: object; 24 | "a" in x; 25 | `, 26 | // OK for index signatures 27 | dedent`\ 28 | declare const x: { [key: string]: number }; 29 | "a" in x; 30 | `, 31 | ], 32 | invalid: [ 33 | // Error if it possibly narrows type 34 | { 35 | code: dedent`\ 36 | declare const x: { a: number } | { b: string }; 37 | "a" in x; 38 | `, 39 | errors: [ 40 | { 41 | messageId: "noInOperator", 42 | line: 2, 43 | column: 1, 44 | }, 45 | ], 46 | }, 47 | { 48 | code: dedent`\ 49 | declare const x: { a: number } | { b: string } | { [key: string]: number }; 50 | "a" in x; 51 | `, 52 | errors: [ 53 | { 54 | messageId: "noInOperator", 55 | line: 2, 56 | column: 1, 57 | }, 58 | ], 59 | }, 60 | ], 61 | }); 62 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-check/index.ts: -------------------------------------------------------------------------------- 1 | import { ESLintUtils } from "@typescript-eslint/utils"; 2 | import { createRule, hasIndexSignatures, isAnyType, isNonPrimitiveType } from "../utils.js"; 3 | 4 | type Options = []; 5 | 6 | type MessageIds = "noInOperator"; 7 | 8 | const rule = createRule({ 9 | name: "no-unsafe-object-property-check", 10 | meta: { 11 | type: "suggestion", 12 | docs: { 13 | description: "Disallow possibly unsafe property checks of object", 14 | requiresTypeChecking: true, 15 | }, 16 | messages: { 17 | noInOperator: 18 | "Type narrowing using the `in` operator is possibly unsafe. Consider using discriminated unions.", 19 | }, 20 | schema: [], 21 | }, 22 | defaultOptions: [], 23 | create: (context) => { 24 | const services = ESLintUtils.getParserServices(context); 25 | const checker = services.program.getTypeChecker(); 26 | return { 27 | BinaryExpression: (node) => { 28 | if (node.operator !== "in") { 29 | return; 30 | } 31 | const tsRightType = services.getTypeAtLocation(node.right); 32 | // The check work propertly for the any and non-primitive types. 33 | if (isAnyType(tsRightType) || isNonPrimitiveType(tsRightType)) { 34 | return; 35 | } 36 | // Safe if the argument has index signatures. 37 | if (hasIndexSignatures(checker, tsRightType)) { 38 | return; 39 | } 40 | context.report({ 41 | node, 42 | messageId: "noInOperator", 43 | }); 44 | }, 45 | }; 46 | }, 47 | }); 48 | 49 | export default rule; 50 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-overwrite/README.md: -------------------------------------------------------------------------------- 1 | # `no-unsafe-object-property-overwrite` 2 | 3 | Disallow possibly unsafe overwrites of object properties. 4 | 5 | [The object spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) enumerates and copies an object's own properties, but it may contain properties that do not appear in the object's type. 6 | 7 | For example, suppose we have a type `Data`, and `DataWithMetadata` that extends `Data`. 8 | 9 | ```ts 10 | type Data = { 11 | foo: number; 12 | bar: number; 13 | }; 14 | 15 | type DataWithMetadata = Data & { 16 | metadata: string; 17 | }; 18 | 19 | function withMetadata(data: Data, metadata: string): DataWithMetadata { 20 | return { metadata, ...data }; 21 | } 22 | 23 | const dataA = { foo: 0, bar: 1 }; 24 | // metaA = "xxx" 25 | const metaA: string = withMetadata(dataA, "xxx").metadata; 26 | ``` 27 | 28 | This seems pretty good. 29 | However, the definition of `withMetadata()` is actually unsafe, because it allows overwriting `metadata` with the properties of `data`. 30 | 31 | ```ts 32 | const dataB = { foo: 0, bar: 1, metadata: 666 }; 33 | // metaB = 666 34 | const metaB: string = withMetadata(dataB, "xxx").metadata; 35 | ``` 36 | 37 | To fix the function, use the spread syntax at the beginning of the object literal. 38 | 39 | ```ts 40 | function withMetadata(data: Data, metadata: string): DataWithMetadata { 41 | // Write `...data` first so that it will not overwrite `metadata`. 42 | return { ...data, metadata }; 43 | } 44 | ``` 45 | 46 | The same applies to [`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). 47 | 48 | ```ts 49 | function withMetadata(data: Data, metadata: string): DataWithMetadata { 50 | // Don't do `Object.assign({ metadata }, data)` 51 | return Object.assign({ ...data }, { metadata }); 52 | } 53 | ``` 54 | 55 | ## Examples 56 | 57 | 👎 Examples of incorrect code for this rule: 58 | 59 | ```ts 60 | declare const x: { foo: number; bar: number }; 61 | declare const cond: boolean; 62 | 63 | ({ a: 0, ...x, b: 1 }); 64 | ({ a: 0, b: 1, ...x }); 65 | ({ a: 0, b: 1, ...{ ...x, c: 1, d: 2 } }); 66 | ({ a: 0, b: 1, ...(cond ? { c: 1, d: 2 } : x) }); 67 | 68 | Object.assign({ a: 0 }, x, { b: 1 }); 69 | Object.assign({ a: 0, b: 1 }, x); 70 | Object.assign({ a: 0, b: 1 }, { ...x, c: 1, d: 2 }); 71 | Object.assign({ a: 0, b: 1 }, cond ? { c: 1, d: 2 } : x); 72 | ``` 73 | 74 | 👍 Examples of correct code for this rule: 75 | 76 | ```ts 77 | declare const x: { foo: number; bar: number }; 78 | declare const cond: boolean; 79 | 80 | ({ ...x }); 81 | ({ ...x, a: 0, b: 1 }); 82 | ({ a: 0, b: 1, ...{ c: 2, d: 3, ...{ e: 4, f: 5 } } }); 83 | ({ a: 0, b: 1, ...(cond ? { c: 2, d: 3 } : { e: 4, f: 5 }) }); 84 | 85 | Object.assign(x); 86 | Object.assign(x, { a: 0, b: 1 }); 87 | Object.assign({ a: 0, b: 1 }, { c: 2, d: 3, ...{ e: 4, f: 5 } }); 88 | Object.assign({ a: 0, b: 1 }, cond ? { c: 2, d: 3 } : { e: 4, f: 5 }); 89 | 90 | declare const anyValue: any; 91 | 92 | ({ a: 0, b: 1, ...anyValue }); 93 | Object.assign({ a: 0, b: 1 }, anyValue); 94 | 95 | declare const countsA: { [key: string]: number }; 96 | declare const countsB: { [key: string]: number }; 97 | 98 | ({ ...countsA, ...countsB }); 99 | ``` 100 | 101 | ## Options 102 | 103 | ### `allowIndexSignatures` 104 | 105 | default = `true` 106 | 107 | When set to `true`, allows object spreads in any position if the object's type has only [index signatures](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) like `{ [key: string]: number }`. 108 | 109 | If the type has index signatures, object spreads are safe in most cases, while there are still some cases where it becomes unsafe. 110 | For example: 111 | 112 | ```ts 113 | const countsA: { [key: string]: number } = { 114 | foo: 1, 115 | bar: 2, 116 | }; 117 | 118 | const x = { 119 | baz: 3, 120 | metadata: "xxx", 121 | }; 122 | const y: { baz: number } = x; 123 | const countsB: { [key: string]: number } = y; 124 | 125 | // counts["metadata"] = "xxx" but its type is number 126 | const counts: { [key: string]: number } = { ...countsA, ...countsB }; 127 | ``` 128 | 129 | 👎 Examples of incorrect code for the `{ "allowIndexSignatures": false }` option: 130 | 131 | ```ts 132 | declare const countsA: { [key: string]: number }; 133 | declare const countsB: { [key: string]: number }; 134 | 135 | ({ ...countsA, ...countsB }); 136 | ``` 137 | 138 | ## When Not To Use It 139 | 140 | If you don't care about this kind of type safety, disable this rule. 141 | 142 | If it is ensured that the object does not contain unknown properties i.e. all the properties appear in its type, you can safely disable this rule for that specific case. 143 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-overwrite/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RuleTester } from "@typescript-eslint/rule-tester"; 2 | import { dedent } from "@qnighy/dedent"; 3 | import { getFixturesDir } from "../__tests__/utils.js"; 4 | import rule from "./index.js"; 5 | 6 | const ruleTester = new RuleTester({ 7 | languageOptions: { 8 | parserOptions: { 9 | tsconfigRootDir: getFixturesDir(), 10 | project: "./tsconfig.json", 11 | }, 12 | }, 13 | }); 14 | 15 | ruleTester.run("no-unsafe-object-property-overwrite", rule, { 16 | valid: [ 17 | // OK at the beginning of the object literal / Object.assign() 18 | dedent`\ 19 | declare const x: { foo: number; bar: number }; 20 | ({ ...x }); 21 | `, 22 | dedent`\ 23 | declare const x: { foo: number; bar: number }; 24 | Object.assign(x); 25 | `, 26 | dedent`\ 27 | declare const x: { foo: number; bar: number }; 28 | ({ ...x, a: 0, b: 1 }); 29 | `, 30 | dedent`\ 31 | declare const x: { foo: number; bar: number }; 32 | Object.assign(x, { a: 0, b: 1 }); 33 | `, 34 | // OK if all properties are known 35 | `({ a: 0, b: 1, ...{ c: 2, d: 3, ...{ e: 4, f: 5 } } })`, 36 | `Object.assign({ a: 0, b: 1 }, { c: 2, d: 3, ...{ e: 4, f: 5 } })`, 37 | dedent`\ 38 | declare const cond: boolean; 39 | ({ a: 0, b: 1, ...(cond ? { c: 2, d: 3 } : { e: 4, f: 5 }) }); 40 | `, 41 | dedent`\ 42 | declare const cond: boolean; 43 | Object.assign({ a: 0, b: 1 }, cond ? { c: 2, d: 3 } : { e: 4, f: 5 }); 44 | `, 45 | // OK for any 46 | dedent`\ 47 | declare const x: any; 48 | ({ a: 0, b: 1, ...x }); 49 | `, 50 | dedent`\ 51 | declare const x: any; 52 | Object.assign({ a: 0, b: 1 }, x); 53 | `, 54 | // OK if the object has only index signatures 55 | dedent`\ 56 | declare const x: { [key: string]: number }; 57 | declare const y: { [key: string]: string }; 58 | ({ ...x, ...y }); 59 | `, 60 | ], 61 | invalid: [ 62 | // Error at the middle or end of the object literal / Object.assign() 63 | { 64 | code: dedent`\ 65 | declare const x: { foo: number; bar: number }; 66 | ({ a: 0, ...x, b: 1 }); 67 | `, 68 | errors: [ 69 | { 70 | messageId: "noSpreadSyntax", 71 | line: 2, 72 | column: 10, 73 | suggestions: [ 74 | { 75 | messageId: "suggestMoveSpreadSyntax", 76 | output: dedent`\ 77 | declare const x: { foo: number; bar: number }; 78 | ({ ...x,a: 0, b: 1 }); 79 | `, 80 | }, 81 | ], 82 | }, 83 | ], 84 | }, 85 | { 86 | code: dedent`\ 87 | declare const x: { foo: number; bar: number }; 88 | Object.assign({ a: 0 }, x, { b: 1 }) 89 | `, 90 | errors: [ 91 | { 92 | messageId: "noObjectAssign", 93 | line: 2, 94 | column: 25, 95 | }, 96 | ], 97 | }, 98 | { 99 | code: dedent`\ 100 | declare const x: { foo: number; bar: number }; 101 | ({ a: 0, b: 1, ...x }); 102 | `, 103 | errors: [ 104 | { 105 | messageId: "noSpreadSyntax", 106 | line: 2, 107 | column: 16, 108 | suggestions: [ 109 | { 110 | messageId: "suggestMoveSpreadSyntax", 111 | output: dedent`\ 112 | declare const x: { foo: number; bar: number }; 113 | ({ ...x,a: 0, b: 1, }); 114 | `, 115 | }, 116 | ], 117 | }, 118 | ], 119 | }, 120 | { 121 | code: dedent`\ 122 | declare const x: { foo: number; bar: number }; 123 | Object.assign({ a: 0, b: 1 }, x); 124 | `, 125 | errors: [ 126 | { 127 | messageId: "noObjectAssign", 128 | line: 2, 129 | column: 31, 130 | }, 131 | ], 132 | }, 133 | // Error if possibly contains unknown properties 134 | { 135 | code: dedent`\ 136 | declare const x: { foo: number; bar: number }; 137 | ({ a: 0, b: 1, ...{ ...x, c: 1, d: 2 } }); 138 | `, 139 | errors: [ 140 | { 141 | messageId: "noSpreadSyntax", 142 | line: 2, 143 | column: 16, 144 | suggestions: [ 145 | { 146 | messageId: "suggestMoveSpreadSyntax", 147 | output: dedent`\ 148 | declare const x: { foo: number; bar: number }; 149 | ({ ...{ ...x, c: 1, d: 2 },a: 0, b: 1, }); 150 | `, 151 | }, 152 | ], 153 | }, 154 | ], 155 | }, 156 | { 157 | code: dedent`\ 158 | declare const x: { foo: number; bar: number }; 159 | Object.assign({ a: 0, b: 1 }, { ...x, c: 1, d: 2 }); 160 | `, 161 | errors: [ 162 | { 163 | messageId: "noObjectAssign", 164 | line: 2, 165 | column: 31, 166 | }, 167 | ], 168 | }, 169 | { 170 | code: dedent`\ 171 | declare const x: { foo: number; bar: number }; 172 | declare const cond: boolean; 173 | ({ a: 0, b: 1, ...(cond ? { c: 1, d: 2 } : x) }); 174 | `, 175 | errors: [ 176 | { 177 | messageId: "noSpreadSyntax", 178 | line: 3, 179 | column: 16, 180 | suggestions: [ 181 | { 182 | messageId: "suggestMoveSpreadSyntax", 183 | output: dedent`\ 184 | declare const x: { foo: number; bar: number }; 185 | declare const cond: boolean; 186 | ({ ...(cond ? { c: 1, d: 2 } : x),a: 0, b: 1, }); 187 | `, 188 | }, 189 | ], 190 | }, 191 | ], 192 | }, 193 | { 194 | code: dedent`\ 195 | declare const x: { foo: number; bar: number }; 196 | declare const cond: boolean; 197 | Object.assign({ a: 0, b: 1 }, cond ? { c: 1, d: 2 } : x); 198 | `, 199 | errors: [ 200 | { 201 | messageId: "noObjectAssign", 202 | line: 3, 203 | column: 31, 204 | }, 205 | ], 206 | }, 207 | // Multiple errors 208 | { 209 | code: dedent`\ 210 | declare const x: { foo: number; bar: number }; 211 | declare const y: { foo: number; bar: number }; 212 | declare const z: { foo: number; bar: number }; 213 | ({ ...x, a: 0, ...y, b: 1, ...z }); 214 | `, 215 | errors: [ 216 | { 217 | messageId: "noSpreadSyntax", 218 | line: 4, 219 | column: 16, 220 | suggestions: [ 221 | { 222 | messageId: "suggestMoveSpreadSyntax", 223 | output: dedent`\ 224 | declare const x: { foo: number; bar: number }; 225 | declare const y: { foo: number; bar: number }; 226 | declare const z: { foo: number; bar: number }; 227 | ({ ...x, ...y,a: 0, b: 1, ...z }); 228 | `, 229 | }, 230 | ], 231 | }, 232 | { 233 | messageId: "noSpreadSyntax", 234 | line: 4, 235 | column: 28, 236 | suggestions: [ 237 | { 238 | messageId: "suggestMoveSpreadSyntax", 239 | output: dedent`\ 240 | declare const x: { foo: number; bar: number }; 241 | declare const y: { foo: number; bar: number }; 242 | declare const z: { foo: number; bar: number }; 243 | ({ ...x, ...z,a: 0, ...y, b: 1, }); 244 | `, 245 | }, 246 | ], 247 | }, 248 | ], 249 | }, 250 | { 251 | code: dedent`\ 252 | declare const x: { foo: number; bar: number }; 253 | declare const y: { foo: number; bar: number }; 254 | declare const z: { foo: number; bar: number }; 255 | Object.assign(x, { a: 0 }, y, { b: 1 }, z); 256 | `, 257 | errors: [ 258 | { 259 | messageId: "noObjectAssign", 260 | line: 4, 261 | column: 28, 262 | }, 263 | { 264 | messageId: "noObjectAssign", 265 | line: 4, 266 | column: 41, 267 | }, 268 | ], 269 | }, 270 | // Error if the object has only index signatures but it is disallowed by the option 271 | { 272 | code: dedent`\ 273 | declare const x: { [key: string]: number }; 274 | declare const y: { [key: string]: string }; 275 | ({ ...x, ...y }); 276 | `, 277 | options: [{ allowIndexSignatures: false }], 278 | errors: [ 279 | { 280 | messageId: "noSpreadSyntax", 281 | line: 3, 282 | column: 10, 283 | }, 284 | ], 285 | }, 286 | ], 287 | }); 288 | -------------------------------------------------------------------------------- /src/rules/no-unsafe-object-property-overwrite/index.ts: -------------------------------------------------------------------------------- 1 | import { AST_NODE_TYPES, AST_TOKEN_TYPES, ESLintUtils } from "@typescript-eslint/utils"; 2 | import { 3 | createRule, 4 | hasOnlyIndexSignatures, 5 | isAnyType, 6 | matchObjectMethodCall, 7 | possiblyContainsUnknownProperties, 8 | } from "../utils.js"; 9 | 10 | type Options = [ 11 | { 12 | allowIndexSignatures?: boolean; 13 | }, 14 | ]; 15 | 16 | type MessageIds = "noSpreadSyntax" | "noObjectAssign" | "suggestMoveSpreadSyntax"; 17 | 18 | const rule = createRule({ 19 | name: "no-unsafe-object-property-overwrite", 20 | meta: { 21 | type: "suggestion", 22 | docs: { 23 | description: "Disallow possibly unsafe overwrites of object properties", 24 | requiresTypeChecking: true, 25 | }, 26 | hasSuggestions: true, 27 | messages: { 28 | noSpreadSyntax: 29 | "The spread syntax possibly overwrites properties with unknown values. Consider moving this to the beginning of the object literal.", 30 | noObjectAssign: 31 | "Object.assign() possibly overwrites properties with unknown values. Consider moving this to the beginning of the argument list.", 32 | suggestMoveSpreadSyntax: "Move the spread syntax to the front.", 33 | }, 34 | schema: [ 35 | { 36 | type: "object", 37 | additionalProperties: false, 38 | properties: { 39 | allowIndexSignatures: { 40 | type: "boolean", 41 | }, 42 | }, 43 | }, 44 | ], 45 | }, 46 | defaultOptions: [ 47 | { 48 | allowIndexSignatures: true, 49 | }, 50 | ], 51 | create: (context, [options]) => { 52 | const services = ESLintUtils.getParserServices(context); 53 | const checker = services.program.getTypeChecker(); 54 | return { 55 | ObjectExpression: (node) => { 56 | const tsNodeType = services.getTypeAtLocation(node); 57 | // Ignore any. 58 | if (isAnyType(tsNodeType)) { 59 | return; 60 | } 61 | // Mostly safe if the object has only index signatures. 62 | if (options.allowIndexSignatures && hasOnlyIndexSignatures(checker, tsNodeType)) { 63 | return; 64 | } 65 | // Nothing to check. 66 | if (node.properties.length <= 1) { 67 | return; 68 | } 69 | const firstNonSpreadProp = node.properties.find( 70 | (prop) => prop.type !== AST_NODE_TYPES.SpreadElement, 71 | ); 72 | for (let i = 1; i < node.properties.length; i++) { 73 | const prop = node.properties[i]; 74 | if (prop.type !== AST_NODE_TYPES.SpreadElement) { 75 | continue; 76 | } 77 | // Safe if the spread contains only known properties. 78 | if (!possiblyContainsUnknownProperties(prop.argument)) { 79 | continue; 80 | } 81 | context.report({ 82 | node: prop, 83 | messageId: "noSpreadSyntax", 84 | suggest: 85 | firstNonSpreadProp ? 86 | [ 87 | { 88 | messageId: "suggestMoveSpreadSyntax", 89 | *fix(fixer) { 90 | const nextToken = context.sourceCode.getTokenAfter(prop); 91 | const hasTrailingComma = 92 | !!nextToken 93 | && nextToken.type === AST_TOKEN_TYPES.Punctuator 94 | && nextToken.value === ","; 95 | yield fixer.insertTextBefore( 96 | firstNonSpreadProp, 97 | context.sourceCode.getText(prop) + ",", 98 | ); 99 | yield fixer.remove(prop); 100 | if (hasTrailingComma) { 101 | yield fixer.removeRange(nextToken.range); 102 | } 103 | }, 104 | }, 105 | ] 106 | : [], 107 | }); 108 | } 109 | }, 110 | CallExpression: (node) => { 111 | const method = matchObjectMethodCall(node); 112 | if (method !== "assign") { 113 | return; 114 | } 115 | // Nothing to check. 116 | if (node.arguments.length <= 1) { 117 | return; 118 | } 119 | for (let i = 1; i < node.arguments.length; i++) { 120 | const arg = node.arguments[i]; 121 | // Safe if the argument contains only known properties. 122 | // We do not consider Object.assign(...[{ a: 0, b: 1 }]) 123 | if (arg.type !== AST_NODE_TYPES.SpreadElement) { 124 | const tsArgType = services.getTypeAtLocation(arg); 125 | if (isAnyType(tsArgType)) { 126 | continue; 127 | } 128 | if (!possiblyContainsUnknownProperties(arg)) { 129 | continue; 130 | } 131 | } 132 | context.report({ 133 | node: arg, 134 | messageId: "noObjectAssign", 135 | }); 136 | } 137 | }, 138 | }; 139 | }, 140 | }); 141 | 142 | export default rule; 143 | -------------------------------------------------------------------------------- /src/rules/utils.ts: -------------------------------------------------------------------------------- 1 | import type { TSESTree } from "@typescript-eslint/utils"; 2 | import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils"; 3 | import ts from "typescript"; 4 | 5 | export type PluginDocs = { 6 | requiresTypeChecking?: boolean | undefined; 7 | }; 8 | 9 | // eslint-disable-next-line new-cap 10 | export const createRule = ESLintUtils.RuleCreator( 11 | (ruleName) => 12 | `https://github.com/susisu/eslint-plugin-safe-typescript/blob/main/src/rules/${ruleName}/README.md`, 13 | ); 14 | 15 | /** 16 | * Checks if the value of the expression possibly contains properties that do not appear in its type. 17 | */ 18 | export function possiblyContainsUnknownProperties(node: TSESTree.Expression): boolean { 19 | if (node.type === AST_NODE_TYPES.ObjectExpression) { 20 | return node.properties.some((prop) => { 21 | if (prop.type === AST_NODE_TYPES.SpreadElement) { 22 | return possiblyContainsUnknownProperties(prop.argument); 23 | } else { 24 | return false; 25 | } 26 | }); 27 | } else if (node.type === AST_NODE_TYPES.ConditionalExpression) { 28 | return ( 29 | possiblyContainsUnknownProperties(node.consequent) 30 | || possiblyContainsUnknownProperties(node.alternate) 31 | ); 32 | } else { 33 | return true; 34 | } 35 | } 36 | 37 | /** 38 | * Matches Object method call and returns the method's name. 39 | */ 40 | export function matchObjectMethodCall(node: TSESTree.CallExpression): string | undefined { 41 | const { callee } = node; 42 | // We do not consider the following cases: 43 | // - const m = Object.keys; m(x) 44 | // - const o = Object; o.keys(x) 45 | // - const k = "keys"; Object[k](x) 46 | if (callee.type !== AST_NODE_TYPES.MemberExpression) { 47 | return undefined; 48 | } 49 | const { object, property } = callee; 50 | if (object.type !== AST_NODE_TYPES.Identifier || object.name !== "Object") { 51 | return undefined; 52 | } 53 | if (property.type === AST_NODE_TYPES.Identifier) { 54 | if (callee.computed) { 55 | return undefined; 56 | } 57 | const method = property.name; 58 | return method; 59 | } else if (property.type === AST_NODE_TYPES.Literal) { 60 | const method = property.value; 61 | if (typeof method !== "string") { 62 | return undefined; 63 | } 64 | return method; 65 | } else { 66 | return undefined; 67 | } 68 | } 69 | 70 | /** 71 | * Checks if the type is the any type. 72 | */ 73 | export function isAnyType(type: ts.Type): boolean { 74 | return (type.flags & ts.TypeFlags.Any) !== 0; 75 | } 76 | 77 | /** 78 | * Checks if the type is the non-primitive type i.e. `object`. 79 | */ 80 | export function isNonPrimitiveType(type: ts.Type): boolean { 81 | return (type.flags & ts.TypeFlags.NonPrimitive) !== 0; 82 | } 83 | 84 | /** 85 | * Checks if the type has index signatures. 86 | */ 87 | export function hasIndexSignatures(checker: ts.TypeChecker, type: ts.Type): boolean { 88 | return checker.getIndexInfosOfType(type).length > 0; 89 | } 90 | 91 | /** 92 | * Checks if the type has only index signatures. 93 | */ 94 | export function hasOnlyIndexSignatures(checker: ts.TypeChecker, type: ts.Type): boolean { 95 | return hasIndexSignatures(checker, type) && checker.getPropertiesOfType(type).length === 0; 96 | } 97 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "declarationMap": true 9 | }, 10 | "include": [ 11 | "src/**/*" 12 | ], 13 | "exclude": [ 14 | "src/**/*.test.*", 15 | "src/**/*.spec.*", 16 | "src/**/__tests__/**/*" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "nodenext", 5 | "moduleResolution": "nodenext", 6 | "esModuleInterop": true, 7 | "verbatimModuleSyntax": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "jsx": "react-jsx", 10 | "lib": ["esnext"], 11 | "strict": true, 12 | "exactOptionalPropertyTypes": true, 13 | "noImplicitOverride": true, 14 | "noImplicitReturns": true, 15 | "noPropertyAccessFromIndexSignature": true, 16 | "skipLibCheck": true, 17 | "types": ["vitest/globals"] 18 | }, 19 | "include": [ 20 | "**/*" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /vitest.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true, 6 | coverage: { 7 | include: ["src/**/*"], 8 | }, 9 | }, 10 | }); 11 | --------------------------------------------------------------------------------