diff --git a/.eslintrc.json b/.eslintrc.json index 8bccb2a..a16f69b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,6 +9,7 @@ ], "no-case-declarations": 0, "no-tabs": "off", + "no-mixed-spaces-and-tabs": "off", "vitest/unbound-method": "off" } } \ No newline at end of file diff --git a/README.md b/README.md index 4472421..d4a2885 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ export default [ | [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | 🌐 | 🔧 | | | [prefer-each](docs/rules/prefer-each.md) | Prefer `each` rather than manual loops | | 🌐 | | | | [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in quality matchers | | 🌐 | | 💡 | +| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using expect assertions instead of callbacks | | 🌐 | | 💡 | | [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Suggest using `expect().resolves` over `expect(await ...)` syntax | | 🌐 | 🔧 | | | [prefer-hooks-in-order](docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in consistent order | | 🌐 | | | | [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | 🌐 | | | diff --git a/docs/rules/prefer-expect-assertions.md b/docs/rules/prefer-expect-assertions.md new file mode 100644 index 0000000..cfe2562 --- /dev/null +++ b/docs/rules/prefer-expect-assertions.md @@ -0,0 +1,116 @@ +# Suggest using expect assertions instead of callbacks (`vitest/prefer-expect-assertions`) + +⚠️ This rule _warns_ in the 🌐 `all` config. + +💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). + + + +Ensure every test to have either `expect.assertions()` OR +`expect.hasAssertions()` as its first expression. + +This will warn if a test has no assertions, or if it has assertions but they are not the first expression. + +## Examples + +Examples of **incorrect** code for this rule: + +```js +test('no assertions', () => { + // ... +}); + +test('assertions not first', () => { + expect(true).toBe(true); + // ... +}); +``` + +Examples of **correct** code for this rule: + +```js +test('assertions first', () => { + expect.assertions(1); + // ... +}); + +test('assertions first', () => { + expect.hasAssertions(); + // ... +}); +``` + +## Options + +`onlyFunctionsWithAsyncKeyword` (default: `false`) + +When `true`, only functions with the `async` keyword will be checked. + +when this option is enabled the following code will be considered incorrect: + +```js +test('assertions first', () => { + const data = await fetchData(); + expect(data).toBe('peanut butter'); +}); +``` + +To fix this, you'll need to add `expect.assertions(1)` or `expect.hasAssertions()` as the first expression: + +```js +test('assertions first', () => { + expect.assertions(1); + const data = await fetchData(); + expect(data).toBe('peanut butter'); +}); +``` + +`onlyFunctionsWithExpectInLoop` (default: `false`) + +When `true`, only functions with `expect` in a loop will be checked. + +when this option is enabled the following code will be considered incorrect: + +```js +test('assertions first', () => { + for (let i = 0; i < 10; i++) { + expect(i).toBeLessThan(10); + } +}); +``` + +To fix this, you'll need to add `expect.assertions(1)` or `expect.hasAssertions()` as the first expression: + +```js +test('assertions first', () => { + expect.hasAssertions(); + for (let i = 0; i < 10; i++) { + expect(i).toBeLessThan(10); + } +}); +``` + +`onlyFunctionsWithExpectInCallback` + +When `true`, only functions with `expect` in a callback will be checked. + +when this option is enabled the following code will be considered incorrect: + +```js +test('assertions first', () => { + fetchData((data) => { + expect(data).toBe('peanut butter'); + }); +}); +``` + +To fix this, you'll need to add `expect.assertions(1)` or `expect.hasAssertions()` as the first expression: + +```js +test('assertions first', () => { + expect.assertions(1); + fetchData((data) => { + expect(data).toBe('peanut butter'); + }); +}); +``` diff --git a/fixtures/package.json b/fixtures/package.json index e2fa496..a8ed755 100644 --- a/fixtures/package.json +++ b/fixtures/package.json @@ -12,9 +12,9 @@ "license": "MIT", "dependencies": { "eslint-plugin-vitest": "link:../", - "vitest": "^1.0.2" + "vitest": "^1.0.4" }, "devDependencies": { - "eslint": "^8.55.0" + "eslint": "^8.56.0" } } diff --git a/package.json b/package.json index d0d72d9..780406b 100644 --- a/package.json +++ b/package.json @@ -40,26 +40,26 @@ "tsc": "tsc --noEmit" }, "devDependencies": { - "@babel/types": "^7.23.5", + "@babel/types": "^7.23.6", "@types/mocha": "^10.0.6", "@types/node": "^20.10.4", - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/rule-tester": "^6.13.2", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/rule-tester": "^6.14.0", "@veritem/eslint-config": "^0.0.11", - "bumpp": "^9.2.0", + "bumpp": "^9.2.1", "concurrently": "^8.2.2", - "eslint": "^8.55.0", + "eslint": "^8.56.0", "eslint-doc-generator": "^1.6.1", - "eslint-plugin-eslint-plugin": "^5.1.1", + "eslint-plugin-eslint-plugin": "^5.2.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-vitest": "^0.3.10", + "eslint-plugin-vitest": "^0.3.17", "eslint-remote-tester": "^3.0.1", "eslint-remote-tester-repositories": "^1.0.1", "ts-node": "^10.9.2", "tsx": "^4.6.2", "typescript": "^5.3.3", "unbuild": "^2.0.0", - "vitest": "^1.0.2" + "vitest": "^1.0.4" }, "engines": { "node": "^18.0.0 || >= 20.0.0" @@ -77,6 +77,6 @@ } }, "dependencies": { - "@typescript-eslint/utils": "^6.13.2" + "@typescript-eslint/utils": "^6.14.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ce36d0..0813311 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,13 +6,13 @@ settings: dependencies: '@typescript-eslint/utils': - specifier: ^6.13.2 - version: 6.13.2(eslint@8.55.0)(typescript@5.3.3) + specifier: ^6.14.0 + version: 6.14.0(eslint@8.56.0)(typescript@5.3.3) devDependencies: '@babel/types': - specifier: ^7.23.5 - version: 7.23.5 + specifier: ^7.23.6 + version: 7.23.6 '@types/mocha': specifier: ^10.0.6 version: 10.0.6 @@ -20,38 +20,38 @@ devDependencies: specifier: ^20.10.4 version: 20.10.4 '@typescript-eslint/eslint-plugin': - specifier: ^6.13.2 - version: 6.13.2(@typescript-eslint/parser@6.4.1)(eslint@8.55.0)(typescript@5.3.3) + specifier: ^6.14.0 + version: 6.14.0(@typescript-eslint/parser@6.4.1)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/rule-tester': - specifier: ^6.13.2 - version: 6.13.2(@eslint/eslintrc@2.1.3)(eslint@8.55.0)(typescript@5.3.3) + specifier: ^6.14.0 + version: 6.14.0(@eslint/eslintrc@2.1.4)(eslint@8.56.0)(typescript@5.3.3) '@veritem/eslint-config': specifier: ^0.0.11 - version: 0.0.11(eslint@8.55.0)(typescript@5.3.3) + version: 0.0.11(eslint@8.56.0)(typescript@5.3.3) bumpp: - specifier: ^9.2.0 - version: 9.2.0 + specifier: ^9.2.1 + version: 9.2.1 concurrently: specifier: ^8.2.2 version: 8.2.2 eslint: - specifier: ^8.55.0 - version: 8.55.0 + specifier: ^8.56.0 + version: 8.56.0 eslint-doc-generator: specifier: ^1.6.1 - version: 1.6.1(eslint@8.55.0)(typescript@5.3.3) + version: 1.6.1(eslint@8.56.0)(typescript@5.3.3) eslint-plugin-eslint-plugin: - specifier: ^5.1.1 - version: 5.1.1(eslint@8.55.0) + specifier: ^5.2.1 + version: 5.2.1(eslint@8.56.0) eslint-plugin-node: specifier: ^11.1.0 - version: 11.1.0(eslint@8.55.0) + version: 11.1.0(eslint@8.56.0) eslint-plugin-vitest: - specifier: ^0.3.10 - version: 0.3.10(@typescript-eslint/eslint-plugin@6.13.2)(eslint@8.55.0)(typescript@5.3.3)(vitest@1.0.2) + specifier: ^0.3.17 + version: 0.3.17(@typescript-eslint/eslint-plugin@6.14.0)(eslint@8.56.0)(typescript@5.3.3)(vitest@1.0.4) eslint-remote-tester: specifier: ^3.0.1 - version: 3.0.1(eslint@8.55.0)(ts-node@10.9.2) + version: 3.0.1(eslint@8.56.0)(ts-node@10.9.2) eslint-remote-tester-repositories: specifier: ^1.0.1 version: 1.0.1 @@ -68,8 +68,8 @@ devDependencies: specifier: ^2.0.0 version: 2.0.0(typescript@5.3.3) vitest: - specifier: ^1.0.2 - version: 1.0.2(@types/node@20.10.4) + specifier: ^1.0.4 + version: 1.0.4(@types/node@20.10.4) packages: @@ -119,7 +119,7 @@ packages: '@babel/parser': 7.22.10 '@babel/template': 7.22.5 '@babel/traverse': 7.22.10 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -133,7 +133,7 @@ packages: resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 @@ -160,21 +160,21 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.22.5 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/helper-hoist-variables@7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/helper-module-imports@7.22.5: resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.10): @@ -195,14 +195,14 @@ packages: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/helper-string-parser@7.23.4: @@ -226,7 +226,7 @@ packages: dependencies: '@babel/template': 7.22.5 '@babel/traverse': 7.22.10 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 transitivePeerDependencies: - supports-color dev: true @@ -255,7 +255,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/runtime@7.20.7: @@ -283,7 +283,7 @@ packages: dependencies: '@babel/code-frame': 7.22.10 '@babel/parser': 7.22.10 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 dev: true /@babel/traverse@7.22.10: @@ -297,15 +297,15 @@ packages: '@babel/helper-hoist-variables': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.22.10 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/types@7.23.5: - resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.23.4 @@ -914,36 +914,19 @@ packages: dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 3.4.3 /@eslint-community/regexpp@4.7.0: resolution: {integrity: sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - /@eslint/eslintrc@2.1.3: - resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.19.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - /@eslint/eslintrc@2.1.4: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -960,8 +943,8 @@ packages: transitivePeerDependencies: - supports-color - /@eslint/js@8.55.0: - resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} /@humanwhocodes/config-array@0.11.13: @@ -1338,7 +1321,7 @@ packages: resolution: {integrity: sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==} dev: true - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.55.0)(typescript@5.3.3): + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1350,12 +1333,12 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.7.0 - '@typescript-eslint/parser': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/type-utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/type-utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare-lite: 1.4.0 @@ -1366,8 +1349,8 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin@6.13.2(@typescript-eslint/parser@6.4.1)(eslint@8.55.0)(typescript@5.3.3): - resolution: {integrity: sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==} + /@typescript-eslint/eslint-plugin@6.14.0(@typescript-eslint/parser@6.4.1)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1378,13 +1361,13 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.7.0 - '@typescript-eslint/parser': 6.4.1(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.13.2 - '@typescript-eslint/type-utils': 6.13.2(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.13.2(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.13.2 + '@typescript-eslint/parser': 6.4.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/type-utils': 6.14.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 @@ -1395,7 +1378,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.55.0)(typescript@5.3.3): + /@typescript-eslint/parser@5.62.0(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1409,13 +1392,13 @@ packages: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3) debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.4.1(eslint@8.55.0)(typescript@5.3.3): + /@typescript-eslint/parser@6.4.1(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -1430,24 +1413,24 @@ packages: '@typescript-eslint/typescript-estree': 6.4.1(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.4.1 debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/rule-tester@6.13.2(@eslint/eslintrc@2.1.3)(eslint@8.55.0)(typescript@5.3.3): - resolution: {integrity: sha512-lmrPsmmi7hAGE6KYmvLkBPVWxsYhJ9mQ3BLdh09fPOgXIX6q3ukK1QSA5KbwFQ6qY39nkhTPORPHVEaVha4KpQ==} + /@typescript-eslint/rule-tester@6.14.0(@eslint/eslintrc@2.1.4)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-SCxrm68pudpNTUGCqaGxgqNujca+sEjJXA52gH3b0q1DrVBq1VSlxgO9kSmodhbXKVyS7UGlbz3dPDqa65gR2g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@eslint/eslintrc': '>=2' eslint: '>=8' dependencies: - '@eslint/eslintrc': 2.1.3 - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.3.3) - '@typescript-eslint/utils': 6.13.2(eslint@8.55.0)(typescript@5.3.3) + '@eslint/eslintrc': 2.1.4 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.56.0)(typescript@5.3.3) ajv: 6.12.6 - eslint: 8.55.0 + eslint: 8.56.0 lodash.merge: 4.6.2 semver: 7.5.4 transitivePeerDependencies: @@ -1463,12 +1446,12 @@ packages: '@typescript-eslint/visitor-keys': 5.62.0 dev: true - /@typescript-eslint/scope-manager@6.13.2: - resolution: {integrity: sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==} + /@typescript-eslint/scope-manager@6.14.0: + resolution: {integrity: sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/visitor-keys': 6.13.2 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 /@typescript-eslint/scope-manager@6.4.1: resolution: {integrity: sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==} @@ -1478,7 +1461,7 @@ packages: '@typescript-eslint/visitor-keys': 6.4.1 dev: true - /@typescript-eslint/type-utils@5.62.0(eslint@8.55.0)(typescript@5.3.3): + /@typescript-eslint/type-utils@5.62.0(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1489,17 +1472,17 @@ packages: optional: true dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3) - '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 tsutils: 3.21.0(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/type-utils@6.13.2(eslint@8.55.0)(typescript@5.3.3): - resolution: {integrity: sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==} + /@typescript-eslint/type-utils@6.14.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1508,10 +1491,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.3.3) - '@typescript-eslint/utils': 6.13.2(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 - eslint: 8.55.0 + eslint: 8.56.0 ts-api-utils: 1.0.2(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: @@ -1523,8 +1506,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/types@6.13.2: - resolution: {integrity: sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==} + /@typescript-eslint/types@6.14.0: + resolution: {integrity: sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==} engines: {node: ^16.0.0 || >=18.0.0} /@typescript-eslint/types@6.4.1: @@ -1553,8 +1536,8 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree@6.13.2(typescript@5.3.3): - resolution: {integrity: sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==} + /@typescript-eslint/typescript-estree@6.14.0(typescript@5.3.3): + resolution: {integrity: sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1562,8 +1545,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/visitor-keys': 6.13.2 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1594,19 +1577,19 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.55.0)(typescript@5.3.3): + /@typescript-eslint/utils@5.62.0(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3) - eslint: 8.55.0 + eslint: 8.56.0 eslint-scope: 5.1.1 semver: 7.5.4 transitivePeerDependencies: @@ -1614,19 +1597,19 @@ packages: - typescript dev: true - /@typescript-eslint/utils@6.13.2(eslint@8.55.0)(typescript@5.3.3): - resolution: {integrity: sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==} + /@typescript-eslint/utils@6.14.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.13.2 - '@typescript-eslint/types': 6.13.2 - '@typescript-eslint/typescript-estree': 6.13.2(typescript@5.3.3) - eslint: 8.55.0 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + eslint: 8.56.0 semver: 7.5.4 transitivePeerDependencies: - supports-color @@ -1640,11 +1623,11 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@typescript-eslint/visitor-keys@6.13.2: - resolution: {integrity: sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==} + /@typescript-eslint/visitor-keys@6.14.0: + resolution: {integrity: sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.13.2 + '@typescript-eslint/types': 6.14.0 eslint-visitor-keys: 3.4.3 /@typescript-eslint/visitor-keys@6.4.1: @@ -1658,18 +1641,18 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - /@veritem/eslint-config-base@0.0.11(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint@8.55.0)(typescript@5.3.3): + /@veritem/eslint-config-base@0.0.11(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-tmDpz6DheFC4b7n8FxiyG/TCoHgSeiA3sECXvcvJi5ECokHfhubjoTJu4jha6XdE8rReiv5eXFx/CJtanSgpaw==} peerDependencies: typescript: '>=4.x' dependencies: - eslint-plugin-eslint-comments: 3.2.0(eslint@8.55.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.56.0) eslint-plugin-html: 7.1.0 - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.55.0) - eslint-plugin-markdown: 3.0.1(eslint@8.55.0) - eslint-plugin-promise: 6.1.1(eslint@8.55.0) - eslint-plugin-unicorn: 46.0.1(eslint@8.55.0) - eslint-plugin-unused-imports: 2.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.55.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.56.0) + eslint-plugin-markdown: 3.0.1(eslint@8.56.0) + eslint-plugin-promise: 6.1.1(eslint@8.56.0) + eslint-plugin-unicorn: 46.0.1(eslint@8.56.0) + eslint-plugin-unused-imports: 2.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.56.0) typescript: 5.3.3 transitivePeerDependencies: - '@typescript-eslint/eslint-plugin' @@ -1680,16 +1663,16 @@ packages: - supports-color dev: true - /@veritem/eslint-config-react@0.0.11(eslint@8.55.0)(typescript@5.3.3): + /@veritem/eslint-config-react@0.0.11(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-s5RbJvdrY5bYPAro3nsw0BWVYCIVyyw7cm6jbXASsqoBrUEkt+ubCm7h3oO0WGoO3ioqu8uBhQCTSZP9U4T/NA==} peerDependencies: eslint: '>=8.0.0' dependencies: - '@veritem/eslint-config-ts': 0.0.11(eslint@8.55.0)(typescript@5.3.3) - eslint: 8.55.0 - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.55.0) - eslint-plugin-react: 7.33.2(eslint@8.55.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.55.0) + '@veritem/eslint-config-ts': 0.0.11(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + eslint-plugin-jsx-a11y: 6.7.1(eslint@8.56.0) + eslint-plugin-react: 7.33.2(eslint@8.56.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -1697,16 +1680,16 @@ packages: - typescript dev: true - /@veritem/eslint-config-ts@0.0.11(eslint@8.55.0)(typescript@5.3.3): + /@veritem/eslint-config-ts@0.0.11(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-OZ6GzEtbZlTg0ZwUfPl2kHJKuQJapZ3fZf4/Uhs7xnbONtkUprgBlU4oH20+12XdS2CUQLmUEzvUGpgho/UniA==} peerDependencies: eslint: '>=8.0.0' dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/parser': 5.62.0(eslint@8.55.0)(typescript@5.3.3) - '@veritem/eslint-config-base': 0.0.11(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint@8.55.0)(typescript@5.3.3) - eslint: 8.55.0 - eslint-plugin-n: 15.7.0(eslint@8.55.0) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3) + '@veritem/eslint-config-base': 0.0.11(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + eslint-plugin-n: 15.7.0(eslint@8.56.0) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -1714,10 +1697,10 @@ packages: - typescript dev: true - /@veritem/eslint-config@0.0.11(eslint@8.55.0)(typescript@5.3.3): + /@veritem/eslint-config@0.0.11(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-NTESflVjo4gdIab27tSmGaRoAI5rkSEvp24pSXouIULb7Ah7UaIZoGfmZpwhGJlgOafkySiofe0gqzFwrVPO3Q==} dependencies: - '@veritem/eslint-config-react': 0.0.11(eslint@8.55.0)(typescript@5.3.3) + '@veritem/eslint-config-react': 0.0.11(eslint@8.56.0)(typescript@5.3.3) transitivePeerDependencies: - eslint - eslint-import-resolver-typescript @@ -1726,38 +1709,38 @@ packages: - typescript dev: true - /@vitest/expect@1.0.2: - resolution: {integrity: sha512-mAIo/8uddSWkjQMLFcjqZP3WmkwvvN0OtlyZIu33jFnwme3vZds8m8EDMxtj+Uzni2DwtPfHNjJcTM8zTV1f4A==} + /@vitest/expect@1.0.4: + resolution: {integrity: sha512-/NRN9N88qjg3dkhmFcCBwhn/Ie4h064pY3iv7WLRsDJW7dXnEgeoa8W9zy7gIPluhz6CkgqiB3HmpIXgmEY5dQ==} dependencies: - '@vitest/spy': 1.0.2 - '@vitest/utils': 1.0.2 + '@vitest/spy': 1.0.4 + '@vitest/utils': 1.0.4 chai: 4.3.10 dev: true - /@vitest/runner@1.0.2: - resolution: {integrity: sha512-ZcHJXPT2kg/9Hc4fNkCbItlsgZSs3m4vQbxB8LCSdzpbG85bExCmSvu6K9lWpMNdoKfAr1Jn0BwS9SWUcGnbTQ==} + /@vitest/runner@1.0.4: + resolution: {integrity: sha512-rhOQ9FZTEkV41JWXozFM8YgOqaG9zA7QXbhg5gy6mFOVqh4PcupirIJ+wN7QjeJt8S8nJRYuZH1OjJjsbxAXTQ==} dependencies: - '@vitest/utils': 1.0.2 + '@vitest/utils': 1.0.4 p-limit: 5.0.0 pathe: 1.1.1 dev: true - /@vitest/snapshot@1.0.2: - resolution: {integrity: sha512-9ClDz2/aV5TfWA4reV7XR9p+hE0e7bifhwxlURugj3Fw0YXeTFzHmKCNEHd6wOIFMfthbGGwhlq7TOJ2jDO4/g==} + /@vitest/snapshot@1.0.4: + resolution: {integrity: sha512-vkfXUrNyNRA/Gzsp2lpyJxh94vU2OHT1amoD6WuvUAA12n32xeVZQ0KjjQIf8F6u7bcq2A2k969fMVxEsxeKYA==} dependencies: magic-string: 0.30.5 pathe: 1.1.1 pretty-format: 29.7.0 dev: true - /@vitest/spy@1.0.2: - resolution: {integrity: sha512-YlnHmDntp+zNV3QoTVFI5EVHV0AXpiThd7+xnDEbWnD6fw0TH/J4/+3GFPClLimR39h6nA5m0W4Bjm5Edg4A/A==} + /@vitest/spy@1.0.4: + resolution: {integrity: sha512-9ojTFRL1AJVh0hvfzAQpm0QS6xIS+1HFIw94kl/1ucTfGCaj1LV/iuJU4Y6cdR03EzPDygxTHwE1JOm+5RCcvA==} dependencies: tinyspy: 2.2.0 dev: true - /@vitest/utils@1.0.2: - resolution: {integrity: sha512-GPQkGHAnFAP/+seSbB9pCsj339yRrMgILoI5H2sPevTLCYgBq0VRjF8QSllmnQyvf0EontF6KUIt2t5s2SmqoQ==} + /@vitest/utils@1.0.4: + resolution: {integrity: sha512-gsswWDXxtt0QvtK/y/LWukN7sGMYmnCcv1qv05CsY6cU/Y1zpGX1QuvLs+GO1inczpE6Owixeel3ShkjhYtGfA==} dependencies: diff-sequences: 29.6.3 loupe: 2.3.7 @@ -1794,9 +1777,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} dependencies: debug: 4.3.4 transitivePeerDependencies: @@ -2038,30 +2021,30 @@ packages: semver: 7.5.4 dev: true - /bumpp@9.2.0: - resolution: {integrity: sha512-pgp7y3jp33QTaXFVDrE0IKuZF5Y8EsIz+ywZXFALW2nD+ZD+4crxJe/GypBQBoJuZrr5dc6TGrR3wl7fk3+C6w==} + /bumpp@9.2.1: + resolution: {integrity: sha512-mq6/e8+bnIsOMy1VceTLC49WucMIZqd2nYn0e7Et5LhTO3yYQ8OWJsTl/B+uJDs5eywZmJ4Yt1WTEd2HCI35pw==} engines: {node: '>=10'} hasBin: true dependencies: '@jsdevtools/ez-spawn': 3.0.4 - c12: 1.4.2 + c12: 1.5.1 cac: 6.7.14 - fast-glob: 3.3.1 + fast-glob: 3.3.2 prompts: 2.4.2 semver: 7.5.4 transitivePeerDependencies: - supports-color dev: true - /c12@1.4.2: - resolution: {integrity: sha512-3IP/MuamSVRVw8W8+CHWAz9gKN4gd+voF2zm/Ln6D25C2RhytEZ1ABbC8MjKr4BR9rhoV1JQ7jJA158LDiTkLg==} + /c12@1.5.1: + resolution: {integrity: sha512-BWZRJgDEveT8uI+cliCwvYSSSSvb4xKoiiu5S0jaDbKBopQLQF7E+bq9xKk1pTcG+mUa3yXuFO7bD9d8Lr9Xxg==} dependencies: chokidar: 3.5.3 defu: 6.1.2 dotenv: 16.3.1 - giget: 1.1.2 - jiti: 1.19.3 - mlly: 1.4.0 + giget: 1.1.3 + jiti: 1.21.0 + mlly: 1.4.2 ohash: 1.1.3 pathe: 1.1.1 perfect-debounce: 1.0.0 @@ -2103,7 +2086,7 @@ packages: check-error: 1.0.3 deep-eql: 4.1.3 get-func-name: 2.0.2 - loupe: 2.3.6 + loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 dev: true @@ -2717,21 +2700,21 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /eslint-doc-generator@1.6.1(eslint@8.55.0)(typescript@5.3.3): + /eslint-doc-generator@1.6.1(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-X9NmwwUBxIUSS5CVXJ/vjz/eRD2H/NMhi4ZrnBRSuiAEQO5tjaQeSuHZ3wrUt8cZj0KaXWw8d7xI38JszGpSUw==} engines: {node: ^14.18.0 || ^16.0.0 || >=18.0.0} hasBin: true peerDependencies: eslint: '>= 7' dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3) ajv: 8.11.2 boolean: 3.2.0 commander: 10.0.0 cosmiconfig: 8.0.0 deepmerge: 4.2.2 dot-prop: 7.2.0 - eslint: 8.55.0 + eslint: 8.56.0 jest-diff: 29.3.1 json-schema-traverse: 1.0.0 markdown-table: 3.0.3 @@ -2752,7 +2735,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.55.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2773,55 +2756,55 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3) debug: 3.2.7 - eslint: 8.55.0 + eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-es@3.0.1(eslint@8.55.0): + /eslint-plugin-es@3.0.1(eslint@8.56.0): resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-es@4.1.0(eslint@8.55.0): + /eslint-plugin-es@4.1.0(eslint@8.56.0): resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-eslint-comments@3.2.0(eslint@8.55.0): + /eslint-plugin-eslint-comments@3.2.0(eslint@8.56.0): resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} engines: {node: '>=6.5.0'} peerDependencies: eslint: '>=4.19.1' dependencies: escape-string-regexp: 1.0.5 - eslint: 8.55.0 + eslint: 8.56.0 ignore: 5.2.4 dev: true - /eslint-plugin-eslint-plugin@5.1.1(eslint@8.55.0): - resolution: {integrity: sha512-4MGDsG505Ot2TSDSYxFL0cpDo4Y+t6hKB8cfZw9Jx484VjXWDfiYC/A6cccWFtWoOOC0j+wGgQIIb11cdIAMBg==} + /eslint-plugin-eslint-plugin@5.2.1(eslint@8.56.0): + resolution: {integrity: sha512-W+WergGahmRTz5yhw/+6TVqlXZkxucK0rM6KWRjona3MYx8+QJ+9KpXn3sYi1lgLduitfmT8YiAmO4RPC/mxEQ==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.55.0 - eslint-utils: 3.0.0(eslint@8.55.0) + eslint: 8.56.0 + eslint-utils: 3.0.0(eslint@8.56.0) estraverse: 5.3.0 dev: true @@ -2831,7 +2814,7 @@ packages: htmlparser2: 8.0.2 dev: true - /eslint-plugin-import@2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.55.0): + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.56.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} peerDependencies: @@ -2841,16 +2824,16 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3) array-includes: 3.1.6 array.prototype.findlastindex: 1.2.2 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.55.0 + eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.55.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -2866,7 +2849,7 @@ packages: - supports-color dev: true - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.55.0): + /eslint-plugin-jsx-a11y@6.7.1(eslint@8.56.0): resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: @@ -2881,7 +2864,7 @@ packages: axobject-query: 3.2.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 8.55.0 + eslint: 8.56.0 has: 1.0.3 jsx-ast-utils: 3.3.3 language-tags: 1.0.5 @@ -2891,28 +2874,28 @@ packages: semver: 6.3.1 dev: true - /eslint-plugin-markdown@3.0.1(eslint@8.55.0): + /eslint-plugin-markdown@3.0.1(eslint@8.56.0): resolution: {integrity: sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 mdast-util-from-markdown: 0.8.5 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-n@15.7.0(eslint@8.55.0): + /eslint-plugin-n@15.7.0(eslint@8.56.0): resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==} engines: {node: '>=12.22.0'} peerDependencies: eslint: '>=7.0.0' dependencies: builtins: 5.0.1 - eslint: 8.55.0 - eslint-plugin-es: 4.1.0(eslint@8.55.0) - eslint-utils: 3.0.0(eslint@8.55.0) + eslint: 8.56.0 + eslint-plugin-es: 4.1.0(eslint@8.56.0) + eslint-utils: 3.0.0(eslint@8.56.0) ignore: 5.2.4 is-core-module: 2.11.0 minimatch: 3.1.2 @@ -2920,14 +2903,14 @@ packages: semver: 7.5.4 dev: true - /eslint-plugin-node@11.1.0(eslint@8.55.0): + /eslint-plugin-node@11.1.0(eslint@8.56.0): resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=5.16.0' dependencies: - eslint: 8.55.0 - eslint-plugin-es: 3.0.1(eslint@8.55.0) + eslint: 8.56.0 + eslint-plugin-es: 3.0.1(eslint@8.56.0) eslint-utils: 2.1.0 ignore: 5.2.0 minimatch: 3.0.4 @@ -2935,25 +2918,25 @@ packages: semver: 6.3.0 dev: true - /eslint-plugin-promise@6.1.1(eslint@8.55.0): + /eslint-plugin-promise@6.1.1(eslint@8.56.0): resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 dev: true - /eslint-plugin-react-hooks@4.6.0(eslint@8.55.0): + /eslint-plugin-react-hooks@4.6.0(eslint@8.56.0): resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 dev: true - /eslint-plugin-react@7.33.2(eslint@8.55.0): + /eslint-plugin-react@7.33.2(eslint@8.56.0): resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} engines: {node: '>=4'} peerDependencies: @@ -2964,7 +2947,7 @@ packages: array.prototype.tosorted: 1.1.1 doctrine: 2.1.0 es-iterator-helpers: 1.0.13 - eslint: 8.55.0 + eslint: 8.56.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.3 minimatch: 3.1.2 @@ -2978,17 +2961,17 @@ packages: string.prototype.matchall: 4.0.8 dev: true - /eslint-plugin-unicorn@46.0.1(eslint@8.55.0): + /eslint-plugin-unicorn@46.0.1(eslint@8.56.0): resolution: {integrity: sha512-setGhMTiLAddg1asdwjZ3hekIN5zLznNa5zll7pBPwFOka6greCKDQydfqy4fqyUhndi74wpDzClSQMEcmOaew==} engines: {node: '>=14.18'} peerDependencies: eslint: '>=8.28.0' dependencies: '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) ci-info: 3.7.1 clean-regexp: 1.0.0 - eslint: 8.55.0 + eslint: 8.56.0 esquery: 1.5.0 indent-string: 4.0.0 is-builtin-module: 3.2.0 @@ -3003,7 +2986,7 @@ packages: strip-indent: 3.0.0 dev: true - /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.55.0): + /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.56.0): resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3013,14 +2996,14 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.55.0)(typescript@5.3.3) - eslint: 8.55.0 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 eslint-rule-composer: 0.3.0 dev: true - /eslint-plugin-vitest@0.3.10(@typescript-eslint/eslint-plugin@6.13.2)(eslint@8.55.0)(typescript@5.3.3)(vitest@1.0.2): - resolution: {integrity: sha512-08lj4rdhZHYyHk+Py2nJ7SlE6arP8GNfGXl9jVqhe9s5JoZIGiBpIkLGX+VNBiB6vXTn56H6Ant7Koc6XzRjtQ==} - engines: {node: 14.x || >= 16} + /eslint-plugin-vitest@0.3.17(@typescript-eslint/eslint-plugin@6.14.0)(eslint@8.56.0)(typescript@5.3.3)(vitest@1.0.4): + resolution: {integrity: sha512-JzljEhaJ3YDNJc4n2VTlOdMhElwLsQQprVtgY+eoKQkearKiFP53Vw3515J3jb4ZM8TVnpk7UsIFXM0gbhz+vQ==} + engines: {node: ^18.0.0 || >= 20.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': '*' eslint: '>=8.0.0' @@ -3031,10 +3014,10 @@ packages: vitest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.13.2(@typescript-eslint/parser@6.4.1)(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.13.2(eslint@8.55.0)(typescript@5.3.3) - eslint: 8.55.0 - vitest: 1.0.2(@types/node@20.10.4) + '@typescript-eslint/eslint-plugin': 6.14.0(@typescript-eslint/parser@6.4.1)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + vitest: 1.0.4(@types/node@20.10.4) transitivePeerDependencies: - supports-color - typescript @@ -3044,7 +3027,7 @@ packages: resolution: {integrity: sha512-XL9PqGBDL4rORnQ74b/3tqbJUpMlPz9gzKSrmYFtakLBQ/ayBELB/HZvd6ZEl+mH0vBeSYtUH7E/rawBsf9Qzg==} dev: true - /eslint-remote-tester@3.0.1(eslint@8.55.0)(ts-node@10.9.2): + /eslint-remote-tester@3.0.1(eslint@8.56.0)(ts-node@10.9.2): resolution: {integrity: sha512-/jifRW0gJ5NmrWGD8mn2imvafO0fS6KBKLzv8ZIdI1uMHZ2EriYN7Fw4cyOR7rfbt6Ve2tUrluSvVptW1PxEvg==} engines: {node: '>=12.11'} hasBin: true @@ -3058,7 +3041,7 @@ packages: '@babel/code-frame': 7.22.13 JSONStream: 1.3.5 chalk: 4.1.2 - eslint: 8.55.0 + eslint: 8.56.0 ink: 3.2.0(react@17.0.2) object-hash: 3.0.0 react: 17.0.2 @@ -3098,13 +3081,13 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils@3.0.0(eslint@8.55.0): + /eslint-utils@3.0.0(eslint@8.56.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 2.1.0 dev: true @@ -3122,15 +3105,15 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint@8.55.0: - resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/regexpp': 4.7.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.55.0 + '@eslint/js': 8.56.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -3233,6 +3216,17 @@ packages: merge2: 1.4.1 micromatch: 4.0.4 + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: true + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -3387,17 +3381,17 @@ packages: resolve-pkg-maps: 1.0.0 dev: true - /giget@1.1.2: - resolution: {integrity: sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==} + /giget@1.1.3: + resolution: {integrity: sha512-zHuCeqtfgqgDwvXlR84UNgnJDuUHQcNI5OqWqFxxuk2BshuKbYhJWdxBsEo4PvKqoGh23lUAIvBNpChMLv7/9Q==} hasBin: true dependencies: colorette: 2.0.20 defu: 6.1.2 - https-proxy-agent: 5.0.1 + https-proxy-agent: 7.0.2 mri: 1.2.0 - node-fetch-native: 1.3.3 + node-fetch-native: 1.4.1 pathe: 1.1.1 - tar: 6.1.15 + tar: 6.2.0 transitivePeerDependencies: - supports-color dev: true @@ -3549,11 +3543,11 @@ packages: entities: 4.5.0 dev: true - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} dependencies: - agent-base: 6.0.2 + agent-base: 7.1.0 debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -3937,6 +3931,11 @@ packages: hasBin: true dev: true + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -4077,13 +4076,6 @@ packages: js-tokens: 4.0.0 dev: true - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} - deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 - dependencies: - get-func-name: 2.0.2 - dev: true - /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: @@ -4310,8 +4302,8 @@ packages: tslib: 2.4.1 dev: true - /node-fetch-native@1.3.3: - resolution: {integrity: sha512-dw7R7GkbPkgC2jfEtJjvF2t3eJ/2+Pj1crKjbowhgnkMsuehYx6LUvfDG4FmWX20KYddJCZbQG8kZE9LNrf5GQ==} + /node-fetch-native@1.4.1: + resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==} dev: true /node-releases@2.0.13: @@ -5161,8 +5153,8 @@ packages: engines: {node: '>= 0.4'} dev: true - /tar@6.1.15: - resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} engines: {node: '>=10'} dependencies: chownr: 2.0.0 @@ -5452,7 +5444,7 @@ packages: dependencies: '@babel/core': 7.22.10 '@babel/standalone': 7.22.10 - '@babel/types': 7.23.5 + '@babel/types': 7.23.6 defu: 6.1.2 jiti: 1.19.3 mri: 1.2.0 @@ -5488,8 +5480,8 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite-node@1.0.2(@types/node@20.10.4): - resolution: {integrity: sha512-h7BbMJf46fLvFW/9Ygo3snkIBEHFh6fHpB4lge98H5quYrDhPFeI3S0LREz328uqPWSnii2yeJXktQ+Pmqk5BQ==} + /vite-node@1.0.4(@types/node@20.10.4): + resolution: {integrity: sha512-9xQQtHdsz5Qn8hqbV7UKqkm8YkJhzT/zr41Dmt5N7AlD8hJXw/Z7y0QiD5I8lnTthV9Rvcvi0QW7PI0Fq83ZPg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true dependencies: @@ -5545,8 +5537,8 @@ packages: fsevents: 2.3.3 dev: true - /vitest@1.0.2(@types/node@20.10.4): - resolution: {integrity: sha512-F3NVwwpXfRSDnJmyv+ALPwSRVt0zDkRRE18pwUHSUPXAlWQ47rY1dc99ziMW5bBHyqwK2ERjMisLNoef64qk9w==} + /vitest@1.0.4(@types/node@20.10.4): + resolution: {integrity: sha512-s1GQHp/UOeWEo4+aXDOeFBJwFzL6mjycbQwwKWX2QcYfh/7tIerS59hWQ20mxzupTJluA2SdwiBuWwQHH67ckg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -5571,11 +5563,11 @@ packages: optional: true dependencies: '@types/node': 20.10.4 - '@vitest/expect': 1.0.2 - '@vitest/runner': 1.0.2 - '@vitest/snapshot': 1.0.2 - '@vitest/spy': 1.0.2 - '@vitest/utils': 1.0.2 + '@vitest/expect': 1.0.4 + '@vitest/runner': 1.0.4 + '@vitest/snapshot': 1.0.4 + '@vitest/spy': 1.0.4 + '@vitest/utils': 1.0.4 acorn-walk: 8.3.1 cac: 6.7.14 chai: 4.3.10 @@ -5590,7 +5582,7 @@ packages: tinybench: 2.5.1 tinypool: 0.8.1 vite: 5.0.7(@types/node@20.10.4) - vite-node: 1.0.2(@types/node@20.10.4) + vite-node: 1.0.4(@types/node@20.10.4) why-is-node-running: 2.2.2 transitivePeerDependencies: - less diff --git a/scripts/chain-permutations.mjs b/scripts/chain-permutations.mjs deleted file mode 100644 index 20ff103..0000000 --- a/scripts/chain-permutations.mjs +++ /dev/null @@ -1,108 +0,0 @@ -// imported from https://github.com/veritem/eslint-plugin-vitest/pull/293 -// This script generates all possible permutations for vitest methods -import { per } from "percom"; - -const data = [ - { - names: ["beforeEach", "beforeAll", "afterEach", "afterAll"], - first: [], - conditions: [], - methods: [], - last: [], - }, - { - names: ["it", "test"], - first: ["extend"], - conditions: ["skipIf", "runIf"], - methods: ["skip", "only", "concurrent", "sequential", "todo", "fails"], - last: ["each"], - }, - { - names: ["bench"], - first: [], - conditions: ["skipIf", "runIf"], - methods: ["skip", "only", "todo"], - last: [], - }, - { - names: ["describe"], - first: [], - conditions: ["skipIf", "runIf"], - methods: ["skip", "only", "concurrent", "sequential", "shuffle", "todo"], - last: ["each"], - }, -]; - -const DEPTH = 3; - -const allPermutations = []; - -const join = (methods) => methods.filter((method) => !!method).join("."); -const depths = (maxDepth) => Array.from({ length: maxDepth }, (_, i) => i); - -data.forEach((q) => { - q.names.map((name) => { - allPermutations.push(name); - - const maxDepth = Math.min(DEPTH, q.methods.length); - const methodPerms = depths(maxDepth).flatMap((i) => [ - ...per(q.methods, i + 1), - ...q.first.flatMap((first) => - (per(q.methods, i) || [""]).map((p) => [first, ...p]) - ), - ...q.conditions.flatMap((condition) => - (per(q.methods, i) || [""]).map((p) => [condition, ...p]) - ), - ...q.last.flatMap((last) => - (per(q.methods, i) || [""]).map((p) => [...p, last]) - ), - ...(i > 0 - ? q.first.flatMap((first) => - q.conditions.flatMap((condition) => - (per(q.methods, i - 1) || [""]).map((p) => [ - first, - condition, - ...p, - ]) - ) - ) - : []), - ...(i > 0 - ? q.first.flatMap((first) => - q.last.flatMap((last) => - (per(q.methods, i - 1) || [""]).map((p) => [first, ...p, last]) - ) - ) - : []), - ...(i > 0 - ? q.conditions.flatMap((condition) => - q.last.flatMap((last) => - (per(q.methods, i - 1) || [""]).map((p) => [ - condition, - ...p, - last, - ]) - ) - ) - : []), - ...(i > 1 - ? q.first.flatMap((first) => - q.conditions.flatMap((condition) => - q.last.flatMap((last) => - (per(q.methods, i - 2) || [""]).map((p) => [ - first, - condition, - ...p, - last, - ]) - ) - ) - ) - : []), - ]); - const allPerms = methodPerms.map((p) => [name, ...p].join(".")); - allPermutations.push(...allPerms); - }); -}); - -console.log(allPermutations); diff --git a/scripts/chain-permutations.ts b/scripts/chain-permutations.ts new file mode 100644 index 0000000..a7f0c0f --- /dev/null +++ b/scripts/chain-permutations.ts @@ -0,0 +1,107 @@ +// imported from https://github.com/veritem/eslint-plugin-vitest/pull/293 +// This script generates all possible permutations for vitest methods +import { per } from 'percom' + +const data = [ + { + names: ['beforeEach', 'beforeAll', 'afterEach', 'afterAll'], + first: [], + conditions: [], + methods: [], + last: [] + }, + { + names: ['it', 'test'], + first: ['extend'], + conditions: ['skipIf', 'runIf'], + methods: ['skip', 'only', 'concurrent', 'sequential', 'todo', 'fails'], + last: ['each'] + }, + { + names: ['bench'], + first: [], + conditions: ['skipIf', 'runIf'], + methods: ['skip', 'only', 'todo'], + last: [] + }, + { + names: ['describe'], + first: [], + conditions: ['skipIf', 'runIf'], + methods: ['skip', 'only', 'concurrent', 'sequential', 'shuffle', 'todo'], + last: ['each'] + } +] + +const DEPTH = 3 + +const allPermutations: string[] = [] + +const depths = (maxDepth) => Array.from({ length: maxDepth }, (_, i) => i) + +data.forEach((q) => { + q.names.forEach((name) => { + allPermutations.push(name) + + const maxDepth = Math.min(DEPTH, q.methods.length) + const methodPerms = depths(maxDepth).flatMap((i) => [ + ...per(q.methods, i + 1), + ...q.first.flatMap((first) => + (per(q.methods, i) || ['']).map((p) => [first, ...p]) + ), + ...q.conditions.flatMap((condition) => + (per(q.methods, i) || ['']).map((p) => [condition, ...p]) + ), + ...q.last.flatMap((last) => + (per(q.methods, i) || ['']).map((p) => [...p, last]) + ), + ...(i > 0 + ? q.first.flatMap((first) => + q.conditions.flatMap((condition) => + (per(q.methods, i - 1) || ['']).map((p) => [ + first, + condition, + ...p + ]) + ) + ) + : []), + ...(i > 0 + ? q.first.flatMap((first) => + q.last.flatMap((last) => + (per(q.methods, i - 1) || ['']).map((p) => [first, ...p, last]) + ) + ) + : []), + ...(i > 0 + ? q.conditions.flatMap((condition) => + q.last.flatMap((last) => + (per(q.methods, i - 1) || ['']).map((p) => [ + condition, + ...p, + last + ]) + ) + ) + : []), + ...(i > 1 + ? q.first.flatMap((first) => + q.conditions.flatMap((condition) => + q.last.flatMap((last) => + (per(q.methods, i - 2) || ['']).map((p) => [ + first, + condition, + ...p, + last + ]) + ) + ) + ) + : []) + ]) + const allPerms = methodPerms.map((p) => [name, ...p].join('.')) + allPermutations.push(...allPerms) + }) +}) + +console.log(allPermutations) diff --git a/src/index.ts b/src/index.ts index 1474e40..1b037db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,7 @@ import preferSpyOn, { RULE_NAME as preferSpyOnName } from './rules/prefer-spy-on import preferComparisonMatcher, { RULE_NAME as preferComparisonMatcherName } from './rules/prefer-comparison-matcher' import preferToContain, { RULE_NAME as preferToContainName } from './rules/prefer-to-contain' import preferCalledExactlyOnceWith, { RULE_NAME as preferCalledExactlyOnceWithName } from './rules/prefer-called-exactly-once-with' +import preferExpectAssertions, {RULE_NAME as preferExpectAssertionsName} from './rules/prefer-expect-assertions' // import unboundMethod, { RULE_NAME as unboundMethodName } from './rules/unbound-method' const createConfig = (rules: Record) => ({ @@ -105,7 +106,8 @@ const allRules = { [preferSpyOnName]: 'warn', [preferComparisonMatcherName]: 'warn', [preferToContainName]: 'warn', - [preferCalledExactlyOnceWithName]: 'warn' + [preferCalledExactlyOnceWithName]: 'warn', + [preferExpectAssertionsName]: 'warn' // [unboundMethodName]: 'warn' } @@ -174,7 +176,8 @@ export default { [preferSpyOnName]: preferSpyOn, [preferComparisonMatcherName]: preferComparisonMatcher, [preferToContainName]: preferToContain, - [preferCalledExactlyOnceWithName]: preferCalledExactlyOnceWith + [preferCalledExactlyOnceWithName]: preferCalledExactlyOnceWith, + [preferExpectAssertionsName]: preferExpectAssertions // [unboundMethodName]: unboundMethod }, configs: { diff --git a/src/rules/prefer-expect-assertions.ts b/src/rules/prefer-expect-assertions.ts new file mode 100644 index 0000000..87c9b50 --- /dev/null +++ b/src/rules/prefer-expect-assertions.ts @@ -0,0 +1,239 @@ +import { AST_NODE_TYPES, type TSESLint, type TSESTree } from '@typescript-eslint/utils' +import { createEslintRule, getAccessorValue, isFunction, removeExtraArgumentsFixer } from '../utils' +import { ParsedExpectVitestFnCall, isTypeOfVitestFnCall, parseVitestFnCall } from '../utils/parseVitestFnCall' + +type Options = { + onlyFunctionsWithAsyncKeyword?: boolean; + onlyFunctionsWithExpectInLoop?: boolean; + onlyFunctionsWithExpectInCallback?: boolean +} + +export const RULE_NAME = 'prefer-expect-assertions' + +type MessageIds = + | 'hasAssertionsTakesNoArguments' + | 'assertionsRequiresOneArgument' + | 'assertionsRequiresNumberArgument' + | 'haveExpectAssertions' + | 'suggestAddingHasAssertions' + | 'suggestAddingAssertions' + | 'suggestRemovingExtraArguments'; + +const isFirstStatement = (node: TSESTree.CallExpression): boolean => { + let parent: TSESTree.Node['parent'] = node + + while (parent) { + if (parent.parent?.type === AST_NODE_TYPES.BlockStatement) + return parent.parent.body[0] === parent + + if (parent.parent?.type === AST_NODE_TYPES.ArrowFunctionExpression) + return true + + parent = parent.parent + } + + throw new Error('Could not find parent block statement') +} + +const suggestRemovingExtraArguments = (context: TSESLint.RuleContext, + func: TSESTree.CallExpression, + from: number): TSESLint.ReportSuggestionArray[0] => ({ + messageId: 'suggestRemovingExtraArguments', + fix: fixer => removeExtraArgumentsFixer(fixer, context, func, from) + }) + +export default createEslintRule({ + name: 'prefer-expect-assertions', + meta: { + docs: { + description: 'Suggest using expect assertions instead of callbacks', + recommended: 'error' + }, + messages: { + hasAssertionsTakesNoArguments: + '`expect.hasAssertions` expects no arguments', + assertionsRequiresOneArgument: + '`expect.assertions` excepts a single argument of type number', + assertionsRequiresNumberArgument: 'This argument should be a number', + haveExpectAssertions: + 'Every test should have either `expect.assertions()` or `expect.hasAssertions()` as its first expression', + suggestAddingHasAssertions: 'Add `expect.hasAssertions()`', + suggestAddingAssertions: + 'Add `expect.assertions()`', + suggestRemovingExtraArguments: 'Remove extra arguments' + }, + type: 'suggestion', + hasSuggestions: true, + schema: [ + { + type: 'object', + properties: { + onlyFunctionsWithAsyncKeyword: { type: 'boolean' }, + onlyFunctionsWithExpectInLoop: { type: 'boolean' }, + onlyFunctionsWithExpectInCallback: { type: 'boolean' } + }, + additionalProperties: false + } + ] + }, + defaultOptions: [ + { + onlyFunctionsWithAsyncKeyword: false, + onlyFunctionsWithExpectInCallback: false, + onlyFunctionsWithExpectInLoop: false + } + ], + create(context, [options]) { + let expressionDepth = 0 + let hasExpectInCallBack = false + let hasExpectInLoop = false + let hasExpectAssertAsFirstStatement = false + let inTestCaseCall = false + let inForLoop = false + + const shouldCheckFunction = (testFunction: TSESTree.FunctionLike) => { + if (!options.onlyFunctionsWithAsyncKeyword && !options.onlyFunctionsWithExpectInCallback && !options.onlyFunctionsWithExpectInLoop) + return true + + if (options.onlyFunctionsWithAsyncKeyword) { + if (testFunction.async) + return true + } + + if (options.onlyFunctionsWithExpectInCallback) { + if (hasExpectInCallBack) + return true + } + + if (options.onlyFunctionsWithExpectInLoop) { + if (hasExpectInLoop) + return true + } + + return false + } + + function checkExpectHasAssertions(expectFnCall: ParsedExpectVitestFnCall, func: TSESTree.CallExpression) { + if (getAccessorValue(expectFnCall.members[0]) === 'hasAssertions') { + if (expectFnCall.args.length) { + context.report({ + messageId: 'hasAssertionsTakesNoArguments', + node: expectFnCall.matcher, + suggest: [suggestRemovingExtraArguments(context, func, 0)] + }) + } + return + } + + if (expectFnCall.args.length !== 1) { + let { loc } = expectFnCall.matcher + const suggestions: TSESLint.ReportSuggestionArray = [] + + if (expectFnCall.args.length) { + loc = expectFnCall.args[1].loc + suggestions.push(suggestRemovingExtraArguments(context, func, 1)) + } + + context.report({ + messageId: 'assertionsRequiresOneArgument', + suggest: suggestions, + loc + }) + return + } + + const [arg] = expectFnCall.args + + if (arg.type === AST_NODE_TYPES.Literal && typeof arg.value === 'number' && Number.isInteger(arg.value)) + return + + context.report({ + messageId: 'assertionsRequiresNumberArgument', + node: arg + }) + } + const enterExpression = () => (inTestCaseCall && expressionDepth++) + const exitExpression = () => (inTestCaseCall && expressionDepth--) + const enterForLoop = () => (inForLoop = true) + const exitForLoop = () => (inForLoop = false) + + return { + FunctionExpression: enterExpression, + 'FunctionExpression:exit': exitExpression, + ArrowFunctionExpression: enterExpression, + 'ArrowFunctionExpression:exit': exitExpression, + ForStatement: enterForLoop, + 'ForStatement:exit': exitForLoop, + ForInStatement: enterForLoop, + 'ForInStatement:exit': exitForLoop, + ForOfStatement: enterForLoop, + 'ForOfStatement:exit': exitForLoop, + CallExpression(node: TSESTree.CallExpression) { + const vitestFnCall = parseVitestFnCall(node, context) + + if (vitestFnCall?.type === 'test') { + inTestCaseCall = true + return + } + + if (vitestFnCall?.type === 'expect' && inTestCaseCall) { + if (expressionDepth === 1 && isFirstStatement(node) && vitestFnCall.head.node.parent?.type === AST_NODE_TYPES.MemberExpression && vitestFnCall.members.length === 1 && + ['assertions', 'hasAssertions'].includes(getAccessorValue(vitestFnCall.members[0]))) { + checkExpectHasAssertions(vitestFnCall, node) + hasExpectAssertAsFirstStatement = true + } + + if (inForLoop) + hasExpectInLoop = true + + if (expressionDepth > 1) + hasExpectInCallBack = true + } + }, + + 'CallExpression:exit'(node: TSESTree.CallExpression) { + if (!isTypeOfVitestFnCall(node, context, ['test'])) + return + + inTestCaseCall = false + + if (node.arguments.length < 2) + return + + const [, secondArg] = node.arguments + + if (!isFunction(secondArg) || !shouldCheckFunction(secondArg)) + return + + hasExpectInLoop = false + hasExpectInCallBack = false + + if (hasExpectAssertAsFirstStatement) { + hasExpectAssertAsFirstStatement = false + + return + } + + const suggestions: Array<[MessageIds, string]> = [] + + if (secondArg.body.type === AST_NODE_TYPES.BlockStatement) { + suggestions.push(['suggestAddingHasAssertions', 'expect.hasAssertions();'], + ['suggestAddingAssertions', 'expect.assertions();']) + } + + context.report({ + messageId: 'haveExpectAssertions', + node, + suggest: suggestions.map(([messageId, text]) => ({ + messageId, + fix: fixer => + fixer.insertTextBeforeRange( + [secondArg.body.range[0] + 1, secondArg.body.range[1]], + text + ) + })) + }) + } + } + } +}) diff --git a/tests/prefer-expect-assertions.test.ts b/tests/prefer-expect-assertions.test.ts new file mode 100644 index 0000000..c90ac55 --- /dev/null +++ b/tests/prefer-expect-assertions.test.ts @@ -0,0 +1,298 @@ +import rule, { RULE_NAME } from '../src/rules/prefer-expect-assertions' +import { ruleTester } from './ruleTester' + +ruleTester.run(RULE_NAME, rule, { + valid: [ + 'test("it1", () => {expect.assertions(0);})', + 'test("it1", function() {expect.assertions(0);})', + 'test("it1", function() {expect.hasAssertions();})', + 'it("it1", function() {expect.assertions(0);})', + 'test("it1")', + 'itHappensToStartWithIt("foo", function() {})', + 'testSomething("bar", function() {})', + 'it(async () => {expect.assertions(0);})', + { + code: ` + const expectNumbersToBeGreaterThan = (numbers, value) => { + for (let number of numbers) { + expect(number).toBeGreaterThan(value); + } + }; + + it('returns numbers that are greater than two', function () { + expectNumbersToBeGreaterThan(getNumbers(), 2); + }); + `, + options: [{ onlyFunctionsWithExpectInLoop: true }] + }, + { + code: ` + it("returns numbers that are greater than five", function () { + expect.assertions(2); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + options: [{ onlyFunctionsWithExpectInLoop: true }] + }, + { + code: `it("returns things that are less than ten", function () { + expect.hasAssertions(); + + for (const thing in things) { + expect(thing).toBeLessThan(10); + } + });`, + options: [{ onlyFunctionsWithExpectInLoop: true }] + } + ], + invalid: [ + { + code: 'it("it1", () => foo())', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: null + } + ] + }, + { + code: 'it(\'resolves\', () => expect(staged()).toBe(true));', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: null + } + ] + }, + { + code: 'it(\'resolves\', async () => expect(await staged()).toBe(true));', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: null + } + ] + }, + { + code: 'it("it1", () => {})', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: 'it("it1", () => {expect.hasAssertions();})' + }, + { + messageId: 'suggestAddingAssertions', + output: 'it("it1", () => {expect.assertions();})' + } + ] + } + ] + }, + { + code: 'it("it1", () => { foo()})', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: 'it("it1", () => {expect.hasAssertions(); foo()})' + }, + { + messageId: 'suggestAddingAssertions', + output: 'it("it1", () => {expect.assertions(); foo()})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {var a = 2;})', + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: + 'it("it1", function() {expect.hasAssertions();var a = 2;})' + }, + { + messageId: 'suggestAddingAssertions', + output: 'it("it1", function() {expect.assertions();var a = 2;})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {expect.assertions();})', + errors: [ + { + messageId: 'assertionsRequiresOneArgument', + column: 30, + line: 1, + suggestions: [] + } + ] + }, + { + code: 'it("it1", function() {expect.assertions(1,2);})', + errors: [ + { + messageId: 'assertionsRequiresOneArgument', + column: 43, + line: 1, + suggestions: [ + { + messageId: 'suggestRemovingExtraArguments', + output: 'it("it1", function() {expect.assertions(1,);})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {expect.assertions(1,2,);})', + errors: [ + { + messageId: 'assertionsRequiresOneArgument', + column: 43, + line: 1, + suggestions: [ + { + messageId: 'suggestRemovingExtraArguments', + output: 'it("it1", function() {expect.assertions(1,);})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {expect.assertions("1");})', + errors: [ + { + messageId: 'assertionsRequiresNumberArgument', + column: 41, + line: 1, + suggestions: [] + } + ] + }, + { + code: 'it("it1", function() {expect.hasAssertions("1");})', + errors: [ + { + messageId: 'hasAssertionsTakesNoArguments', + column: 30, + line: 1, + suggestions: [ + { + messageId: 'suggestRemovingExtraArguments', + output: 'it("it1", function() {expect.hasAssertions();})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {expect.hasAssertions("1",);})', + errors: [ + { + messageId: 'hasAssertionsTakesNoArguments', + column: 30, + line: 1, + suggestions: [ + { + messageId: 'suggestRemovingExtraArguments', + output: 'it("it1", function() {expect.hasAssertions();})' + } + ] + } + ] + }, + { + code: 'it("it1", function() {expect.hasAssertions("1", "2");})', + errors: [ + { + messageId: 'hasAssertionsTakesNoArguments', + column: 30, + line: 1, + suggestions: [ + { + messageId: 'suggestRemovingExtraArguments', + output: 'it("it1", function() {expect.hasAssertions();})' + } + ] + } + ] + }, + { + code: `it("it1", () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it("it1", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + });`, + options: [{ onlyFunctionsWithExpectInLoop: true }], + errors: [ + { + messageId: 'haveExpectAssertions', + column: 6, + line: 9, + } + ] + }, + { + code: `it("returns numbers that are greater than four", async () => { + for (const number of await getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + options: [{ onlyFunctionsWithExpectInLoop: true }], + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + line: 1, + }, + { + messageId: 'haveExpectAssertions', + column: 4, + line: 7, + }, + ], + }, + ] +}) diff --git a/vitest.config.ts b/vitest.config.mts similarity index 100% rename from vitest.config.ts rename to vitest.config.mts