eslint-cdk-plugin 3.0.2 → 3.1.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 CHANGED
@@ -35,29 +35,34 @@ Note: This plugin uses typescript type information and must be used in conjuncti
35
35
 
36
36
  ```js
37
37
  // eslint.config.mjs
38
+ import eslint from "@eslint/js";
39
+ import { defineConfig } from "eslint/config";
40
+ import tseslint from "typescript-eslint";
38
41
  import cdkPlugin from "eslint-cdk-plugin";
39
- import tsEslint from "typescript-eslint";
40
42
 
41
- export default [
42
- ...tsEslint.configs.recommended,
43
- // ✅ Add plugins
44
- cdkPlugin.configs.recommended,
43
+ export default defineConfig([
44
+ eslint.configs.recommended,
45
+ ...tseslint.configs.recommended,
45
46
  {
46
47
  files: ["lib/**/*.ts", "bin/*.ts"],
47
- // ... some configs
48
+ // Add plugins
49
+ extends: [cdkPlugin.configs.recommended],
48
50
  },
49
- ];
51
+ ]);
50
52
  ```
51
53
 
52
54
  ### When using custom config
53
55
 
54
56
  ```js
55
57
  // eslint.config.mjs
56
- import tsEslint from "typescript-eslint";
58
+ import eslint from "@eslint/js";
59
+ import { defineConfig } from "eslint/config";
60
+ import tseslint from "typescript-eslint";
57
61
  import cdkPlugin from "eslint-cdk-plugin";
58
62
 
59
- export default [
60
- ...tsEslint.configs.recommended,
63
+ export default defineConfig([
64
+ eslint.configs.recommended,
65
+ ...tseslint.configs.recommended,
61
66
  {
62
67
  files: ["lib/**/*.ts", "bin/*.ts"],
63
68
  languageOptions: {
@@ -77,7 +82,7 @@ export default [
77
82
  "cdk/no-parent-name-construct-id-match": "error",
78
83
  },
79
84
  },
80
- ];
85
+ ]);
81
86
  ```
82
87
 
83
88
  ## ❗ Issue
