eslint-config-typed 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/configs/typescript.mjs +2 -2
- package/dist/configs/typescript.mjs.map +1 -1
- package/dist/entry-point.d.mts +1 -1
- package/dist/entry-point.d.mts.map +1 -1
- package/dist/entry-point.mjs +6 -7
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.d.mts +11 -0
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.d.mts.map +1 -0
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs +217 -0
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/rules.d.mts +4 -0
- package/dist/plugins/ts-restrictions/rules/rules.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/rules.mjs +2 -0
- package/dist/plugins/ts-restrictions/rules/rules.mjs.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.d.mts +2 -1
- package/dist/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.mjs +5 -2
- package/dist/rules/eslint-ts-restrictions-rules.mjs.map +1 -1
- package/dist/rules/index.mjs +1 -1
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts +50 -0
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/package.json +1 -1
- package/src/configs/typescript.mts +2 -2
- package/src/entry-point.mts +14 -2
- package/src/plugins/ts-restrictions/rules/check-destructuring-completeness.mts +306 -0
- package/src/plugins/ts-restrictions/rules/check-destructuring-completeness.test.mts +158 -0
- package/src/plugins/ts-restrictions/rules/rules.mts +2 -0
- package/src/rules/eslint-ts-restrictions-rules.mts +7 -2
- package/src/types/rules/eslint-ts-restrictions-rules.mts +55 -0
package/README.md
CHANGED
|
@@ -499,18 +499,20 @@ Pre-configured rule sets that can be imported and customized:
|
|
|
499
499
|
| **`eslintImportsRules`** | `eslint-plugin-import-x` | Import/export rules |
|
|
500
500
|
| **`eslintSecurityRules`** | `eslint-plugin-security` | Security best practices |
|
|
501
501
|
| **`eslintTreeShakableRules`** | `eslint-plugin-tree-shakable` | Tree-shaking optimization rules |
|
|
502
|
+
| **`eslintStylisticRules`** | `@stylistic/eslint-plugin` | Stylistic formatting rules disabled to mirror Prettier |
|
|
503
|
+
| **`eslintTsRestrictionsRules`** | `eslint-plugin-ts-restrictions` | Restrict some syntax in TypeScript |
|
|
502
504
|
| **`eslintReactRules`** | `eslint-plugin-react` | React-specific rules |
|
|
503
505
|
| **`eslintReactHooksRules`** | `eslint-plugin-react-hooks` | React Hooks rules |
|
|
504
506
|
| **`eslintReactPerfRules`** | `eslint-plugin-react-perf` | React performance optimization rules |
|
|
505
507
|
| **`eslintReactRefreshRules`** | `eslint-plugin-react-refresh` | React Refresh (HMR) rules |
|
|
506
508
|
| **`eslintReactCodingStyleRules`** | `eslint-plugin-react-coding-style` | Opinionated React component style rules |
|
|
507
|
-
| **`eslintStylisticRules`** | `@stylistic/eslint-plugin` | Stylistic formatting rules disabled to mirror Prettier |
|
|
508
509
|
| **`eslintJsxA11yRules`** | `eslint-plugin-jsx-a11y` | Accessibility rules for JSX |
|
|
509
510
|
| **`eslintVitestRules`** | `eslint-plugin-vitest` | Vitest-specific rules |
|
|
510
511
|
| **`eslintJestRules`** | `eslint-plugin-jest` | Jest-specific rules |
|
|
511
512
|
| **`eslintTestingLibraryRules`** | `eslint-plugin-testing-library` | Testing Library rules |
|
|
512
513
|
| **`eslintPlaywrightRules`** | `eslint-plugin-playwright` | Playwright-specific rules |
|
|
513
514
|
| **`eslintCypressRules`** | `eslint-plugin-cypress` | Cypress-specific rules |
|
|
515
|
+
| **`eslintVitestCodingStyleRules`** | `eslint-plugin-vitest-coding-style` | Vitest best practices |
|
|
514
516
|
| **`eslintPluginRules`** | `eslint-plugin-eslint-plugin` | eslint-plugin development rules |
|
|
515
517
|
|
|
516
518
|
### Exported Pre-configured Rule Options
|
|
@@ -607,18 +609,22 @@ Each plugin provides typed rule definitions:
|
|
|
607
609
|
- **`EslintStrictDependenciesRules`** & **`EslintStrictDependenciesRulesOption`**
|
|
608
610
|
- **`EslintSecurityRules`** (no options)
|
|
609
611
|
- **`EslintTreeShakableRules`** (no options)
|
|
612
|
+
- **`EslintStylisticRules`** & **`EslintStylisticRulesOption`**
|
|
613
|
+
- **`EslintTsRestrictionsRules`** & **`EslintTsRestrictionsRulesOption`**
|
|
610
614
|
- React & JSX
|
|
611
615
|
- **`EslintReactRules`** & **`EslintReactRulesOption`**
|
|
612
616
|
- **`EslintReactHooksRules`** & **`EslintReactHooksRulesOption`**
|
|
613
617
|
- **`EslintReactPerfRules`** & **`EslintReactPerfRulesOption`**
|
|
614
618
|
- **`EslintReactRefreshRules`** & **`EslintReactRefreshRulesOption`**
|
|
615
619
|
- **`EslintJsxA11yRules`** & **`EslintJsxA11yRulesOption`**
|
|
620
|
+
- **`EslintReactCodingStyleRules`** & **`EslintReactCodingStyleRulesOption`**
|
|
616
621
|
- Testing
|
|
617
622
|
- **`EslintVitestRules`** & **`EslintVitestRulesOption`**
|
|
618
623
|
- **`EslintJestRules`** & **`EslintJestRulesOption`**
|
|
619
624
|
- **`EslintPlaywrightRules`** & **`EslintPlaywrightRulesOption`**
|
|
620
625
|
- **`EslintCypressRules`** & **`EslintCypressRulesOption`**
|
|
621
626
|
- **`EslintTestingLibraryRules`** & **`EslintTestingLibraryRulesOption`**
|
|
627
|
+
- **`EslintVitestCodingStyleRules`** (no options)
|
|
622
628
|
- Others
|
|
623
629
|
- **`EslintPluginRules`** & **`EslintPluginRulesOption`**
|
|
624
630
|
|
|
@@ -10,7 +10,7 @@ import { eslintSecurityRules } from '../rules/eslint-security-rules.mjs';
|
|
|
10
10
|
import { eslintStylisticRules } from '../rules/eslint-stylistic-rules.mjs';
|
|
11
11
|
import { eslintTotalFunctionsRules } from '../rules/eslint-total-functions-rules.mjs';
|
|
12
12
|
import { eslintTreeShakableRules } from '../rules/eslint-tree-shakable-rules.mjs';
|
|
13
|
-
import {
|
|
13
|
+
import { eslintTsRestrictionsRules } from '../rules/eslint-ts-restrictions-rules.mjs';
|
|
14
14
|
import { eslintUnicornRules } from '../rules/eslint-unicorn-rules.mjs';
|
|
15
15
|
import { typescriptEslintRules } from '../rules/typescript-eslint-rules.mjs';
|
|
16
16
|
import { eslintConfigForTypeScriptWithoutRules } from './typescript-without-rules.mjs';
|
|
@@ -36,7 +36,7 @@ const eslintConfigForTypeScript = ({ files, packageDirs, tsconfigFileName, tscon
|
|
|
36
36
|
...typescriptEslintRules,
|
|
37
37
|
...eslintTreeShakableRules,
|
|
38
38
|
...eslintPluginSortDestructureKeysRules,
|
|
39
|
-
...
|
|
39
|
+
...eslintTsRestrictionsRules,
|
|
40
40
|
'strict-dependencies/strict-dependencies': ['error', []],
|
|
41
41
|
'import-x/no-extraneous-dependencies': [
|
|
42
42
|
'error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.mjs","sources":["../../src/configs/typescript.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAyB,GAAG,CAAC,EACxC,KAAK,EACL,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GAOhB,KACA;AACE,IAAA,GAAG,qCAAqC,CAAC;QACvC,gBAAgB;QAChB,eAAe;KAChB,CAAC;AACF,IAAA;AACE,QAAA,KAAK,EAAE,KAAK,IAAI,CAAC,sCAAsC,CAAC;QACxD,KAAK,EAAE,gBAAgB,CAAC;AACtB,YAAA,GAAG,oBAAoB;AACvB,YAAA,GAAG,8BAA8B;AACjC,YAAA,GAAG,qBAAqB;AACxB,YAAA,GAAG,yBAAyB;AAC5B,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,WAAW;AACd,YAAA,GAAG,oBAAoB;AACvB,YAAA,GAAG,mBAAmB;AACtB,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,qBAAqB;AACxB,YAAA,GAAG,uBAAuB;AAC1B,YAAA,GAAG,oCAAoC;AACvC,YAAA,GAAG,
|
|
1
|
+
{"version":3,"file":"typescript.mjs","sources":["../../src/configs/typescript.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAyB,GAAG,CAAC,EACxC,KAAK,EACL,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GAOhB,KACA;AACE,IAAA,GAAG,qCAAqC,CAAC;QACvC,gBAAgB;QAChB,eAAe;KAChB,CAAC;AACF,IAAA;AACE,QAAA,KAAK,EAAE,KAAK,IAAI,CAAC,sCAAsC,CAAC;QACxD,KAAK,EAAE,gBAAgB,CAAC;AACtB,YAAA,GAAG,oBAAoB;AACvB,YAAA,GAAG,8BAA8B;AACjC,YAAA,GAAG,qBAAqB;AACxB,YAAA,GAAG,yBAAyB;AAC5B,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,WAAW;AACd,YAAA,GAAG,oBAAoB;AACvB,YAAA,GAAG,mBAAmB;AACtB,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,qBAAqB;AACxB,YAAA,GAAG,uBAAuB;AAC1B,YAAA,GAAG,oCAAoC;AACvC,YAAA,GAAG,yBAAyB;AAE5B,YAAA,yCAAyC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;AAExD,YAAA,qCAAqC,EAAE;gBACrC,OAAO;AACP,gBAAA;AACE,oBAAA,UAAU,EAAE,WAAW;AACxB,iBAAA;AACF,aAAA;YACD,IAAI,gBAAgB,KAAK;AACvB,kBAAE;AACE,oBAAA,iDAAiD,EAAE,KAAK;AACxD,oBAAA,2DAA2D,EACzD,KAAK;AACR;kBACD,EAAE,CAAC;SACR,CAAC;AACH,KAAA;AACD,IAAA;QACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;QAChC,KAAK,EAAE,gBAAgB,CAAC;AACtB,YAAA,kDAAkD,EAAE,KAAK;AACzD,YAAA,8BAA8B,EAAE,KAAK;SACtC,CAAC;AACH,KAAA;AACD,IAAA;QACE,KAAK,EAAE,CAAC,qBAAqB,CAAC;QAC9B,KAAK,EAAE,gBAAgB,CAAC;AACtB,YAAA,2CAA2C,EAAE,KAAK;AAClD,YAAA,sBAAsB,EAAE,KAAK;SAC9B,CAAC;AACH,KAAA;AACD,IAAA;AACE,QAAA,KAAK,EAAE;;;;;;;;YASL,qCAAqC;YAErC,uCAAuC;YAEvC,4CAA4C;YAC5C,gDAAgD;YAChD,qCAAqC;AACtC,SAAA;QACD,KAAK,EAAE,gBAAgB,CAAC;AACtB,YAAA,0CAA0C,EAAE,KAAK;AACjD,YAAA,4BAA4B,EAAE,KAAK;AACnC,YAAA,sCAAsC,EAAE,KAAK;AAC7C,YAAA,8BAA8B,EAAE,KAAK;AACrC,YAAA,8BAA8B,EAAE,KAAK;AACrC,YAAA,oBAAoB,EAAE,KAAK;SAC5B,CAAC;AACH,KAAA;;;;;"}
|
package/dist/entry-point.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { eslintConfigForTypeScriptWithoutRules, eslintConfigForTypeScript, eslintConfigForBrowser, eslintConfigForNodeJs, eslintConfigForReact, eslintConfigForPreact, eslintConfigForVitest, eslintConfigForJest, eslintConfigForPlaywright, eslintConfigForCypress, eslintConfigForTestingLibrary, eslintRules, typescriptEslintRules, eslintFunctionalRules, eslintTotalFunctionsRules, eslintUnicornRules, eslintArrayFuncRules, eslintPreferArrowFunctionRules, eslintPluginSortDestructureKeysRules, eslintImportsRules, eslintPromiseRules, eslintSecurityRules, eslintTreeShakableRules, eslintReactRules, eslintReactHooksRules, eslintReactPerfRules, eslintReactRefreshRules, eslintVitestRules, eslintJestRules, eslintJsxA11yRules, eslintTestingLibraryRules, eslintCypressRules, eslintPlaywrightRules, eslintPluginRules, restrictedGlobals, restrictedGlobalsForBrowser, restrictedSyntax,
|
|
1
|
+
export { eslintConfigForTypeScriptWithoutRules, eslintConfigForTypeScript, eslintConfigForBrowser, eslintConfigForNodeJs, eslintConfigForReact, eslintConfigForPreact, eslintConfigForVitest, eslintConfigForJest, eslintConfigForPlaywright, eslintConfigForCypress, eslintConfigForTestingLibrary, eslintRules, typescriptEslintRules, eslintFunctionalRules, eslintTotalFunctionsRules, eslintUnicornRules, eslintArrayFuncRules, eslintPreferArrowFunctionRules, eslintPluginSortDestructureKeysRules, eslintImportsRules, eslintPromiseRules, eslintSecurityRules, eslintTreeShakableRules, eslintReactRules, eslintReactHooksRules, eslintReactPerfRules, eslintReactRefreshRules, eslintVitestRules, eslintJestRules, eslintJsxA11yRules, eslintTestingLibraryRules, eslintCypressRules, eslintPlaywrightRules, eslintPluginRules, eslintTsRestrictionsRules, eslintReactCodingStyleRules, eslintStylisticRules, eslintVitestCodingStyleRules, restrictedGlobals, restrictedGlobalsForBrowser, restrictedSyntax, eslintPluginTotalFunctions, eslintPluginTreeShakable, eslintPluginStrictDependencies, eslintPluginTsRestrictions, eslintPluginVitestCodingStyle, eslintPluginReactCodingStyle, defineConfig, defineKnownRules, withDefaultOption, plugins, type EslintRules, type EslintRulesOption, type TypeScriptEslintRules, type TypeScriptEslintRulesOption, type EslintFunctionalRules, type EslintFunctionalRulesOption, type EslintTotalFunctionsRules, type EslintUnicornRules, type EslintUnicornRulesOption, type EslintArrayFuncRules, type EslintPreferArrowFunctionRules, type EslintPreferArrowFunctionRulesOption, type EslintPluginSortDestructureKeysRules, type EslintPluginSortDestructureKeysRulesOption, type EslintPromiseRules, type EslintPromiseRulesOption, type EslintImportsRules, type EslintImportsRulesOption, type EslintStrictDependenciesRules, type EslintStrictDependenciesRulesOption, type EslintReactCodingStyleRules, type EslintReactCodingStyleRulesOption, type EslintSecurityRules, type EslintTreeShakableRules, type EslintReactRules, type EslintReactRulesOption, type EslintReactHooksRules, type EslintReactHooksRulesOption, type EslintReactPerfRules, type EslintReactPerfRulesOption, type EslintReactRefreshRules, type EslintReactRefreshRulesOption, type EslintJsxA11yRules, type EslintJsxA11yRulesOption, type EslintVitestRules, type EslintVitestRulesOption, type EslintJestRules, type EslintJestRulesOption, type EslintPlaywrightRules, type EslintPlaywrightRulesOption, type EslintCypressRules, type EslintCypressRulesOption, type EslintTestingLibraryRules, type EslintTestingLibraryRulesOption, type EslintPluginRules, type EslintPluginRulesOption, type EslintStylisticRules, type EslintStylisticRulesOption, type EslintTsRestrictionsRules, type EslintTsRestrictionsRulesOption, type EslintVitestCodingStyleRules, type FlatConfig, type ESLintPlugin, type Rule, type Rules, } from './index.mjs';
|
|
2
2
|
//# sourceMappingURL=entry-point.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-point.d.mts","sourceRoot":"","sources":["../src/entry-point.mts"],"names":[],"mappings":"AACA,OAAO,EAEL,qCAAqC,EACrC,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,6BAA6B,EAG7B,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,8BAA8B,EAC9B,oCAAoC,EACpC,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"entry-point.d.mts","sourceRoot":"","sources":["../src/entry-point.mts"],"names":[],"mappings":"AACA,OAAO,EAEL,qCAAqC,EACrC,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,6BAA6B,EAG7B,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,8BAA8B,EAC9B,oCAAoC,EACpC,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,EACzB,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAG5B,iBAAiB,EACjB,2BAA2B,EAC3B,gBAAgB,EAGhB,0BAA0B,EAC1B,wBAAwB,EACxB,8BAA8B,EAC9B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAG5B,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EAGjB,OAAO,EAGP,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,8BAA8B,EACnC,KAAK,oCAAoC,EACzC,KAAK,oCAAoC,EACzC,KAAK,0CAA0C,EAC/C,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EAClC,KAAK,mCAAmC,EACxC,KAAK,2BAA2B,EAChC,KAAK,iCAAiC,EACtC,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACpC,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACpC,KAAK,4BAA4B,EAGjC,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,KAAK,GACX,MAAM,aAAa,CAAC"}
|
package/dist/entry-point.mjs
CHANGED
|
@@ -16,17 +16,20 @@ export { eslintPluginRules } from './rules/eslint-plugin-rules.mjs';
|
|
|
16
16
|
export { eslintPluginSortDestructureKeysRules } from './rules/eslint-plugin-sort-destructure-keys-rules.mjs';
|
|
17
17
|
export { eslintPreferArrowFunctionRules } from './rules/eslint-prefer-arrow-functions-rules.mjs';
|
|
18
18
|
export { eslintPromiseRules } from './rules/eslint-promise-rules.mjs';
|
|
19
|
+
export { eslintReactCodingStyleRules } from './rules/eslint-react-coding-style-rules.mjs';
|
|
19
20
|
export { eslintReactHooksRules } from './rules/eslint-react-hooks-rules.mjs';
|
|
20
21
|
export { eslintReactPerfRules } from './rules/eslint-react-perf-rules.mjs';
|
|
21
22
|
export { eslintReactRefreshRules } from './rules/eslint-react-refresh-rules.mjs';
|
|
22
23
|
export { eslintReactRules } from './rules/eslint-react-rules.mjs';
|
|
23
24
|
export { eslintRules, restrictedGlobals, restrictedGlobalsForBrowser, restrictedSyntax } from './rules/eslint-rules.mjs';
|
|
24
25
|
export { eslintSecurityRules } from './rules/eslint-security-rules.mjs';
|
|
25
|
-
|
|
26
|
+
export { eslintStylisticRules } from './rules/eslint-stylistic-rules.mjs';
|
|
26
27
|
export { eslintTestingLibraryRules } from './rules/eslint-testing-library-rules.mjs';
|
|
27
28
|
export { eslintTotalFunctionsRules } from './rules/eslint-total-functions-rules.mjs';
|
|
28
29
|
export { eslintTreeShakableRules } from './rules/eslint-tree-shakable-rules.mjs';
|
|
30
|
+
export { eslintTsRestrictionsRules } from './rules/eslint-ts-restrictions-rules.mjs';
|
|
29
31
|
export { eslintUnicornRules } from './rules/eslint-unicorn-rules.mjs';
|
|
32
|
+
export { eslintVitestCodingStyleRules } from './rules/eslint-vitest-coding-style-rules.mjs';
|
|
30
33
|
export { eslintVitestRules } from './rules/eslint-vitest-rules.mjs';
|
|
31
34
|
export { typescriptEslintRules } from './rules/typescript-eslint-rules.mjs';
|
|
32
35
|
export { defineConfig } from './types/define-config.mjs';
|
|
@@ -38,13 +41,9 @@ export { eslintConfigForTypeScriptWithoutRules } from './configs/typescript-with
|
|
|
38
41
|
export { eslintConfigForTypeScript } from './configs/typescript.mjs';
|
|
39
42
|
export { eslintConfigForVitest } from './configs/vitest.mjs';
|
|
40
43
|
export { eslintPluginReactCodingStyle } from './plugins/react-coding-style/plugin.mjs';
|
|
41
|
-
|
|
42
|
-
import 'micromatch';
|
|
43
|
-
import 'node:path';
|
|
44
|
-
import 'ts-data-forge';
|
|
45
|
-
import 'typescript';
|
|
44
|
+
export { eslintPluginStrictDependencies } from './plugins/strict-dependencies/plugin.mjs';
|
|
46
45
|
export { eslintPluginTotalFunctions } from './plugins/total-functions/plugin.mjs';
|
|
47
46
|
export { eslintPluginTreeShakable } from './plugins/tree-shakable/plugin.mjs';
|
|
48
47
|
export { eslintPluginTsRestrictions } from './plugins/ts-restrictions/plugin.mjs';
|
|
49
|
-
|
|
48
|
+
export { eslintPluginVitestCodingStyle } from './plugins/vitest-coding-style/plugin.mjs';
|
|
50
49
|
//# sourceMappingURL=entry-point.mjs.map
|
package/dist/entry-point.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -40,7 +40,7 @@ export { eslintStylisticRules } from './rules/eslint-stylistic-rules.mjs';
|
|
|
40
40
|
export { eslintTestingLibraryRules } from './rules/eslint-testing-library-rules.mjs';
|
|
41
41
|
export { eslintTotalFunctionsRules } from './rules/eslint-total-functions-rules.mjs';
|
|
42
42
|
export { eslintTreeShakableRules } from './rules/eslint-tree-shakable-rules.mjs';
|
|
43
|
-
export {
|
|
43
|
+
export { eslintTsRestrictionsRules } from './rules/eslint-ts-restrictions-rules.mjs';
|
|
44
44
|
export { eslintUnicornRules } from './rules/eslint-unicorn-rules.mjs';
|
|
45
45
|
export { eslintVitestCodingStyleRules } from './rules/eslint-vitest-coding-style-rules.mjs';
|
|
46
46
|
export { eslintVitestRules } from './rules/eslint-vitest-rules.mjs';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [
|
|
3
|
+
Readonly<{
|
|
4
|
+
alwaysCheckReactComponentProps?: boolean;
|
|
5
|
+
directiveKeyword?: string;
|
|
6
|
+
}>?
|
|
7
|
+
];
|
|
8
|
+
type MessageIds = 'incompleteDestructuring';
|
|
9
|
+
export declare const checkDestructuringCompleteness: TSESLint.RuleModule<MessageIds, Options>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=check-destructuring-completeness.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-destructuring-completeness.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/check-destructuring-completeness.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAGlC,KAAK,OAAO,GAAG,SAAS;IACtB,QAAQ,CAAC;QACP,8BAA8B,CAAC,EAAE,OAAO,CAAC;QACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC,CAAC;CACJ,CAAC;AAEF,KAAK,UAAU,GAAG,yBAAyB,CAAC;AA8D5C,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,UAAU,CAC9D,UAAU,EACV,OAAO,CAmOR,CAAC"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_DIRECTIVE_KEYWORD = '@check-destructuring-completeness';
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
5
|
+
const getObjectTypeProperties = (type) => {
|
|
6
|
+
try {
|
|
7
|
+
const properties = type.getProperties();
|
|
8
|
+
// Limit to reasonable number of properties to avoid hangs
|
|
9
|
+
if (properties.length > 1000) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
return properties
|
|
13
|
+
.map((prop) => prop.name)
|
|
14
|
+
.filter((name) =>
|
|
15
|
+
// Filter out symbol properties and internal properties
|
|
16
|
+
!name.startsWith('__') &&
|
|
17
|
+
// Only include string property names
|
|
18
|
+
typeof name === 'string' &&
|
|
19
|
+
name.length > 0);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// If there's any error getting properties, return empty array
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const isReactComponentFunction = (node) => {
|
|
27
|
+
if (node === undefined || node === null)
|
|
28
|
+
return false;
|
|
29
|
+
// Arrow function component
|
|
30
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
31
|
+
const { body } = node;
|
|
32
|
+
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
33
|
+
return body.body.some((statement) => {
|
|
34
|
+
if (statement.type !== AST_NODE_TYPES.ReturnStatement)
|
|
35
|
+
return false;
|
|
36
|
+
const { argument } = statement;
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
38
|
+
if (argument === null || argument === undefined)
|
|
39
|
+
return false;
|
|
40
|
+
const argType = argument.type;
|
|
41
|
+
return argType === 'JSXElement' || argType === 'JSXFragment';
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const bodyType = body.type;
|
|
45
|
+
return bodyType === 'JSXElement' || bodyType === 'JSXFragment';
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
};
|
|
49
|
+
const checkDestructuringCompleteness = {
|
|
50
|
+
meta: {
|
|
51
|
+
type: 'suggestion',
|
|
52
|
+
docs: {
|
|
53
|
+
description: 'Ensure all properties are destructured from an object when explicitly requested',
|
|
54
|
+
},
|
|
55
|
+
schema: [
|
|
56
|
+
{
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
alwaysCheckReactComponentProps: {
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
description: 'Always check React component props destructuring without directive keyword',
|
|
62
|
+
},
|
|
63
|
+
directiveKeyword: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Custom directive keyword to enable checking (default: "@check-destructuring-completeness")',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
additionalProperties: false,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
messages: {
|
|
72
|
+
incompleteDestructuring: 'Not all properties are destructured. Missing: {{missingProps}}',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
create: (context) => {
|
|
76
|
+
const parserServices = context.sourceCode.parserServices;
|
|
77
|
+
if (parserServices?.program === undefined ||
|
|
78
|
+
parserServices.program === null ||
|
|
79
|
+
parserServices.esTreeNodeToTSNodeMap === undefined) {
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
const options = context.options[0] ?? {};
|
|
83
|
+
const alwaysCheckReactComponentProps = options.alwaysCheckReactComponentProps ?? true;
|
|
84
|
+
const directiveKeyword = options.directiveKeyword ?? DEFAULT_DIRECTIVE_KEYWORD;
|
|
85
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
86
|
+
const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
|
|
87
|
+
const sourceCode = context.sourceCode;
|
|
88
|
+
const hasDirectiveComment = (node) => {
|
|
89
|
+
// Get the parent VariableDeclaration
|
|
90
|
+
const parent = node.parent;
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
92
|
+
if (parent?.type !== AST_NODE_TYPES.VariableDeclaration) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
96
|
+
const comments = sourceCode.getCommentsBefore(parent);
|
|
97
|
+
return comments.some((comment) => comment.value.includes(directiveKeyword));
|
|
98
|
+
};
|
|
99
|
+
const isReactComponentPropsDestructuring = (node) => {
|
|
100
|
+
if (!alwaysCheckReactComponentProps)
|
|
101
|
+
return false;
|
|
102
|
+
const parent = node.parent;
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
104
|
+
if (parent === undefined)
|
|
105
|
+
return false;
|
|
106
|
+
// Case 1: const { a, b } = props; inside component
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
108
|
+
if (parent.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
109
|
+
const grandParent = parent.parent;
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
111
|
+
if (grandParent === undefined)
|
|
112
|
+
return false;
|
|
113
|
+
// Check if we're inside a BlockStatement of an arrow function component
|
|
114
|
+
if (grandParent.type === AST_NODE_TYPES.BlockStatement) {
|
|
115
|
+
const greatGrandParent = grandParent.parent;
|
|
116
|
+
if (
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
118
|
+
greatGrandParent?.type === AST_NODE_TYPES.ArrowFunctionExpression &&
|
|
119
|
+
node.init?.type === AST_NODE_TYPES.Identifier) {
|
|
120
|
+
const initName =
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
122
|
+
node.init.type === AST_NODE_TYPES.Identifier
|
|
123
|
+
? node.init.name
|
|
124
|
+
: undefined;
|
|
125
|
+
if (initName !== undefined &&
|
|
126
|
+
greatGrandParent.params.some((param) => param.type === AST_NODE_TYPES.Identifier &&
|
|
127
|
+
param.name === initName)) {
|
|
128
|
+
return isReactComponentFunction(greatGrandParent);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (grandParent.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
133
|
+
return isReactComponentFunction(grandParent);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
};
|
|
138
|
+
const checkNode = (node) => {
|
|
139
|
+
if (node.id.type !== AST_NODE_TYPES.ObjectPattern)
|
|
140
|
+
return;
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
142
|
+
if (node.init === undefined || node.init === null)
|
|
143
|
+
return;
|
|
144
|
+
const shouldCheck = hasDirectiveComment(node) || isReactComponentPropsDestructuring(node);
|
|
145
|
+
if (!shouldCheck)
|
|
146
|
+
return;
|
|
147
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
148
|
+
const tsNode = esTreeNodeToTSNodeMap.get(node.init);
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
150
|
+
if (tsNode === undefined)
|
|
151
|
+
return;
|
|
152
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
153
|
+
const objectProps = getObjectTypeProperties(type);
|
|
154
|
+
const destructuredProps = new Set();
|
|
155
|
+
for (const prop of node.id.properties) {
|
|
156
|
+
if (prop.type === AST_NODE_TYPES.Property &&
|
|
157
|
+
prop.key.type === AST_NODE_TYPES.Identifier) {
|
|
158
|
+
// eslint-disable-next-line functional/immutable-data
|
|
159
|
+
destructuredProps.add(prop.key.name);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const missingProps = objectProps.filter((prop) => !destructuredProps.has(prop));
|
|
163
|
+
if (missingProps.length > 0) {
|
|
164
|
+
context.report({
|
|
165
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
166
|
+
node: node.id,
|
|
167
|
+
messageId: 'incompleteDestructuring',
|
|
168
|
+
data: {
|
|
169
|
+
missingProps: missingProps.join(', '),
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
VariableDeclarator: checkNode,
|
|
176
|
+
ArrowFunctionExpression: (node) => {
|
|
177
|
+
if (!alwaysCheckReactComponentProps)
|
|
178
|
+
return;
|
|
179
|
+
if (!isReactComponentFunction(node))
|
|
180
|
+
return;
|
|
181
|
+
for (const param of node.params) {
|
|
182
|
+
if (param.type === AST_NODE_TYPES.ObjectPattern) {
|
|
183
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
184
|
+
const tsNode = esTreeNodeToTSNodeMap.get(param);
|
|
185
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
186
|
+
if (tsNode === undefined)
|
|
187
|
+
continue;
|
|
188
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
189
|
+
const objectProps = getObjectTypeProperties(type);
|
|
190
|
+
const destructuredProps = new Set();
|
|
191
|
+
for (const prop of param.properties) {
|
|
192
|
+
if (prop.type === AST_NODE_TYPES.Property &&
|
|
193
|
+
prop.key.type === AST_NODE_TYPES.Identifier) {
|
|
194
|
+
// eslint-disable-next-line functional/immutable-data
|
|
195
|
+
destructuredProps.add(prop.key.name);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const missingProps = objectProps.filter((prop) => !destructuredProps.has(prop));
|
|
199
|
+
if (missingProps.length > 0) {
|
|
200
|
+
context.report({
|
|
201
|
+
node: param,
|
|
202
|
+
messageId: 'incompleteDestructuring',
|
|
203
|
+
data: {
|
|
204
|
+
missingProps: missingProps.join(', '),
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
},
|
|
213
|
+
defaultOptions: [],
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export { checkDestructuringCompleteness };
|
|
217
|
+
//# sourceMappingURL=check-destructuring-completeness.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-destructuring-completeness.mjs","sources":["../../../../src/plugins/ts-restrictions/rules/check-destructuring-completeness.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare const tsRestrictionsRules: {
|
|
2
|
+
readonly 'check-destructuring-completeness': import("@typescript-eslint/utils/ts-eslint").RuleModule<"incompleteDestructuring", readonly [(Readonly<{
|
|
3
|
+
alwaysCheckReactComponentProps?: boolean;
|
|
4
|
+
directiveKeyword?: string;
|
|
5
|
+
}> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
2
6
|
readonly 'no-restricted-cast-name': import("@typescript-eslint/utils/ts-eslint").RuleModule<"restrictedCast", readonly (string | Readonly<{
|
|
3
7
|
name: string;
|
|
4
8
|
fixWith?: Readonly<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAIU,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { checkDestructuringCompleteness } from './check-destructuring-completeness.mjs';
|
|
1
2
|
import { noRestrictedCastName } from './no-restricted-cast-name.mjs';
|
|
2
3
|
import { noRestrictedSyntax } from './no-restricted-syntax.mjs';
|
|
3
4
|
|
|
4
5
|
const tsRestrictionsRules = {
|
|
6
|
+
'check-destructuring-completeness': checkDestructuringCompleteness,
|
|
5
7
|
'no-restricted-cast-name': noRestrictedCastName,
|
|
6
8
|
'no-restricted-syntax': noRestrictedSyntax,
|
|
7
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAKO,MAAM,mBAAmB,GAAG;AACjC,IAAA,kCAAkC,EAAE,8BAA8B;AAClE,IAAA,yBAAyB,EAAE,oBAAoB;AAC/C,IAAA,sBAAsB,EAAE,kBAAkB;;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const eslintTsRestrictionsRules: {
|
|
2
2
|
readonly 'ts-restrictions/no-restricted-syntax': "off";
|
|
3
3
|
readonly 'ts-restrictions/no-restricted-cast-name': "off";
|
|
4
|
+
readonly 'ts-restrictions/check-destructuring-completeness': 2 | 1;
|
|
4
5
|
};
|
|
5
6
|
//# sourceMappingURL=eslint-ts-restrictions-rules.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB;;;;CAKQ,CAAC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { withDefaultOption } from '../types/rule-severity-with-default-option.mjs';
|
|
2
|
+
|
|
3
|
+
const eslintTsRestrictionsRules = {
|
|
2
4
|
'ts-restrictions/no-restricted-syntax': 'off',
|
|
3
5
|
'ts-restrictions/no-restricted-cast-name': 'off',
|
|
6
|
+
'ts-restrictions/check-destructuring-completeness': withDefaultOption('error'),
|
|
4
7
|
};
|
|
5
8
|
|
|
6
|
-
export {
|
|
9
|
+
export { eslintTsRestrictionsRules };
|
|
7
10
|
//# sourceMappingURL=eslint-ts-restrictions-rules.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.mjs","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.mjs","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAKO,MAAM,yBAAyB,GAAG;AACvC,IAAA,sCAAsC,EAAE,KAAK;AAC7C,IAAA,yCAAyC,EAAE,KAAK;AAChD,IAAA,kDAAkD,EAChD,iBAAiB,CAAC,OAAO,CAAC;;;;;"}
|
package/dist/rules/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ export { eslintStylisticRules } from './eslint-stylistic-rules.mjs';
|
|
|
21
21
|
export { eslintTestingLibraryRules } from './eslint-testing-library-rules.mjs';
|
|
22
22
|
export { eslintTotalFunctionsRules } from './eslint-total-functions-rules.mjs';
|
|
23
23
|
export { eslintTreeShakableRules } from './eslint-tree-shakable-rules.mjs';
|
|
24
|
-
export {
|
|
24
|
+
export { eslintTsRestrictionsRules } from './eslint-ts-restrictions-rules.mjs';
|
|
25
25
|
export { eslintUnicornRules } from './eslint-unicorn-rules.mjs';
|
|
26
26
|
export { eslintVitestCodingStyleRules } from './eslint-vitest-coding-style-rules.mjs';
|
|
27
27
|
export { eslintVitestRules } from './eslint-vitest-rules.mjs';
|
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import { type Linter } from 'eslint';
|
|
2
2
|
type SpreadOptionsIfIsArray<T extends readonly [Linter.StringSeverity, unknown]> = T[1] extends readonly unknown[] ? readonly [Linter.StringSeverity, ...T[1]] : T;
|
|
3
|
+
/**
|
|
4
|
+
* Ensure all properties are destructured from an object when explicitly
|
|
5
|
+
* requested
|
|
6
|
+
*
|
|
7
|
+
* ```md
|
|
8
|
+
* | key | value |
|
|
9
|
+
* | :--------- | :--------- |
|
|
10
|
+
* | type | suggestion |
|
|
11
|
+
* | deprecated | false |
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
declare namespace CheckDestructuringCompleteness {
|
|
15
|
+
/**
|
|
16
|
+
* ### schema
|
|
17
|
+
*
|
|
18
|
+
* ```json
|
|
19
|
+
* [
|
|
20
|
+
* {
|
|
21
|
+
* "type": "object",
|
|
22
|
+
* "properties": {
|
|
23
|
+
* "alwaysCheckReactComponentProps": {
|
|
24
|
+
* "type": "boolean",
|
|
25
|
+
* "description": "Always check React component props destructuring without directive keyword"
|
|
26
|
+
* },
|
|
27
|
+
* "directiveKeyword": {
|
|
28
|
+
* "type": "string",
|
|
29
|
+
* "description": "Custom directive keyword to enable checking (default: \"@check-destructuring-completeness\")"
|
|
30
|
+
* }
|
|
31
|
+
* },
|
|
32
|
+
* "additionalProperties": false
|
|
33
|
+
* }
|
|
34
|
+
* ]
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
type Options = {
|
|
38
|
+
/**
|
|
39
|
+
* Always check React component props destructuring without directive
|
|
40
|
+
* keyword
|
|
41
|
+
*/
|
|
42
|
+
readonly alwaysCheckReactComponentProps?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Custom directive keyword to enable checking (default:
|
|
45
|
+
* "@check-destructuring-completeness")
|
|
46
|
+
*/
|
|
47
|
+
readonly directiveKeyword?: string;
|
|
48
|
+
};
|
|
49
|
+
type RuleEntry = Linter.Severity | SpreadOptionsIfIsArray<readonly [Linter.StringSeverity, Options]> | 'off';
|
|
50
|
+
}
|
|
3
51
|
/**
|
|
4
52
|
* Disallow type assertions with specified type names
|
|
5
53
|
*
|
|
@@ -139,10 +187,12 @@ declare namespace NoRestrictedSyntax {
|
|
|
139
187
|
type RuleEntry = Linter.Severity | SpreadOptionsIfIsArray<readonly [Linter.StringSeverity, Options]> | 'off';
|
|
140
188
|
}
|
|
141
189
|
export type EslintTsRestrictionsRules = {
|
|
190
|
+
readonly 'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.RuleEntry;
|
|
142
191
|
readonly 'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.RuleEntry;
|
|
143
192
|
readonly 'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.RuleEntry;
|
|
144
193
|
};
|
|
145
194
|
export type EslintTsRestrictionsRulesOption = {
|
|
195
|
+
readonly 'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.Options;
|
|
146
196
|
readonly 'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.Options;
|
|
147
197
|
readonly 'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.Options;
|
|
148
198
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,KAAK,sBAAsB,CACzB,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,IACjD,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,GAC/B,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GACzC,CAAC,CAAC;AAEN;;;;;;;;;;GAUG;AACH,kBAAU,oBAAoB,CAAC;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4DG;IACH,kBAAkB;IAClB,KAAY,OAAO,GAAG,SAAS,CAC3B,MAAM,GACN;QACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,CAAC,EACb;YACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;YAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,GACD;YACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,CAAC;KACP,CACJ,EAAE,CAAC;IAEJ,KAAY,SAAS,GACjB,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACjE,KAAK,CAAC;CACX;AAED;;;;;;;;;;;;GAYG;AACH,kBAAU,kBAAkB,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,kBAAkB;IAClB,KAAY,OAAO,GAAG,SAAS,CAC3B,MAAM,GACN;QACE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC3B,CACJ,EAAE,CAAC;IAEJ,KAAY,SAAS,GACjB,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACjE,KAAK,CAAC;CACX;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,yCAAyC,EAAE,oBAAoB,CAAC,SAAS,CAAC;IACnF,QAAQ,CAAC,sCAAsC,EAAE,kBAAkB,CAAC,SAAS,CAAC;CAC/E,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,CAAC,yCAAyC,EAAE,oBAAoB,CAAC,OAAO,CAAC;IACjF,QAAQ,CAAC,sCAAsC,EAAE,kBAAkB,CAAC,OAAO,CAAC;CAC7E,CAAC"}
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,KAAK,sBAAsB,CACzB,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,IACjD,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,GAC/B,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GACzC,CAAC,CAAC;AAEN;;;;;;;;;;GAUG;AACH,kBAAU,8BAA8B,CAAC;IACvC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,KAAY,OAAO,GAAG;QACpB;;;WAGG;QACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC;QAClD;;;WAGG;QACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;KACpC,CAAC;IAEF,KAAY,SAAS,GACjB,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACjE,KAAK,CAAC;CACX;AAED;;;;;;;;;;GAUG;AACH,kBAAU,oBAAoB,CAAC;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4DG;IACH,kBAAkB;IAClB,KAAY,OAAO,GAAG,SAAS,CAC3B,MAAM,GACN;QACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,CAAC,EACb;YACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;YAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,GACD;YACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,CAAC;KACP,CACJ,EAAE,CAAC;IAEJ,KAAY,SAAS,GACjB,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACjE,KAAK,CAAC;CACX;AAED;;;;;;;;;;;;GAYG;AACH,kBAAU,kBAAkB,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,kBAAkB;IAClB,KAAY,OAAO,GAAG,SAAS,CAC3B,MAAM,GACN;QACE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC3B,CACJ,EAAE,CAAC;IAEJ,KAAY,SAAS,GACjB,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACjE,KAAK,CAAC;CACX;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,kDAAkD,EAAE,8BAA8B,CAAC,SAAS,CAAC;IACtG,QAAQ,CAAC,yCAAyC,EAAE,oBAAoB,CAAC,SAAS,CAAC;IACnF,QAAQ,CAAC,sCAAsC,EAAE,kBAAkB,CAAC,SAAS,CAAC;CAC/E,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,CAAC,kDAAkD,EAAE,8BAA8B,CAAC,OAAO,CAAC;IACpG,QAAQ,CAAC,yCAAyC,EAAE,oBAAoB,CAAC,OAAO,CAAC;IACjF,QAAQ,CAAC,sCAAsC,EAAE,kBAAkB,CAAC,OAAO,CAAC;CAC7E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
eslintArrayFuncRules,
|
|
3
|
-
eslintCustomRules,
|
|
4
3
|
eslintFunctionalRules,
|
|
5
4
|
eslintImportsRules,
|
|
6
5
|
eslintPluginSortDestructureKeysRules,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
eslintStylisticRules,
|
|
12
11
|
eslintTotalFunctionsRules,
|
|
13
12
|
eslintTreeShakableRules,
|
|
13
|
+
eslintTsRestrictionsRules,
|
|
14
14
|
eslintUnicornRules,
|
|
15
15
|
typescriptEslintRules,
|
|
16
16
|
} from '../rules/index.mjs';
|
|
@@ -51,7 +51,7 @@ export const eslintConfigForTypeScript = ({
|
|
|
51
51
|
...typescriptEslintRules,
|
|
52
52
|
...eslintTreeShakableRules,
|
|
53
53
|
...eslintPluginSortDestructureKeysRules,
|
|
54
|
-
...
|
|
54
|
+
...eslintTsRestrictionsRules,
|
|
55
55
|
|
|
56
56
|
'strict-dependencies/strict-dependencies': ['error', []],
|
|
57
57
|
|
package/src/entry-point.mts
CHANGED
|
@@ -37,6 +37,10 @@ export {
|
|
|
37
37
|
eslintCypressRules,
|
|
38
38
|
eslintPlaywrightRules,
|
|
39
39
|
eslintPluginRules,
|
|
40
|
+
eslintTsRestrictionsRules,
|
|
41
|
+
eslintReactCodingStyleRules,
|
|
42
|
+
eslintStylisticRules,
|
|
43
|
+
eslintVitestCodingStyleRules,
|
|
40
44
|
|
|
41
45
|
// Pre-configured rule options
|
|
42
46
|
restrictedGlobals,
|
|
@@ -44,10 +48,12 @@ export {
|
|
|
44
48
|
restrictedSyntax,
|
|
45
49
|
|
|
46
50
|
// Custom plugins
|
|
47
|
-
eslintPluginTsRestrictions,
|
|
48
|
-
eslintPluginReactCodingStyle,
|
|
49
51
|
eslintPluginTotalFunctions,
|
|
50
52
|
eslintPluginTreeShakable,
|
|
53
|
+
eslintPluginStrictDependencies,
|
|
54
|
+
eslintPluginTsRestrictions,
|
|
55
|
+
eslintPluginVitestCodingStyle,
|
|
56
|
+
eslintPluginReactCodingStyle,
|
|
51
57
|
|
|
52
58
|
// Utilities
|
|
53
59
|
defineConfig,
|
|
@@ -79,6 +85,7 @@ export {
|
|
|
79
85
|
type EslintStrictDependenciesRules,
|
|
80
86
|
type EslintStrictDependenciesRulesOption,
|
|
81
87
|
type EslintReactCodingStyleRules,
|
|
88
|
+
type EslintReactCodingStyleRulesOption,
|
|
82
89
|
type EslintSecurityRules,
|
|
83
90
|
type EslintTreeShakableRules,
|
|
84
91
|
type EslintReactRules,
|
|
@@ -103,6 +110,11 @@ export {
|
|
|
103
110
|
type EslintTestingLibraryRulesOption,
|
|
104
111
|
type EslintPluginRules,
|
|
105
112
|
type EslintPluginRulesOption,
|
|
113
|
+
type EslintStylisticRules,
|
|
114
|
+
type EslintStylisticRulesOption,
|
|
115
|
+
type EslintTsRestrictionsRules,
|
|
116
|
+
type EslintTsRestrictionsRulesOption,
|
|
117
|
+
type EslintVitestCodingStyleRules,
|
|
106
118
|
|
|
107
119
|
// Utility types
|
|
108
120
|
type FlatConfig,
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AST_NODE_TYPES,
|
|
3
|
+
type TSESLint,
|
|
4
|
+
type TSESTree,
|
|
5
|
+
} from '@typescript-eslint/utils';
|
|
6
|
+
import type * as ts from 'typescript';
|
|
7
|
+
|
|
8
|
+
type Options = readonly [
|
|
9
|
+
Readonly<{
|
|
10
|
+
alwaysCheckReactComponentProps?: boolean;
|
|
11
|
+
directiveKeyword?: string;
|
|
12
|
+
}>?,
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
type MessageIds = 'incompleteDestructuring';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_DIRECTIVE_KEYWORD = '@check-destructuring-completeness';
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
20
|
+
const getObjectTypeProperties = (type: ts.Type): readonly string[] => {
|
|
21
|
+
try {
|
|
22
|
+
const properties = type.getProperties();
|
|
23
|
+
|
|
24
|
+
// Limit to reasonable number of properties to avoid hangs
|
|
25
|
+
if (properties.length > 1000) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return properties
|
|
30
|
+
.map((prop) => prop.name)
|
|
31
|
+
.filter(
|
|
32
|
+
(name) =>
|
|
33
|
+
// Filter out symbol properties and internal properties
|
|
34
|
+
!name.startsWith('__') &&
|
|
35
|
+
// Only include string property names
|
|
36
|
+
typeof name === 'string' &&
|
|
37
|
+
name.length > 0,
|
|
38
|
+
);
|
|
39
|
+
} catch {
|
|
40
|
+
// If there's any error getting properties, return empty array
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const isReactComponentFunction = (
|
|
46
|
+
node: DeepReadonly<TSESTree.Node> | undefined | null,
|
|
47
|
+
): boolean => {
|
|
48
|
+
if (node === undefined || node === null) return false;
|
|
49
|
+
|
|
50
|
+
// Arrow function component
|
|
51
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
52
|
+
const { body } = node;
|
|
53
|
+
|
|
54
|
+
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
55
|
+
return body.body.some((statement) => {
|
|
56
|
+
if (statement.type !== AST_NODE_TYPES.ReturnStatement) return false;
|
|
57
|
+
|
|
58
|
+
const { argument } = statement;
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
61
|
+
if (argument === null || argument === undefined) return false;
|
|
62
|
+
|
|
63
|
+
const argType = (argument as { type?: string }).type;
|
|
64
|
+
|
|
65
|
+
return argType === 'JSXElement' || argType === 'JSXFragment';
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const bodyType = (body as { type?: string }).type;
|
|
70
|
+
|
|
71
|
+
return bodyType === 'JSXElement' || bodyType === 'JSXFragment';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return false;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const checkDestructuringCompleteness: TSESLint.RuleModule<
|
|
78
|
+
MessageIds,
|
|
79
|
+
Options
|
|
80
|
+
> = {
|
|
81
|
+
meta: {
|
|
82
|
+
type: 'suggestion',
|
|
83
|
+
docs: {
|
|
84
|
+
description:
|
|
85
|
+
'Ensure all properties are destructured from an object when explicitly requested',
|
|
86
|
+
},
|
|
87
|
+
schema: [
|
|
88
|
+
{
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
alwaysCheckReactComponentProps: {
|
|
92
|
+
type: 'boolean',
|
|
93
|
+
description:
|
|
94
|
+
'Always check React component props destructuring without directive keyword',
|
|
95
|
+
},
|
|
96
|
+
directiveKeyword: {
|
|
97
|
+
type: 'string',
|
|
98
|
+
description:
|
|
99
|
+
'Custom directive keyword to enable checking (default: "@check-destructuring-completeness")',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
additionalProperties: false,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
messages: {
|
|
106
|
+
incompleteDestructuring:
|
|
107
|
+
'Not all properties are destructured. Missing: {{missingProps}}',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
create: (context) => {
|
|
112
|
+
const parserServices = context.sourceCode.parserServices;
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
parserServices?.program === undefined ||
|
|
116
|
+
parserServices.program === null ||
|
|
117
|
+
parserServices.esTreeNodeToTSNodeMap === undefined
|
|
118
|
+
) {
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const options = context.options[0] ?? {};
|
|
123
|
+
|
|
124
|
+
const alwaysCheckReactComponentProps =
|
|
125
|
+
options.alwaysCheckReactComponentProps ?? true;
|
|
126
|
+
|
|
127
|
+
const directiveKeyword =
|
|
128
|
+
options.directiveKeyword ?? DEFAULT_DIRECTIVE_KEYWORD;
|
|
129
|
+
|
|
130
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
131
|
+
const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
|
|
132
|
+
const sourceCode = context.sourceCode;
|
|
133
|
+
|
|
134
|
+
const hasDirectiveComment = (
|
|
135
|
+
node: DeepReadonly<TSESTree.VariableDeclarator>,
|
|
136
|
+
): boolean => {
|
|
137
|
+
// Get the parent VariableDeclaration
|
|
138
|
+
const parent = node.parent;
|
|
139
|
+
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
141
|
+
if (parent?.type !== AST_NODE_TYPES.VariableDeclaration) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
146
|
+
const comments = sourceCode.getCommentsBefore(parent as never);
|
|
147
|
+
|
|
148
|
+
return comments.some((comment) =>
|
|
149
|
+
comment.value.includes(directiveKeyword),
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const isReactComponentPropsDestructuring = (
|
|
154
|
+
node: DeepReadonly<TSESTree.VariableDeclarator>,
|
|
155
|
+
): boolean => {
|
|
156
|
+
if (!alwaysCheckReactComponentProps) return false;
|
|
157
|
+
|
|
158
|
+
const parent = node.parent;
|
|
159
|
+
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
161
|
+
if (parent === undefined) return false;
|
|
162
|
+
|
|
163
|
+
// Case 1: const { a, b } = props; inside component
|
|
164
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
165
|
+
if (parent.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
166
|
+
const grandParent = parent.parent;
|
|
167
|
+
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
169
|
+
if (grandParent === undefined) return false;
|
|
170
|
+
|
|
171
|
+
// Check if we're inside a BlockStatement of an arrow function component
|
|
172
|
+
if (grandParent.type === AST_NODE_TYPES.BlockStatement) {
|
|
173
|
+
const greatGrandParent = grandParent.parent;
|
|
174
|
+
|
|
175
|
+
if (
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
177
|
+
greatGrandParent?.type === AST_NODE_TYPES.ArrowFunctionExpression &&
|
|
178
|
+
node.init?.type === AST_NODE_TYPES.Identifier
|
|
179
|
+
) {
|
|
180
|
+
const initName =
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
182
|
+
node.init.type === AST_NODE_TYPES.Identifier
|
|
183
|
+
? node.init.name
|
|
184
|
+
: undefined;
|
|
185
|
+
|
|
186
|
+
if (
|
|
187
|
+
initName !== undefined &&
|
|
188
|
+
greatGrandParent.params.some(
|
|
189
|
+
(param) =>
|
|
190
|
+
param.type === AST_NODE_TYPES.Identifier &&
|
|
191
|
+
param.name === initName,
|
|
192
|
+
)
|
|
193
|
+
) {
|
|
194
|
+
return isReactComponentFunction(greatGrandParent);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (grandParent.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
200
|
+
return isReactComponentFunction(grandParent);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return false;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const checkNode = (
|
|
208
|
+
node: DeepReadonly<TSESTree.VariableDeclarator>,
|
|
209
|
+
): void => {
|
|
210
|
+
if (node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
|
|
211
|
+
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
213
|
+
if (node.init === undefined || node.init === null) return;
|
|
214
|
+
|
|
215
|
+
const shouldCheck =
|
|
216
|
+
hasDirectiveComment(node) || isReactComponentPropsDestructuring(node);
|
|
217
|
+
|
|
218
|
+
if (!shouldCheck) return;
|
|
219
|
+
|
|
220
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
221
|
+
const tsNode = esTreeNodeToTSNodeMap.get(node.init as never);
|
|
222
|
+
|
|
223
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
224
|
+
if (tsNode === undefined) return;
|
|
225
|
+
|
|
226
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
227
|
+
|
|
228
|
+
const objectProps = getObjectTypeProperties(type);
|
|
229
|
+
const destructuredProps = new Set<string>();
|
|
230
|
+
|
|
231
|
+
for (const prop of node.id.properties) {
|
|
232
|
+
if (
|
|
233
|
+
prop.type === AST_NODE_TYPES.Property &&
|
|
234
|
+
prop.key.type === AST_NODE_TYPES.Identifier
|
|
235
|
+
) {
|
|
236
|
+
// eslint-disable-next-line functional/immutable-data
|
|
237
|
+
destructuredProps.add(prop.key.name);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const missingProps = objectProps.filter(
|
|
242
|
+
(prop) => !destructuredProps.has(prop),
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
if (missingProps.length > 0) {
|
|
246
|
+
context.report({
|
|
247
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
248
|
+
node: node.id as never,
|
|
249
|
+
messageId: 'incompleteDestructuring',
|
|
250
|
+
data: {
|
|
251
|
+
missingProps: missingProps.join(', '),
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
VariableDeclarator: checkNode,
|
|
259
|
+
ArrowFunctionExpression: (node) => {
|
|
260
|
+
if (!alwaysCheckReactComponentProps) return;
|
|
261
|
+
|
|
262
|
+
if (!isReactComponentFunction(node)) return;
|
|
263
|
+
|
|
264
|
+
for (const param of node.params) {
|
|
265
|
+
if (param.type === AST_NODE_TYPES.ObjectPattern) {
|
|
266
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
267
|
+
const tsNode = esTreeNodeToTSNodeMap.get(param as never);
|
|
268
|
+
|
|
269
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
270
|
+
if (tsNode === undefined) continue;
|
|
271
|
+
|
|
272
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
273
|
+
|
|
274
|
+
const objectProps = getObjectTypeProperties(type);
|
|
275
|
+
const destructuredProps = new Set<string>();
|
|
276
|
+
|
|
277
|
+
for (const prop of param.properties) {
|
|
278
|
+
if (
|
|
279
|
+
prop.type === AST_NODE_TYPES.Property &&
|
|
280
|
+
prop.key.type === AST_NODE_TYPES.Identifier
|
|
281
|
+
) {
|
|
282
|
+
// eslint-disable-next-line functional/immutable-data
|
|
283
|
+
destructuredProps.add(prop.key.name);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const missingProps = objectProps.filter(
|
|
288
|
+
(prop) => !destructuredProps.has(prop),
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
if (missingProps.length > 0) {
|
|
292
|
+
context.report({
|
|
293
|
+
node: param,
|
|
294
|
+
messageId: 'incompleteDestructuring',
|
|
295
|
+
data: {
|
|
296
|
+
missingProps: missingProps.join(', '),
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
},
|
|
305
|
+
defaultOptions: [],
|
|
306
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import dedent from 'dedent';
|
|
4
|
+
import { checkDestructuringCompleteness } from './check-destructuring-completeness.mjs';
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2020,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
ecmaFeatures: {
|
|
13
|
+
jsx: true,
|
|
14
|
+
},
|
|
15
|
+
projectService: {
|
|
16
|
+
allowDefaultProject: ['*.ts*'],
|
|
17
|
+
},
|
|
18
|
+
tsconfigRootDir: `${import.meta.dirname}/../../../..`,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('check-destructuring-completeness', () => {
|
|
24
|
+
tester.run(
|
|
25
|
+
'check-destructuring-completeness',
|
|
26
|
+
checkDestructuringCompleteness,
|
|
27
|
+
{
|
|
28
|
+
valid: [
|
|
29
|
+
{
|
|
30
|
+
name: 'ignore incomplete destructuring without directive comment',
|
|
31
|
+
code: dedent`
|
|
32
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
33
|
+
const { a } = obj;
|
|
34
|
+
`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'validates destructuring with default directive - complete',
|
|
38
|
+
code: dedent`
|
|
39
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
40
|
+
// @check-destructuring-completeness
|
|
41
|
+
const { a, b, c } = obj;
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'validates destructuring with unknown directive',
|
|
46
|
+
code: dedent`
|
|
47
|
+
const obj: { a: number; b: string; c: boolean } = { a: 1, b: 'hello', c: true };
|
|
48
|
+
// @unknown-directive
|
|
49
|
+
const { a, b } = obj;
|
|
50
|
+
`,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'works with custom directive keyword - custom check',
|
|
54
|
+
code: dedent`
|
|
55
|
+
const obj: { a: number; b: string } = { a: 1, b: 'hello' };
|
|
56
|
+
// @custom-check
|
|
57
|
+
const { a, b } = obj;
|
|
58
|
+
`,
|
|
59
|
+
options: [{ directiveKeyword: '@custom-check' }],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'custom directive ignores default directive',
|
|
63
|
+
code: dedent`
|
|
64
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
65
|
+
// @check-destructuring-completeness
|
|
66
|
+
const { a, b } = obj;
|
|
67
|
+
`,
|
|
68
|
+
options: [{ directiveKeyword: '@custom-check' }],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'custom directive ignores unknown directive',
|
|
72
|
+
code: dedent`
|
|
73
|
+
const obj: { a: number; b: string; c: boolean } = { a: 1, b: 'hello', c: true };
|
|
74
|
+
// @unknown-directive
|
|
75
|
+
const { a, b } = obj;
|
|
76
|
+
`,
|
|
77
|
+
options: [{ directiveKeyword: '@custom-check' }],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'checks React component props - parameter destructuring',
|
|
81
|
+
code: dedent`
|
|
82
|
+
type Props = { a: number; b: string };
|
|
83
|
+
const MyComponent = ({ a, b }: Props) => <div>{a}{b}</div>;
|
|
84
|
+
`,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'checks React component props - internal destructuring',
|
|
88
|
+
code: dedent`
|
|
89
|
+
type Props = { a: number; b: string };
|
|
90
|
+
const MyComponent = (props: Props) => {
|
|
91
|
+
const { a, b } = props;
|
|
92
|
+
return <div>{a}{b}</div>;
|
|
93
|
+
};
|
|
94
|
+
`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'does not check React component props when disabled - parameter',
|
|
98
|
+
code: dedent`
|
|
99
|
+
type Props = { a: number; b: string; c: boolean };
|
|
100
|
+
const MyComponent = ({ a, b }: Props) => <div>{a}{b}</div>;
|
|
101
|
+
`,
|
|
102
|
+
options: [{ alwaysCheckReactComponentProps: false }],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'does not check React component props when disabled - internal',
|
|
106
|
+
code: dedent`
|
|
107
|
+
type Props = { a: number; b: string; c: boolean };
|
|
108
|
+
const MyComponent = (props: Props) => {
|
|
109
|
+
const { a, b } = props;
|
|
110
|
+
return <div>{a}{b}</div>;
|
|
111
|
+
};
|
|
112
|
+
`,
|
|
113
|
+
options: [{ alwaysCheckReactComponentProps: false }],
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
invalid: [
|
|
117
|
+
{
|
|
118
|
+
name: 'validates destructuring with default directive - incomplete',
|
|
119
|
+
code: dedent`
|
|
120
|
+
const obj: { a: number; b: string; c: boolean } = { a: 1, b: 'hello', c: true };
|
|
121
|
+
// @check-destructuring-completeness
|
|
122
|
+
const { a, b } = obj;
|
|
123
|
+
`,
|
|
124
|
+
errors: [{ messageId: 'incompleteDestructuring' }],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'custom directive catches incomplete',
|
|
128
|
+
code: dedent`
|
|
129
|
+
const obj: { a: number; b: string } = { a: 1, b: 'hello' };
|
|
130
|
+
// @custom-check
|
|
131
|
+
const { a } = obj;
|
|
132
|
+
`,
|
|
133
|
+
options: [{ directiveKeyword: '@custom-check' }],
|
|
134
|
+
errors: [{ messageId: 'incompleteDestructuring' }],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'checks React component props - parameter destructuring incomplete',
|
|
138
|
+
code: dedent`
|
|
139
|
+
type Props = { a: number; b: string; c: boolean };
|
|
140
|
+
const MyComponent = ({ a, b }: Props) => <div>{a}{b}</div>;
|
|
141
|
+
`,
|
|
142
|
+
errors: [{ messageId: 'incompleteDestructuring' }],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'checks React component props - internal destructuring incomplete',
|
|
146
|
+
code: dedent`
|
|
147
|
+
type Props = { a: number; b: string; c: boolean };
|
|
148
|
+
const MyComponent = (props: Props) => {
|
|
149
|
+
const { a, b } = props;
|
|
150
|
+
return <div>{a}{b}</div>;
|
|
151
|
+
};
|
|
152
|
+
`,
|
|
153
|
+
errors: [{ messageId: 'incompleteDestructuring' }],
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
}, 20000);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type ESLintPlugin } from '../../../types/index.mjs';
|
|
2
|
+
import { checkDestructuringCompleteness } from './check-destructuring-completeness.mjs';
|
|
2
3
|
import { noRestrictedCastName } from './no-restricted-cast-name.mjs';
|
|
3
4
|
import { noRestrictedSyntax } from './no-restricted-syntax.mjs';
|
|
4
5
|
|
|
5
6
|
export const tsRestrictionsRules = {
|
|
7
|
+
'check-destructuring-completeness': checkDestructuringCompleteness,
|
|
6
8
|
'no-restricted-cast-name': noRestrictedCastName,
|
|
7
9
|
'no-restricted-syntax': noRestrictedSyntax,
|
|
8
10
|
} as const satisfies ESLintPlugin['rules'];
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type EslintTsRestrictionsRules,
|
|
3
|
+
withDefaultOption,
|
|
4
|
+
} from '../types/index.mjs';
|
|
2
5
|
|
|
3
|
-
export const
|
|
6
|
+
export const eslintTsRestrictionsRules = {
|
|
4
7
|
'ts-restrictions/no-restricted-syntax': 'off',
|
|
5
8
|
'ts-restrictions/no-restricted-cast-name': 'off',
|
|
9
|
+
'ts-restrictions/check-destructuring-completeness':
|
|
10
|
+
withDefaultOption('error'),
|
|
6
11
|
} as const satisfies EslintTsRestrictionsRules;
|
|
@@ -7,6 +7,59 @@ type SpreadOptionsIfIsArray<
|
|
|
7
7
|
? readonly [Linter.StringSeverity, ...T[1]]
|
|
8
8
|
: T;
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Ensure all properties are destructured from an object when explicitly
|
|
12
|
+
* requested
|
|
13
|
+
*
|
|
14
|
+
* ```md
|
|
15
|
+
* | key | value |
|
|
16
|
+
* | :--------- | :--------- |
|
|
17
|
+
* | type | suggestion |
|
|
18
|
+
* | deprecated | false |
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
namespace CheckDestructuringCompleteness {
|
|
22
|
+
/**
|
|
23
|
+
* ### schema
|
|
24
|
+
*
|
|
25
|
+
* ```json
|
|
26
|
+
* [
|
|
27
|
+
* {
|
|
28
|
+
* "type": "object",
|
|
29
|
+
* "properties": {
|
|
30
|
+
* "alwaysCheckReactComponentProps": {
|
|
31
|
+
* "type": "boolean",
|
|
32
|
+
* "description": "Always check React component props destructuring without directive keyword"
|
|
33
|
+
* },
|
|
34
|
+
* "directiveKeyword": {
|
|
35
|
+
* "type": "string",
|
|
36
|
+
* "description": "Custom directive keyword to enable checking (default: \"@check-destructuring-completeness\")"
|
|
37
|
+
* }
|
|
38
|
+
* },
|
|
39
|
+
* "additionalProperties": false
|
|
40
|
+
* }
|
|
41
|
+
* ]
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export type Options = {
|
|
45
|
+
/**
|
|
46
|
+
* Always check React component props destructuring without directive
|
|
47
|
+
* keyword
|
|
48
|
+
*/
|
|
49
|
+
readonly alwaysCheckReactComponentProps?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Custom directive keyword to enable checking (default:
|
|
52
|
+
* "@check-destructuring-completeness")
|
|
53
|
+
*/
|
|
54
|
+
readonly directiveKeyword?: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type RuleEntry =
|
|
58
|
+
| Linter.Severity
|
|
59
|
+
| SpreadOptionsIfIsArray<readonly [Linter.StringSeverity, Options]>
|
|
60
|
+
| 'off';
|
|
61
|
+
}
|
|
62
|
+
|
|
10
63
|
/**
|
|
11
64
|
* Disallow type assertions with specified type names
|
|
12
65
|
*
|
|
@@ -164,11 +217,13 @@ namespace NoRestrictedSyntax {
|
|
|
164
217
|
}
|
|
165
218
|
|
|
166
219
|
export type EslintTsRestrictionsRules = {
|
|
220
|
+
readonly 'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.RuleEntry;
|
|
167
221
|
readonly 'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.RuleEntry;
|
|
168
222
|
readonly 'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.RuleEntry;
|
|
169
223
|
};
|
|
170
224
|
|
|
171
225
|
export type EslintTsRestrictionsRulesOption = {
|
|
226
|
+
readonly 'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.Options;
|
|
172
227
|
readonly 'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.Options;
|
|
173
228
|
readonly 'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.Options;
|
|
174
229
|
};
|