eslint-cdk-plugin 0.3.2 → 1.0.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.
Files changed (44) hide show
  1. package/CONTRIBUTING.md +105 -0
  2. package/README.md +51 -6
  3. package/VERSIONING_POLICY.md +34 -0
  4. package/assets/logo.png +0 -0
  5. package/dist/index.d.mts +31 -0
  6. package/dist/index.mjs +9 -2
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/no-class-in-interface-props.d.mts +2 -0
  9. package/dist/{no-class-in-interface.mjs → no-class-in-interface-props.mjs} +13 -14
  10. package/dist/no-class-in-interface-props.mjs.map +1 -0
  11. package/dist/no-construct-stack-suffix.d.mts +2 -0
  12. package/dist/no-construct-stack-suffix.mjs +20 -148
  13. package/dist/no-construct-stack-suffix.mjs.map +1 -0
  14. package/dist/no-import-private.d.mts +2 -0
  15. package/dist/no-import-private.mjs +18 -24
  16. package/dist/no-import-private.mjs.map +1 -0
  17. package/dist/no-mutable-props-interface.d.mts +2 -0
  18. package/dist/no-mutable-props-interface.mjs +14 -19
  19. package/dist/no-mutable-props-interface.mjs.map +1 -0
  20. package/dist/no-mutable-public-fields.d.mts +2 -0
  21. package/dist/no-mutable-public-fields.mjs +26 -25
  22. package/dist/no-mutable-public-fields.mjs.map +1 -0
  23. package/dist/no-parent-name-construct-id-match.d.mts +2 -0
  24. package/dist/no-parent-name-construct-id-match.mjs +101 -140
  25. package/dist/no-parent-name-construct-id-match.mjs.map +1 -0
  26. package/dist/no-public-class-fields.d.mts +2 -0
  27. package/dist/no-public-class-fields.mjs +40 -46
  28. package/dist/no-public-class-fields.mjs.map +1 -0
  29. package/dist/no-variable-construct-id.d.mts +2 -0
  30. package/dist/no-variable-construct-id.mjs +63 -0
  31. package/dist/no-variable-construct-id.mjs.map +1 -0
  32. package/dist/pascal-case-construct-id.d.mts +2 -0
  33. package/dist/pascal-case-construct-id.mjs +40 -47
  34. package/dist/pascal-case-construct-id.mjs.map +1 -0
  35. package/dist/require-passing-this.d.mts +2 -0
  36. package/dist/require-passing-this.mjs +39 -0
  37. package/dist/require-passing-this.mjs.map +1 -0
  38. package/dist/utils/convertString.d.mts +1 -0
  39. package/dist/utils/convertString.mjs +4 -9
  40. package/dist/utils/convertString.mjs.map +1 -0
  41. package/dist/utils/typeCheck.d.mts +3 -0
  42. package/dist/utils/typeCheck.mjs +16 -0
  43. package/dist/utils/typeCheck.mjs.map +1 -0
  44. package/package.json +6 -3
@@ -1,6 +1,7 @@
1
- import { ESLintUtils, } from "@typescript-eslint/utils";
1
+ import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
2
2
  import { SymbolFlags } from "typescript";