package/dist/index.cjs CHANGED
@@ -26,7 +26,11 @@ function _interopNamespaceDefault(e) {
26
26
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
27
27
 
28
28
  var name = "eslint-cdk-plugin";
29
- var version = "3.0.1";
29
+ var version = "3.1.0";
30
+
31
+ const createRule = utils.ESLintUtils.RuleCreator(
32
+ (name) => `https://eslint-cdk-plugin.dev/rules/${name}`
33
+ );
30
34
 
31
35
  const isConstructOrStackType = (type, ignoredClasses = ["App", "Stage"]) => {
32
36
  if (ignoredClasses.includes(type.symbol?.name ?? "")) return false;
@@ -42,43 +46,44 @@ const isConstructType = (type, ignoredClasses = ["App", "Stage", "Stack"]) => {
42
46
  };
43
47
  const isTargetSuperClassType = (type, targetSuperClasses, typeCheckFunction) => {
44
48
  if (!type.symbol) return false;
45
- if (targetSuperClasses.some((suffix) => type.symbol.name.endsWith(suffix))) {
49
+ if (targetSuperClasses.some((suffix) => type.symbol.name === suffix)) {
46
50
  return true;
47
51
  }
48
52
  const baseTypes = type.getBaseTypes() ?? [];
49
53
  return baseTypes.some((baseType) => typeCheckFunction(baseType));
50
54
  };
51
55
 
52
- const constructConstructorProperty = utils.ESLintUtils.RuleCreator.withoutDocs(
53
- {
54
- meta: {
55
- type: "problem",
56
- docs: {
57
- description: "Enforces that constructors of classes extending Construct have the property names 'scope, id' or 'scope, id, props'"
58
- },
59
- messages: {
60
- invalidConstructorProperty: "Constructor of a class extending Construct must have the property names 'scope, id' or 'scope, id, props'"
61
- },
62
- schema: []
56
+ const constructConstructorProperty = createRule({
57
+ name: "construct-constructor-property",
58
+ meta: {
59
+ type: "problem",
60
+ docs: {
61
+ description: "Enforces that constructors of classes extending Construct have the property names 'scope, id' or 'scope, id, props'"
63
62
  },
64
- defaultOptions: [],
65
- create(context) {
66
- const parserServices = utils.ESLintUtils.getParserServices(context);
67
- return {
68
- ClassDeclaration(node) {
69
- const type = parserServices.getTypeAtLocation(node);
70
- if (!isConstructType(type)) return;
71
- const constructor = node.body.body.find(
72
- (member) => member.type === utils.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
73
- );
74
- if (!constructor) return;
75
- validateConstructorProperty(constructor, context);
76
- }
77
- };
78
- }
63
+ messages: {
64
+ invalidConstructorProperty: "Constructor of a class extending Construct must have the property names 'scope, id' or 'scope, id, props'",
65
+ invalidConstructorType: "Constructor of a class extending Construct must have the type 'Construct' for the first parameter",
66
+ invalidConstructorIdType: "Constructor of a class extending Construct must have the type 'string' for the second parameter"
67
+ },
68
+ schema: []
69
+ },
70
+ defaultOptions: [],
71
+ create(context) {
72
+ const parserServices = utils.ESLintUtils.getParserServices(context);
73
+ return {
74
+ ClassDeclaration(node) {
75
+ const type = parserServices.getTypeAtLocation(node);
76
+ if (!isConstructType(type)) return;
77
+ const constructor = node.body.body.find(
78
+ (member) => member.type === utils.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
79
+ );
80
+ if (!constructor) return;
81
+ validateConstructorProperty(constructor, context, parserServices);
82
+ }
83
+ };
79
84
  }
80
- );
81
- const validateConstructorProperty = (constructor, context) => {
85
+ });
86
+ const validateConstructorProperty = (constructor, context, parserServices) => {
82
87
  const params = constructor.value.params;
83
88
  if (params.length < 2) {
84
89
  context.report({
@@ -88,24 +93,35 @@ const validateConstructorProperty = (constructor, context) => {
88
93
  return;
89
94
  }
90
95
  const firstParam = params[0];
91
- if (firstParam.type === utils.AST_NODE_TYPES.Identifier && firstParam.name !== "scope") {
96
+ if (firstParam.type !== utils.AST_NODE_TYPES.Identifier || firstParam.name !== "scope") {
92
97
  context.report({
93
98
  node: firstParam,
94
99
  messageId: "invalidConstructorProperty"
95
100
  });
96
- return;
101
+ } else if (!isConstructType(parserServices.getTypeAtLocation(firstParam))) {
102
+ context.report({
103
+ node: firstParam,
104
+ messageId: "invalidConstructorType"
105
+ });
97
106
  }
98
107
  const secondParam = params[1];
99
- if (secondParam.type === utils.AST_NODE_TYPES.Identifier && secondParam.name !== "id") {
108
+ if (secondParam.type !== utils.AST_NODE_TYPES.Identifier || secondParam.name !== "id") {
100
109
  context.report({
101
110
  node: secondParam,
102
111
  messageId: "invalidConstructorProperty"
103
112
  });
104
113
  return;
114
+ } else if (secondParam.typeAnnotation?.typeAnnotation.type !== utils.AST_NODE_TYPES.TSStringKeyword) {
115
+ context.report({
116
+ node: secondParam,
117
+ messageId: "invalidConstructorIdType"
118
+ });
119
+ return;
105
120
  }
106
- if (params.length < 3) return;
121
+ if (params.length < 3)
122
+ return;
107
123
  const thirdParam = params[2];
108
- if (thirdParam.type === utils.AST_NODE_TYPES.Identifier && thirdParam.name !== "props") {
124
+ if (thirdParam.type !== utils.AST_NODE_TYPES.Identifier || thirdParam.name !== "props") {
109
125
  context.report({
110
126
  node: thirdParam,
111
127
  messageId: "invalidConstructorProperty"
@@ -122,7 +138,8 @@ const SYNTAX_KIND = {
122
138
  CONSTRUCTOR: 176
123
139
  };
124
140
 
125
- const noConstructInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
141
+ const noConstructInInterface = createRule({
142
+ name: "no-construct-in-interface",
126
143
  meta: {
127
144
  type: "problem",
128
145
  docs: {
@@ -160,7 +177,8 @@ const noConstructInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
160
177
  }
161
178
  });
162
179
 
163
- const noConstructInPublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
180
+ const noConstructInPublicPropertyOfConstruct = createRule({
181
+ name: "no-construct-in-public-property-of-construct",
164
182
  meta: {
165
183
  type: "problem",
166
184
  docs: {
@@ -271,7 +289,8 @@ const SUFFIX_TYPE = {
271
289
  CONSTRUCT: "Construct",
272
290
  STACK: "Stack"
273
291
  };
274
- const noConstructStackSuffix = utils.ESLintUtils.RuleCreator.withoutDocs({
292
+ const noConstructStackSuffix = createRule({
293
+ name: "no-construct-stack-suffix",
275
294
  meta: {
276
295
  type: "problem",
277
296
  docs: {
@@ -354,6 +373,7 @@ const noImportPrivate = {
354
373
  meta: {
355
374
  type: "problem",
356
375
  docs: {
376
+ url: "https://eslint-cdk-plugin.dev/rules/no-import-private",
357
377
  description: "Cannot import modules from private dir at different levels of the hierarchy."
358
378
  },
359
379
  messages: {
@@ -386,7 +406,8 @@ const getDirSegments = (dirPath) => {
386
406
  return dirPath.split(path__namespace.sep).filter((segment) => segment !== "");
387
407
  };
388
408
 
389
- const noMutablePropertyOfPropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
409
+ const noMutablePropertyOfPropsInterface = createRule({
410
+ name: "no-mutable-property-of-props-interface",
390
411
  meta: {
391
412
  type: "problem",
392
413
  docs: {
@@ -426,7 +447,8 @@ const noMutablePropertyOfPropsInterface = utils.ESLintUtils.RuleCreator.withoutD
426
447
  }
427
448
  });
428
449
 
429
- const noMutablePublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
450
+ const noMutablePublicPropertyOfConstruct = createRule({
451
+ name: "no-mutable-public-property-of-construct",
430
452
  meta: {
431
453
  type: "problem",
432
454
  docs: {
@@ -477,64 +499,63 @@ const noMutablePublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.without
477
499
  }
478
500
  });
479
501
 
480
- const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
481
- {
482
- meta: {
483
- type: "problem",
484
- docs: {
485
- description: "Enforce that construct IDs does not match the parent construct name."
486
- },
487
- messages: {
488
- invalidConstructId: "Construct ID '{{ constructId }}' should not match parent construct name '{{ parentConstructName }}'. Use a more specific identifier."
489
- },
490
- schema: [
491
- {
492
- type: "object",
493
- properties: {
494
- disallowContainingParentName: {
495
- type: "boolean",
496
- default: false
497
- }
498
- },
499
- additionalProperties: false
500
- }
501
- ]
502
+ const noParentNameConstructIdMatch = createRule({
503
+ name: "no-parent-name-construct-id-match",
504
+ meta: {
505
+ type: "problem",
506
+ docs: {
507
+ description: "Enforce that construct IDs does not match the parent construct name."
508
+ },
509
+ messages: {
510
+ invalidConstructId: "Construct ID '{{ constructId }}' should not match parent construct name '{{ parentConstructName }}'. Use a more specific identifier."
502
511
  },
503
- defaultOptions: [
512
+ schema: [
504
513
  {
505
- disallowContainingParentName: false
514
+ type: "object",
515
+ properties: {
516
+ disallowContainingParentName: {
517
+ type: "boolean",
518
+ default: false
519
+ }
520
+ },
521
+ additionalProperties: false
506
522
  }
507
- ],
508
- create(context) {
509
- const option = context.options[0] || {
510
- disallowContainingParentName: false
511
- };
512
- const parserServices = utils.ESLintUtils.getParserServices(context);
513
- return {
514
- ClassBody(node) {
515
- const type = parserServices.getTypeAtLocation(node);
516
- if (!isConstructOrStackType(type)) return;
517
- const parent = node.parent;
518
- if (parent?.type !== utils.AST_NODE_TYPES.ClassDeclaration) return;
519
- const parentClassName = parent.id?.name;
520
- if (!parentClassName) return;
521
- for (const body of node.body) {
522
- if (body.type !== utils.AST_NODE_TYPES.MethodDefinition || !["method", "constructor"].includes(body.kind) || body.value.type !== utils.AST_NODE_TYPES.FunctionExpression) {
523
- continue;
524
- }
525
- validateConstructorBody({
526
- expression: body.value,
527
- parentClassName,
528
- context,
529
- parserServices,
530
- option
531
- });
523
+ ]
524
+ },
525
+ defaultOptions: [
526
+ {
527
+ disallowContainingParentName: false
528
+ }
529
+ ],
530
+ create(context) {
531
+ const option = context.options[0] || {
532
+ disallowContainingParentName: false
533
+ };
534
+ const parserServices = utils.ESLintUtils.getParserServices(context);
535
+ return {
536
+ ClassBody(node) {
537
+ const type = parserServices.getTypeAtLocation(node);
538
+ if (!isConstructOrStackType(type)) return;
539
+ const parent = node.parent;
540
+ if (parent?.type !== utils.AST_NODE_TYPES.ClassDeclaration) return;
541
+ const parentClassName = parent.id?.name;
542
+ if (!parentClassName) return;
543
+ for (const body of node.body) {
544
+ if (body.type !== utils.AST_NODE_TYPES.MethodDefinition || !["method", "constructor"].includes(body.kind) || body.value.type !== utils.AST_NODE_TYPES.FunctionExpression) {
545
+ continue;
532
546
  }
547
+ validateConstructorBody({
548
+ expression: body.value,
549
+ parentClassName,
550
+ context,
551
+ parserServices,
552
+ option
553
+ });
533
554
  }
534
- };
535
- }
555
+ }
556
+ };
536
557
  }
537
- );
558
+ });
538
559
  const validateConstructorBody = ({
539
560
  expression,
540
561
  parentClassName,
@@ -767,7 +788,8 @@ const validateConstructId$2 = ({
767
788
  }
768
789
  };
769
790
 
770
- const noVariableConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
791
+ const noVariableConstructId = createRule({
792
+ name: "no-variable-construct-id",
771
793
  meta: {
772
794
  type: "problem",
773
795
  docs: {
@@ -832,7 +854,8 @@ const QUOTE_TYPE = {
832
854
  SINGLE: "'",
833
855
  DOUBLE: '"'
834
856
  };
835
- const pascalCaseConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
857
+ const pascalCaseConstructId = createRule({
858
+ name: "pascal-case-construct-id",
836
859
  meta: {
837
860
  type: "problem",
838
861
  docs: {
@@ -881,7 +904,8 @@ const validateConstructId = (node, context) => {
881
904
  });
882
905
  };
883
906
 
884
- const propsNameConvention = utils.ESLintUtils.RuleCreator.withoutDocs({
907
+ const propsNameConvention = createRule({
908
+ name: "props-name-convention",
885
909
  meta: {
886
910
  type: "problem",
887
911
  docs: {
@@ -928,7 +952,8 @@ const propsNameConvention = utils.ESLintUtils.RuleCreator.withoutDocs({
928
952
  }
929
953
  });
930
954
 
931
- const requireJSDoc = utils.ESLintUtils.RuleCreator.withoutDocs({
955
+ const requireJSDoc = createRule({
956
+ name: "require-jsdoc",
932
957
  meta: {
933
958
  type: "problem",
934
959
  docs: {
@@ -993,7 +1018,8 @@ const requireJSDoc = utils.ESLintUtils.RuleCreator.withoutDocs({
993
1018
  }
994
1019
  });
995
1020
 
996
- const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
1021
+ const requirePassingThis = createRule({
1022
+ name: "require-passing-this",
997
1023
  meta: {
998
1024
  type: "problem",
999
1025
  docs: {
@@ -1058,7 +1084,8 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
1058
1084
  }
1059
1085
  });
1060
1086
 
1061
- const requirePropsDefaultDoc = utils.ESLintUtils.RuleCreator.withoutDocs({
1087
+ const requirePropsDefaultDoc = createRule({
1088
+ name: "require-props-default-doc",
1062
1089
  meta: {
1063
1090
  type: "problem",
1064
1091
  docs: {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import tsParser from "@typescript-eslint/parser";
2
2
  declare const rules: {
3
- "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
3
+ "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty" | "invalidConstructorType" | "invalidConstructorIdType", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
4
4
  "no-construct-in-interface": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidInterfaceProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
5
5
  "no-construct-in-public-property-of-construct": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidPublicPropertyOfConstruct", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
6
6
  "no-construct-stack-suffix": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructId", [{
@@ -36,7 +36,7 @@ declare const configs: {
36
36
  version: string;
37
37
  };
38
38
  rules: {
39
- "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
39
+ "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty" | "invalidConstructorType" | "invalidConstructorIdType", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
40
40
  "no-construct-in-interface": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidInterfaceProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
41
41
  "no-construct-in-public-property-of-construct": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidPublicPropertyOfConstruct", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
42
42
  "no-construct-stack-suffix": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructId", [{
@@ -75,7 +75,7 @@ declare const configs: {
75
75
  version: string;
76
76
  };
77
77
  rules: {
78
- "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
78
+ "construct-constructor-property": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructorProperty" | "invalidConstructorType" | "invalidConstructorIdType", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
79
79
  "no-construct-in-interface": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidInterfaceProperty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
80
80
  "no-construct-in-public-property-of-construct": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidPublicPropertyOfConstruct", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
81
81
  "no-construct-stack-suffix": import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidConstructId", [{