eslint-plugin-awscdk 4.3.0 → 4.3.3
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/dist/index.cjs +3307 -2501
- package/dist/index.d.cts +83 -137
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +83 -137
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3306 -2500
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -26
- package/src/configs/classic-config.ts +6 -6
- package/src/configs/flat-config.ts +2 -2
- package/src/configs/index.ts +6 -1
- package/src/core/ast-node/finder/enclosing-class.ts +12 -0
- package/src/core/cdk-construct/type-checker/is-resource-with-readonly-interface.ts +0 -1
- package/src/rules/index.ts +6 -1
- package/src/rules/no-import-private.ts +1 -2
- package/src/rules/no-unused-props/index.ts +0 -1
- package/src/rules/no-unused-props/props-usage-analyzer.ts +5 -1
- package/src/rules/no-unused-props/visitor/direct-props-usage-visitor.ts +0 -1
- package/src/rules/no-unused-props/visitor/instance-variable-usage-visitor.ts +0 -1
- package/src/rules/no-unused-props/visitor/method-call-collector-visitor.ts +4 -1
- package/src/rules/no-unused-props/visitor/props-alias-visitor.ts +0 -1
- package/src/rules/no-unused-props/visitor/traverse-nodes.ts +0 -1
- package/src/rules/no-variable-construct-id.ts +15 -0
- package/src/rules/require-passing-this.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-awscdk",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.3",
|
|
4
4
|
"description": "eslint plugin for AWS CDK projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aws",
|
|
@@ -44,39 +44,28 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"test
|
|
50
|
-
"
|
|
51
|
-
"fmt": "oxfmt",
|
|
52
|
-
"fmt:check": "oxfmt --check",
|
|
53
|
-
"check": "tsgo --noEmit",
|
|
54
|
-
"pack": "pnpm run build && npm pack",
|
|
55
|
-
"docs": "pnpm run --filter=@eslint-plugin-awscdk/docs",
|
|
56
|
-
"example:flat-config": "pnpm run --filter=@eslint-plugin-awscdk/example-flat-config",
|
|
57
|
-
"example:classic-config": "pnpm run --filter=@eslint-plugin-awscdk/example-classic-config",
|
|
58
|
-
"example:oxlint": "pnpm run --filter=@eslint-plugin-awscdk/example-oxlint"
|
|
47
|
+
"pack": "vp pack",
|
|
48
|
+
"check": "vp check",
|
|
49
|
+
"test": "vp test --run",
|
|
50
|
+
"docs": "vp run -F @eslint-plugin-awscdk/docs"
|
|
59
51
|
},
|
|
60
52
|
"devDependencies": {
|
|
61
53
|
"@eslint/js": "^10.0.1",
|
|
62
|
-
"@secretlint/secretlint-rule-preset-recommend": "^
|
|
54
|
+
"@secretlint/secretlint-rule-preset-recommend": "^13.0.0",
|
|
63
55
|
"@types/node": "^24.10.13",
|
|
64
|
-
"@typescript-eslint/parser": "^8.
|
|
65
|
-
"@typescript-eslint/rule-tester": "^8.
|
|
66
|
-
"@typescript-eslint/utils": "^8.
|
|
67
|
-
"@
|
|
56
|
+
"@typescript-eslint/parser": "^8.58.0",
|
|
57
|
+
"@typescript-eslint/rule-tester": "^8.58.0",
|
|
58
|
+
"@typescript-eslint/utils": "^8.58.0",
|
|
59
|
+
"@voidzero-dev/vite-plus-core": "^0.1.11",
|
|
68
60
|
"eslint": "^10.0.0",
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"typescript": "^5.9.3",
|
|
74
|
-
"typescript-eslint": "^8.56.0",
|
|
75
|
-
"vitest": "^4.0.6"
|
|
61
|
+
"secretlint": "^13.0.0",
|
|
62
|
+
"typescript": "^6.0.2",
|
|
63
|
+
"typescript-eslint": "^8.58.0",
|
|
64
|
+
"vite-plus": "^0.1.11"
|
|
76
65
|
},
|
|
77
66
|
"peerDependencies": {
|
|
78
67
|
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
|
79
|
-
"typescript": ">=4.8.4 <6.
|
|
68
|
+
"typescript": ">=4.8.4 <6.1.0"
|
|
80
69
|
},
|
|
81
70
|
"engines": {
|
|
82
71
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ClassicConfig } from "@typescript-eslint/utils/ts-eslint";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
rules: ClassicConfig.RulesRecord,
|
|
5
|
-
): {
|
|
3
|
+
type ClassicRulesConfig = {
|
|
6
4
|
plugins: ["awscdk"];
|
|
7
5
|
rules: ClassicConfig.RulesRecord;
|
|
8
|
-
}
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const createClassicConfig = (rules: ClassicConfig.RulesRecord): ClassicRulesConfig => {
|
|
9
9
|
return {
|
|
10
10
|
plugins: ["awscdk"],
|
|
11
11
|
rules,
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export const recommended = createClassicConfig({
|
|
15
|
+
export const recommended: ClassicRulesConfig = createClassicConfig({
|
|
16
16
|
"awscdk/construct-constructor-property": "error",
|
|
17
17
|
"awscdk/migrate-disable-comments": "error",
|
|
18
18
|
"awscdk/no-construct-in-interface": "error",
|
|
@@ -28,7 +28,7 @@ export const recommended = createClassicConfig({
|
|
|
28
28
|
"awscdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
export const strict = createClassicConfig({
|
|
31
|
+
export const strict: ClassicRulesConfig = createClassicConfig({
|
|
32
32
|
"awscdk/construct-constructor-property": "error",
|
|
33
33
|
"awscdk/migrate-disable-comments": "error",
|
|
34
34
|
"awscdk/no-construct-in-interface": "error",
|
|
@@ -30,7 +30,7 @@ const createFlatConfig = (rules: _FlatConfig.Rules): FlatConfig => {
|
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export const recommended = createFlatConfig({
|
|
33
|
+
export const recommended: FlatConfig = createFlatConfig({
|
|
34
34
|
"awscdk/construct-constructor-property": "error",
|
|
35
35
|
"awscdk/migrate-disable-comments": "error",
|
|
36
36
|
"awscdk/no-construct-in-interface": "error",
|
|
@@ -46,7 +46,7 @@ export const recommended = createFlatConfig({
|
|
|
46
46
|
"awscdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
export const strict = createFlatConfig({
|
|
49
|
+
export const strict: FlatConfig = createFlatConfig({
|
|
50
50
|
"awscdk/construct-constructor-property": "error",
|
|
51
51
|
"awscdk/migrate-disable-comments": "error",
|
|
52
52
|
"awscdk/no-construct-in-interface": "error",
|
package/src/configs/index.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { recommended as classicRecommended, strict as classicStrict } from "./classic-config";
|
|
2
2
|
import { recommended, strict } from "./flat-config";
|
|
3
3
|
|
|
4
|
-
export const configs
|
|
4
|
+
export const configs: Readonly<{
|
|
5
|
+
recommended: typeof recommended;
|
|
6
|
+
strict: typeof strict;
|
|
7
|
+
classicRecommended: typeof classicRecommended;
|
|
8
|
+
classicStrict: typeof classicStrict;
|
|
9
|
+
}> = {
|
|
5
10
|
recommended,
|
|
6
11
|
strict,
|
|
7
12
|
classicRecommended,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Find the enclosing ClassDeclaration from a given node
|
|
5
|
+
* @param node The node to start searching from
|
|
6
|
+
* @returns The enclosing ClassDeclaration or undefined if not found
|
|
7
|
+
*/
|
|
8
|
+
export const findEnclosingClass = (node: TSESTree.Node): TSESTree.ClassDeclaration | undefined => {
|
|
9
|
+
if (!node.parent) return undefined;
|
|
10
|
+
if (node.parent.type === AST_NODE_TYPES.ClassDeclaration) return node.parent;
|
|
11
|
+
return findEnclosingClass(node.parent);
|
|
12
|
+
};
|
package/src/rules/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { TSESLint } from "@typescript-eslint/utils";
|
|
2
|
+
import type { Rule } from "eslint";
|
|
3
|
+
|
|
1
4
|
import { constructConstructorProperty } from "./construct-constructor-property";
|
|
2
5
|
import { migrateDisableComments } from "./migrate-disable-comments";
|
|
3
6
|
import { noConstructInInterface } from "./no-construct-in-interface";
|
|
@@ -17,7 +20,9 @@ import { requireJSDoc } from "./require-jsdoc";
|
|
|
17
20
|
import { requirePassingThis } from "./require-passing-this";
|
|
18
21
|
import { requirePropsDefaultDoc } from "./require-props-default-doc";
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
type RuleModule = TSESLint.RuleModule<string, readonly unknown[]> | Rule.RuleModule;
|
|
24
|
+
|
|
25
|
+
export const rules: Record<string, RuleModule> = {
|
|
21
26
|
"construct-constructor-property": constructConstructorProperty,
|
|
22
27
|
"migrate-disable-comments": migrateDisableComments,
|
|
23
28
|
"no-construct-in-interface": noConstructInInterface,
|
|
@@ -10,7 +10,6 @@ import { Type } from "typescript";
|
|
|
10
10
|
import { findConstructor } from "../../core/ast-node/finder/constructor";
|
|
11
11
|
import { isConstructType } from "../../core/cdk-construct/type-checker/is-construct";
|
|
12
12
|
import { createRule } from "../../shared/create-rule";
|
|
13
|
-
|
|
14
13
|
import { PropsUsageAnalyzer } from "./props-usage-analyzer";
|
|
15
14
|
import { IPropsUsageTracker, PropsUsageTracker } from "./props-usage-tracker";
|
|
16
15
|
|
|
@@ -14,7 +14,11 @@ export interface IPropsUsageAnalyzer {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export class PropsUsageAnalyzer implements IPropsUsageAnalyzer {
|
|
17
|
-
|
|
17
|
+
private readonly tracker: IPropsUsageTracker;
|
|
18
|
+
|
|
19
|
+
constructor(tracker: IPropsUsageTracker) {
|
|
20
|
+
this.tracker = tracker;
|
|
21
|
+
}
|
|
18
22
|
|
|
19
23
|
analyze(constructor: TSESTree.MethodDefinition, propsParam: TSESTree.Identifier): void {
|
|
20
24
|
const constructorBody = constructor.value.body;
|
|
@@ -26,8 +26,11 @@ type MethodCallInfo = {
|
|
|
26
26
|
*/
|
|
27
27
|
export class MethodCallCollectorVisitor implements INodeVisitor {
|
|
28
28
|
private readonly _result: MethodCallInfo[] = [];
|
|
29
|
+
private readonly propsParamName: string;
|
|
29
30
|
|
|
30
|
-
constructor(
|
|
31
|
+
constructor(propsParamName: string) {
|
|
32
|
+
this.propsParamName = propsParamName;
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
visitCallExpression(node: TSESTree.CallExpression): void {
|
|
33
36
|
// NOTE: Check for this.methodName(...) pattern
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils";
|
|
2
2
|
|
|
3
3
|
import { findChildNodes } from "../../../core/ast-node/finder/child-nodes";
|
|
4
|
-
|
|
5
4
|
import { INodeVisitor } from "./interface/node-visitor";
|
|
6
5
|
|
|
7
6
|
export const traverseNodes = (node: TSESTree.Node, visitor: INodeVisitor): void => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from "@typescript-eslint/utils";
|
|
2
2
|
|
|
3
|
+
import { findEnclosingClass } from "../core/ast-node/finder/enclosing-class";
|
|
3
4
|
import { isConstructType } from "../core/cdk-construct/type-checker/is-construct";
|
|
5
|
+
import { isConstructOrStackType } from "../core/cdk-construct/type-checker/is-construct-or-stack";
|
|
4
6
|
import { findConstructorPropertyNames } from "../core/ts-type/finder/constructor-property-name";
|
|
5
7
|
import { createRule } from "../shared/create-rule";
|
|
6
8
|
|
|
@@ -32,6 +34,13 @@ export const noVariableConstructId = createRule({
|
|
|
32
34
|
|
|
33
35
|
if (!isConstructType(type) || node.arguments.length < 2) return;
|
|
34
36
|
|
|
37
|
+
// NOTE: Skip when inside a class that is not Construct/Stack
|
|
38
|
+
const enclosingClass = findEnclosingClass(node);
|
|
39
|
+
const enclosingClassType = enclosingClass
|
|
40
|
+
? parserServices.getTypeAtLocation(enclosingClass)
|
|
41
|
+
: undefined;
|
|
42
|
+
if (enclosingClassType && !isConstructOrStackType(enclosingClassType)) return;
|
|
43
|
+
|
|
35
44
|
const constructorPropertyNames = findConstructorPropertyNames(type);
|
|
36
45
|
if (constructorPropertyNames[1] !== "id") return;
|
|
37
46
|
|
|
@@ -96,6 +105,12 @@ const shouldSkipIdValidation = (node: TSESTree.Node): boolean => {
|
|
|
96
105
|
return true;
|
|
97
106
|
}
|
|
98
107
|
|
|
108
|
+
// Constructs in standalone functions (outside of classes) are intended to be called
|
|
109
|
+
// multiple times with different IDs
|
|
110
|
+
if (current.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
99
114
|
current = current.parent;
|
|
100
115
|
}
|
|
101
116
|
return false;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils";
|
|
2
2
|
|
|
3
|
+
import { findEnclosingClass } from "../core/ast-node/finder/enclosing-class";
|
|
3
4
|
import { isConstructType } from "../core/cdk-construct/type-checker/is-construct";
|
|
5
|
+
import { isConstructOrStackType } from "../core/cdk-construct/type-checker/is-construct-or-stack";
|
|
4
6
|
import { findConstructorPropertyNames } from "../core/ts-type/finder/constructor-property-name";
|
|
5
7
|
import { createRule } from "../shared/create-rule";
|
|
6
8
|
|
|
@@ -53,6 +55,12 @@ export const requirePassingThis = createRule({
|
|
|
53
55
|
|
|
54
56
|
if (!isConstructType(type) || !node.arguments.length) return;
|
|
55
57
|
|
|
58
|
+
// NOTE: Only flag when inside a Construct/Stack class where `this` is available
|
|
59
|
+
const enclosingClass = findEnclosingClass(node);
|
|
60
|
+
if (!enclosingClass) return;
|
|
61
|
+
const enclosingClassType = parserServices.getTypeAtLocation(enclosingClass);
|
|
62
|
+
if (!isConstructOrStackType(enclosingClassType)) return;
|
|
63
|
+
|
|
56
64
|
const argument = node.arguments[0];
|
|
57
65
|
|
|
58
66
|
// NOTE: If the first argument is already `this`, it's valid
|