3
- export var noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
3
+ import { isConstructOrStackType } from "./utils/typeCheck.mjs";
4
+ export const noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
4
5
  meta: {
5
6
  type: "problem",
6
7
  docs: {
@@ -12,57 +13,54 @@ export var noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
12
13
  schema: [],
13
14
  },
14
15
  defaultOptions: [],
15
- create: function (context) {
16
- var parserServices = ESLintUtils.getParserServices(context);
17
- var typeChecker = parserServices.program.getTypeChecker();
16
+ create(context) {
17
+ const parserServices = ESLintUtils.getParserServices(context);
18
+ const typeChecker = parserServices.program.getTypeChecker();
18
19
  return {
19
- ClassDeclaration: function (node) {
20
- // NOTE: Check class members
20
+ ClassDeclaration(node) {
21
+ const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
22
+ if (!isConstructOrStackType(type)) {
23
+ return;
24
+ }
21
25
  validateClassMember({
22
- node: node,
23
- context: context,
24
- parserServices: parserServices,
25
- typeChecker: typeChecker,
26
- });
27
- // NOTE: Check constructor parameter properties
28
- var constructor = node.body.body.find(function (member) {
29
- return member.type === "MethodDefinition" && member.kind === "constructor";
26
+ node,
27
+ context,
28
+ parserServices,
29
+ typeChecker,
30
30
  });
31
- if (!constructor || constructor.value.type !== "FunctionExpression") {
31
+ const constructor = node.body.body.find((member) => member.type === AST_NODE_TYPES.MethodDefinition &&
32
+ member.kind === "constructor");
33
+ if (!constructor ||
34
+ constructor.value.type !== AST_NODE_TYPES.FunctionExpression) {
32
35
  return;
33
36
  }
34
37
  validateConstructorParameterProperty({
35
- constructor: constructor,
36
- context: context,
37
- parserServices: parserServices,
38
- typeChecker: typeChecker,
38
+ constructor,
39
+ context,
40
+ parserServices,
41
+ typeChecker,
39
42
  });
40
43
  },
41
44
  };
42
45
  },
43
46
  });
44
- var validateClassMember = function (_a) {
45
- var _b;
46
- var node = _a.node, context = _a.context, parserServices = _a.parserServices, typeChecker = _a.typeChecker;
47
- for (var _i = 0, _c = node.body.body; _i < _c.length; _i++) {
48
- var member = _c[_i];
49
- if (member.type !== "PropertyDefinition" ||
50
- member.key.type !== "Identifier") {
47
+ const validateClassMember = ({ node, context, parserServices, typeChecker, }) => {
48
+ for (const member of node.body.body) {
49
+ if (member.type !== AST_NODE_TYPES.PropertyDefinition ||
50
+ member.key.type !== AST_NODE_TYPES.Identifier) {
51
51
  continue;
52
52
  }
53
- // NOTE: Skip private and protected fields
54
- if (["private", "protected"].includes((_b = member.accessibility) !== null && _b !== void 0 ? _b : "")) {
53
+ if (["private", "protected"].includes(member.accessibility ?? "")) {
55
54
  continue;
56
55
  }
57
- // NOTE: Skip fields without type annotation
58
56
  if (!member.typeAnnotation) {
59
57
  continue;
60
58
  }
61
- var tsNode = parserServices.esTreeNodeToTSNodeMap.get(member);
62
- var type = typeChecker.getTypeAtLocation(tsNode);
59
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(member);
60
+ const type = typeChecker.getTypeAtLocation(tsNode);
63
61
  if (!type.symbol)
64
62
  continue;
65
- var isClass = type.symbol.flags === SymbolFlags.Class;
63
+ const isClass = type.symbol.flags === SymbolFlags.Class;
66
64
  if (!isClass)
67
65
  continue;
68
66
  context.report({
@@ -75,28 +73,23 @@ var validateClassMember = function (_a) {
75
73
  });
76
74
  }
77
75
  };
78
- var validateConstructorParameterProperty = function (_a) {
79
- var _b;
80
- var constructor = _a.constructor, context = _a.context, parserServices = _a.parserServices, typeChecker = _a.typeChecker;
81
- for (var _i = 0, _c = constructor.value.params; _i < _c.length; _i++) {
82
- var param = _c[_i];
83
- if (param.type !== "TSParameterProperty" ||
84
- param.parameter.type !== "Identifier") {
76
+ const validateConstructorParameterProperty = ({ constructor, context, parserServices, typeChecker, }) => {
77
+ for (const param of constructor.value.params) {
78
+ if (param.type !== AST_NODE_TYPES.TSParameterProperty ||
79
+ param.parameter.type !== AST_NODE_TYPES.Identifier) {
85
80
  continue;
86
81
  }
87
- // NOTE: Skip private and protected parameters
88
- if (["private", "protected"].includes((_b = param.accessibility) !== null && _b !== void 0 ? _b : "")) {
82
+ if (["private", "protected"].includes(param.accessibility ?? "")) {
89
83
  continue;
90
84
  }
91
- // NOTE: Skip parameters without type annotation
92
85
  if (!param.parameter.typeAnnotation) {
93
86
  continue;
94
87
  }
95
- var tsNode = parserServices.esTreeNodeToTSNodeMap.get(param);
96
- var type = typeChecker.getTypeAtLocation(tsNode);
88
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(param);
89
+ const type = typeChecker.getTypeAtLocation(tsNode);
97
90
  if (!type.symbol)
98
91
  continue;
99
- var isClass = type.symbol.flags === SymbolFlags.Class;
92
+ const isClass = type.symbol.flags === SymbolFlags.Class;
100
93
  if (!isClass)
101
94
  continue;
102
95
  context.report({
@@ -109,3 +102,4 @@ var validateConstructorParameterProperty = function (_a) {
109
102
  });
110
103
  }
111
104
  };
105
+ //# sourceMappingURL=no-public-class-fields.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-public-class-fields.mjs","sourceRoot":"","sources":["../src/no-public-class-fields.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noVariableConstructId: ESLintUtils.RuleModule<"noVariableConstructId", [], unknown, ESLintUtils.RuleListener>;
@@ -0,0 +1,63 @@
1
+ import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
2
+ import { isConstructType } from "./utils/typeCheck.mjs";
3
+ export const noVariableConstructId = ESLintUtils.RuleCreator.withoutDocs({
4
+ meta: {
5
+ type: "problem",
6
+ docs: {
7
+ description: `Enforce using literal strings for Construct ID.`,
8
+ },
9
+ messages: {
10
+ noVariableConstructId: "Shouldn't use a parameter as a Construct ID.",
11
+ },
12
+ schema: [],
13
+ },
14
+ defaultOptions: [],
15
+ create(context) {
16
+ const parserServices = ESLintUtils.getParserServices(context);
17
+ const typeChecker = parserServices.program.getTypeChecker();
18
+ return {
19
+ NewExpression(node) {
20
+ const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
21
+ if (!isConstructType(type)) {
22
+ return;
23
+ }
24
+ if (node.arguments.length < 2)
25
+ return;
26
+ validateConstructId(node, context, node);
27
+ },
28
+ };
29
+ },
30
+ });
31
+ const validateConstructId = (node, context, expression) => {
32
+ if (expression.arguments.length < 2 || isInsideLoop(node)) {
33
+ return;
34
+ }
35
+ const secondArg = expression.arguments[1];
36
+ if (secondArg.type === AST_NODE_TYPES.Literal &&
37
+ typeof secondArg.value === "string") {
38
+ return;
39
+ }
40
+ if (secondArg.type === AST_NODE_TYPES.TemplateLiteral &&
41
+ !secondArg.expressions.length) {
42
+ return;
43
+ }
44
+ context.report({
45
+ node,
46
+ messageId: "noVariableConstructId",
47
+ });
48
+ };
49
+ const isInsideLoop = (node) => {
50
+ let current = node.parent;
51
+ while (current) {
52
+ if (current.type === AST_NODE_TYPES.ForStatement ||
53
+ current.type === AST_NODE_TYPES.ForInStatement ||
54
+ current.type === AST_NODE_TYPES.ForOfStatement ||
55
+ current.type === AST_NODE_TYPES.WhileStatement ||
56
+ current.type === AST_NODE_TYPES.DoWhileStatement) {
57
+ return true;
58
+ }
59
+ current = current.parent;
60
+ }
61
+ return false;
62
+ };
63
+ //# sourceMappingURL=no-variable-construct-id.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-variable-construct-id.mjs","sourceRoot":"","sources":["../src/no-variable-construct-id.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AASxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACvE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,iDAAiD;SAC/D;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,8CAA8C;SACtE;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAE5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBACF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBAEtC,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAKH,MAAM,mBAAmB,GAAG,CAC1B,IAAmB,EACnB,OAAgB,EAChB,UAAkC,EAClC,EAAE;IACF,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,OAAO;IACT,CAAC;IAGD,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAG1C,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACzC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;QACD,OAAO;IACT,CAAC;IAGD,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QACjD,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAC7B,CAAC;QACD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,MAAM,CAAC;QACb,IAAI;QACJ,SAAS,EAAE,uBAAuB;KACnC,CAAC,CAAC;AACL,CAAC,CAAC;AAKF,MAAM,YAAY,GAAG,CAAC,IAAmB,EAAW,EAAE;IACpD,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1B,OAAO,OAAO,EAAE,CAAC;QACf,IACE,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,YAAY;YAC5C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EAChD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const pascalCaseConstructId: ESLintUtils.RuleModule<"pascalCaseConstructId", [], unknown, ESLintUtils.RuleListener>;
@@ -1,40 +1,11 @@
1
+ import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
1
2
  import { toPascalCase } from "./utils/convertString.mjs";
2
- var QUOTE_TYPE = {
3
+ import { isConstructOrStackType } from "./utils/typeCheck.mjs";
4
+ const QUOTE_TYPE = {
3
5
  SINGLE: "'",
4
6
  DOUBLE: '"',
5
7
  };
6
- /**
7
- * check if the string is PascalCase
8
- * @param str - The string to check
9
- * @returns true if the string is PascalCase, false otherwise
10
- */
11
- var isPascalCase = function (str) {
12
- return /^[A-Z][a-zA-Z0-9]*$/.test(str);
13
- };
14
- var validateConstructId = function (node, context, args) {
15
- var _a;
16
- if (args.length < 2)
17
- return;
18
- // NOTE: Treat the second argument as ID
19
- var secondArg = args[1];
20
- if (secondArg.type !== "Literal" || typeof secondArg.value !== "string") {
21
- return;
22
- }
23
- var quote = ((_a = secondArg.raw) === null || _a === void 0 ? void 0 : _a.startsWith('"'))
24
- ? QUOTE_TYPE.DOUBLE
25
- : QUOTE_TYPE.SINGLE;
26
- if (!isPascalCase(secondArg.value)) {
27
- context.report({
28
- node: node,
29
- messageId: "pascalCaseConstructId",
30
- fix: function (fixer) {
31
- var pascalCaseValue = toPascalCase(secondArg.value);
32
- return fixer.replaceText(secondArg, "".concat(quote).concat(pascalCaseValue).concat(quote));
33
- },
34
- });
35
- }
36
- };
37
- export var pascalCaseConstructId = {
8
+ export const pascalCaseConstructId = ESLintUtils.RuleCreator.withoutDocs({
38
9
  meta: {
39
10
  type: "problem",
40
11
  docs: {
@@ -46,24 +17,46 @@ export var pascalCaseConstructId = {
46
17
  schema: [],
47
18
  fixable: "code",
48
19
  },
49
- create: function (context) {
20
+ defaultOptions: [],
21
+ create(context) {
22
+ const parserServices = ESLintUtils.getParserServices(context);
23
+ const typeChecker = parserServices.program.getTypeChecker();
50
24
  return {
51
- ExpressionStatement: function (node) {
52
- if (node.expression.type !== "NewExpression")
53
- return;
54
- validateConstructId(node, context, node.expression.arguments);
55
- },
56
- VariableDeclaration: function (node) {
57
- var _a;
58
- if (!node.declarations.length)
25
+ NewExpression(node) {
26
+ const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
27
+ if (!isConstructOrStackType(type)) {
59
28
  return;
60
- for (var _i = 0, _b = node.declarations; _i < _b.length; _i++) {
61
- var declaration = _b[_i];
62
- if (((_a = declaration.init) === null || _a === void 0 ? void 0 : _a.type) !== "NewExpression")
63
- return;
64
- validateConstructId(node, context, declaration.init.arguments);
65
29
  }
30
+ if (node.arguments.length < 2)
31
+ return;
32
+ validateConstructId(node, context, node);
66
33
  },
67
34
  };
68
35
  },
36
+ });
37
+ const isPascalCase = (str) => {
38
+ return /^[A-Z][a-zA-Z0-9]*$/.test(str);
39
+ };
40
+ const validateConstructId = (node, context, expression) => {
41
+ if (expression.arguments.length < 2)
42
+ return;
43
+ const secondArg = expression.arguments[1];
44
+ if (secondArg.type !== AST_NODE_TYPES.Literal ||
45
+ typeof secondArg.value !== "string") {
46
+ return;
47
+ }
48
+ const quote = secondArg.raw?.startsWith('"')
49
+ ? QUOTE_TYPE.DOUBLE
50
+ : QUOTE_TYPE.SINGLE;
51
+ if (!isPascalCase(secondArg.value)) {
52
+ context.report({
53
+ node,
54
+ messageId: "pascalCaseConstructId",
55
+ fix: (fixer) => {
56
+ const pascalCaseValue = toPascalCase(secondArg.value);
57
+ return fixer.replaceText(secondArg, `${quote}${pascalCaseValue}${quote}`);
58
+ },
59
+ });
60
+ }
69
61
  };
62
+ //# sourceMappingURL=pascal-case-construct-id.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pascal-case-construct-id.mjs","sourceRoot":"","sources":["../src/pascal-case-construct-id.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;CACH,CAAC;AAaX,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACvE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,sCAAsC;SACpD;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,kCAAkC;SAC1D;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,MAAM;KAChB;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBACF,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAClC,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBAEtC,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAOH,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE;IACnC,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC,CAAC;AAKF,MAAM,mBAAmB,GAAG,CAC1B,IAAmB,EACnB,OAAgB,EAChB,UAAkC,EAClC,EAAE;IACF,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO;IAG5C,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1C,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACzC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAc,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC;QACrD,CAAC,CAAC,UAAU,CAAC,MAAM;QACnB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;IAEtB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,CAAC;YACb,IAAI;YACJ,SAAS,EAAE,uBAAuB;YAClC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBACb,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,KAAe,CAAC,CAAC;gBAChE,OAAO,KAAK,CAAC,WAAW,CACtB,SAAS,EACT,GAAG,KAAK,GAAG,eAAe,GAAG,KAAK,EAAE,CACrC,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const requirePassingThis: ESLintUtils.RuleModule<"requirePassingThis", [], unknown, ESLintUtils.RuleListener>;
@@ -0,0 +1,39 @@
1
+ import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
2
+ import { isConstructType } from "./utils/typeCheck.mjs";
3
+ export const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
4
+ meta: {
5
+ type: "problem",
6
+ docs: {
7
+ description: "Require passing `this` in a constructor.",
8
+ },
9
+ messages: {
10
+ requirePassingThis: "Require passing `this` in a constructor.",
11
+ },
12
+ schema: [],
13
+ fixable: "code",
14
+ },
15
+ defaultOptions: [],
16
+ create(context) {
17
+ const parserServices = ESLintUtils.getParserServices(context);
18
+ const typeChecker = parserServices.program.getTypeChecker();
19
+ return {
20
+ NewExpression(node) {
21
+ const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
22
+ if (!isConstructType(type) || !node.arguments.length) {
23
+ return;
24
+ }
25
+ const argument = node.arguments[0];
26
+ if (argument.type !== AST_NODE_TYPES.ThisExpression) {
27
+ context.report({
28
+ node,
29
+ messageId: "requirePassingThis",
30
+ fix: (fixer) => {
31
+ return fixer.replaceText(argument, "this");
32
+ },
33
+ });
34
+ }
35
+ },
36
+ };
37
+ },
38
+ });
39
+ //# sourceMappingURL=require-passing-this.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-passing-this.mjs","sourceRoot":"","sources":["../src/require-passing-this.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACpE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,0CAA0C;SACxD;QACD,QAAQ,EAAE;YACR,kBAAkB,EAAE,0CAA0C;SAC/D;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,MAAM;KAChB;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBAEF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;oBACrD,OAAO;gBACT,CAAC;gBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAEnC,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EAAE,CAAC;oBACpD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,oBAAoB;wBAC/B,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;4BACb,OAAO,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;wBAC7C,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const toPascalCase: (str: string) => string;
@@ -1,18 +1,13 @@
1
- /**
2
- * Convert a string to PascalCase
3
- * @param str - The string to convert
4
- * @returns The PascalCase string
5
- */
6
- export var toPascalCase = function (str) {
1
+ export const toPascalCase = (str) => {
7
2
  return str
8
3
  .split(/[-_\s]/)
9
- .map(function (word) {
10
- // Consider camelCase, split by uppercase letters
4
+ .map((word) => {
11
5
  return word
12
6
  .replace(/([A-Z])/g, " $1")
13
7
  .split(/\s+/)
14
- .map(function (part) { return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(); })
8
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
15
9
  .join("");
16
10
  })
17
11
  .join("");
18
12
  };
13
+ //# sourceMappingURL=convertString.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convertString.mjs","sourceRoot":"","sources":["../../src/utils/convertString.mts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,OAAO,GAAG;SACP,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAEZ,OAAO,IAAI;aACR,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;aAC1B,KAAK,CAAC,KAAK,CAAC;aACZ,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CACrE;aACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Type } from "typescript";
2
+ export declare const isConstructOrStackType: (type: Type) => boolean;
3
+ export declare const isConstructType: (type: Type) => boolean;
@@ -0,0 +1,16 @@
1
+ export const isConstructOrStackType = (type) => {
2
+ return isTargetSuperClassType(type, ["Construct", "Stack"]);
3
+ };
4
+ export const isConstructType = (type) => {
5
+ return isTargetSuperClassType(type, ["Construct"]);
6
+ };
7
+ const isTargetSuperClassType = (type, targetSuperClasses) => {
8
+ if (!type.symbol)
9
+ return false;
10
+ if (targetSuperClasses.some((suffix) => type.symbol.name.endsWith(suffix))) {
11
+ return true;
12
+ }
13
+ const baseTypes = type.getBaseTypes() || [];
14
+ return baseTypes.some((baseType) => isConstructOrStackType(baseType));
15
+ };
16
+ //# sourceMappingURL=typeCheck.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeCheck.mjs","sourceRoot":"","sources":["../../src/utils/typeCheck.mts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,IAAU,EAAW,EAAE;IAC5D,OAAO,sBAAsB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAU,EAAW,EAAE;IACrD,OAAO,sBAAsB,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AAQF,MAAM,sBAAsB,GAAG,CAC7B,IAAU,EACV,kBAAoC,EAC3B,EAAE;IACX,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAG/B,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAC5C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "eslint-cdk-plugin",
3
- "version": "0.3.2",
3
+ "version": "1.0.0",
4
4
  "description": "eslint plugin for AWS CDK projects",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "build": "rm -rf dist && tsc src/*.*ts --outDir dist --skipLibCheck",
8
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
9
9
  "test": "vitest --run",
10
10
  "lint": "eslint --fix --config eslint.config.mjs",
11
11
  "release:minor": "standard-version --release-as minor",
@@ -36,7 +36,10 @@
36
36
  "files": [
37
37
  "dist",
38
38
  "README.md",
39
- "LICENSE"
39
+ "LICENSE",
40
+ "CONTRIBUTING.md",
41
+ "VERSIONING_POLICY.md",
42
+ "assets"
40
43
  ],
41
44
  "keywords": [
42
45
  "eslint",