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
@@ -0,0 +1,105 @@
1
+ # Contributing to eslint-cdk-plugin
2
+
3
+ Thank you for your interest in contributing to eslint-cdk-plugin!
4
+ This document provides guidelines and steps for contributing.
5
+
6
+ ## Code of Conduct
7
+
8
+ By participating in this project, you are expected to uphold our Code of Conduct.
9
+ Please report unacceptable behavior to `@ren-yamanashi`.
10
+
11
+ ## How to Contribute
12
+
13
+ ### Create Bugs Issue
14
+
15
+ Before creating issue, please check the existing issues to avoid duplicates.
16
+ When you create a bug issue, include as following content:
17
+
18
+ - A clear and descriptive title
19
+ - Steps to reproduce the behavior
20
+ - Expected behavior
21
+ - Actual behavior
22
+ - Code samples if applicable
23
+ - Version information (Node.js, ESLint)
24
+
25
+ ### Create Feature Request Issue
26
+
27
+ We welcome suggestions for new rules!
28
+ When proposing a new rule:
29
+
30
+ 1. First, check existing rules and issues to avoid duplicates
31
+ 2. Create an issue with the following information:
32
+ - Rule name
33
+ - Description of the problem the rule solves
34
+ - Examples of code that should pass/fail
35
+ - References to AWS CDK best practices if applicable
36
+
37
+ ### Pull Requests
38
+
39
+ 1. Fork the repo and create your branch from `main`
40
+ 2. Implement the rules
41
+ 3. Implement the test for the rule and make sure it passes. (Tests are run in CI)
42
+ 4. Update the documentation
43
+ 5. Create a pull request
44
+
45
+ #### Development Setup
46
+
47
+ ```bash
48
+ # Clone your fork
49
+ https://github.com/ren-yamanashi/eslint-cdk-plugin.git
50
+
51
+ # Install dependencies
52
+ pnpm install
53
+
54
+ # Run tests
55
+ pnpm test
56
+
57
+ # Run linter
58
+ pnpm lint
59
+ ```
60
+
61
+ #### Creating a New Rule
62
+
63
+ 1. Create a new file in `src`(file name should same rule name)
64
+ 2. Create corresponding test file in `src/__tests__`
65
+ 3. Add rule to `src/index.ts`
66
+ 4. Add documentation in `docs`
67
+
68
+ Note: Writing the document is optional (because it is written using Vitepress and is not yet ready to accept contributions)
69
+
70
+ Example rule structure:
71
+
72
+ ```typescript
73
+ import { ESLintUtils } from "@typescript-eslint/utils";
74
+
75
+ export const newRule = ESLintUtils.RuleCreator.withoutDocs({
76
+ meta: {
77
+ type: "problem",
78
+ docs: {
79
+ description: "Rule description",
80
+ },
81
+ messages: {
82
+ ruleError: "Error message with {{ placeholder }}",
83
+ },
84
+ schema: [],
85
+ },
86
+ defaultOptions: [],
87
+ create(context) {
88
+ // Rule implementation
89
+ },
90
+ });
91
+ ```
92
+
93
+ ## Merge Process
94
+
95
+ 1. Changes are merged to `main`
96
+ 2. Maintainers will review and merge
97
+ 3. Publish to npm according to Milestone
98
+
99
+ ## Questions?
100
+
101
+ Feel free to create an issue for any questions about contributing!
102
+
103
+ ## License
104
+
105
+ By contributing, you agree that your contributions will be licensed under the project's MIT License.
package/README.md CHANGED
@@ -1,8 +1,20 @@
1
- # eslint-cdk-plugin
1
+ <p align="center">
2
+ <img width="160px" height="160px" src="./assets/logo.png" alt="ESLint plugin for AWS CDK logo">
3
+ </p>
2
4
 
3
- ESLint plugin for [AWS CDK](https://github.com/aws/aws-cdk).
5
+ <h1 align="center">eslint-cdk-plugin</h1>
6
+ <p align="center">ESLint plugin for AWS CDK</p>
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/eslint-cdk-plugin">
9
+ <img src="https://img.shields.io/npm/v/eslint-cdk-plugin.svg" alt="NPM">
10
+ </a>
11
+ </p>
4
12
 
5
- ## Installation
13
+ ## 📔 Documentation
14
+
15
+ Please refer to the [website](https://eslint-cdk-plugin.dev/).
16
+
17
+ ## 📦 Installation
6
18
 
7
19
  ```bash
8
20
  # npm
@@ -15,9 +27,9 @@ yarn add -D eslint-cdk-plugin
15
27
  pnpm install -D eslint-cdk-plugin
16
28
  ```
17
29
 
18
- ## Usage
30
+ ## 🚀 Usage
19
31
 
20
- ### Use recommended config
32
+ #### Use recommended config
21
33
 
22
34
  ```js
23
35
  // eslint.config.mjs
@@ -34,4 +46,37 @@ export default [
34
46
  ];
35
47
  ```
36
48
 
37
- ### For more detailed documentation, see [docs for eslint-cdk-plugin](https://eslint-cdk-plugin.dev/)
49
+ #### Use custom config
50
+
51
+ ```js
52
+ // eslint.config.mjs
53
+ import eslintCdkPlugin from "eslint-cdk-plugin";
54
+ export default [
55
+ {
56
+ plugins: {
57
+ cdk: eslintCdkPlugin,
58
+ },
59
+ rules: {
60
+ "cdk/no-class-in-interface": "error",
61
+ "cdk/no-construct-stack-suffix": "error",
62
+ "cdk/no-parent-name-construct-id-match": "error",
63
+ },
64
+ },
65
+ ];
66
+ ```
67
+
68
+ ## ❗ Issue
69
+
70
+ If you have any questions or suggestions, please open an [issue](https://github.com/ren-yamanashi/eslint-cdk-plugin/issues).
71
+
72
+ ## 💪 Contribution
73
+
74
+ Contributions are welcome! Please see [Contribution Guide](./CONTRIBUTING.md) for more details.
75
+
76
+ ## ⚓ Versioning Policy
77
+
78
+ Please see [Versioning Policy](./VERSIONING_POLICY.md).
79
+
80
+ ## ©️ License
81
+
82
+ [MIT](http://opensource.org/licenses/MIT)
@@ -0,0 +1,34 @@
1
+ ## Semantic Versioning Policy
2
+
3
+ eslint-cdk-plugin follows semantic versioning. To clarify when a minor or major version bump occurs, we've defined the following semantic versioning policy:
4
+
5
+ ### Patch Release (intended to not break your lint build)
6
+
7
+ - A bug fix in a rule that results in fewer linting errors
8
+ - A bug fix to the core functionality
9
+ - Improvements to documentation
10
+ - Non-user-facing changes such as refactoring code, adding/modifying tests, and increasing test coverage
11
+ - Re-releasing after a failed release
12
+
13
+ ### Minor Release (might break your lint build)
14
+
15
+ - A bug fix in a rule that results in more linting errors
16
+ - A new rule is added (disabled by default)
17
+ - A new option to an existing rule that does not result in more linting errors by default
18
+ - An existing rule is deprecated
19
+
20
+ ### Major Release (likely to break your lint build)
21
+
22
+ - `recommended` config is updated and may result in new linting errors
23
+ - A new rule is added (enabled by default)
24
+ - Removing deprecated rules or functionality
25
+ - Changes that require a new minimum version of Node.js or ESLint
26
+
27
+ ### Version Pinning Recommendations
28
+
29
+ We recommend using one of the following approaches in your `package.json`:
30
+
31
+ - Use tilde (`~`) to allow only patch releases: `"eslint-cdk-plugin": "~1.1.0"`
32
+ - Use caret (`^`) if you're comfortable with minor updates: `"eslint-cdk-plugin": "^1.1.0"`
33
+
34
+ Note that minor updates may report more linting errors than the previous release, so using tilde is recommended for more stable builds.
Binary file
@@ -0,0 +1,31 @@
1
+ declare const plugin: {
2
+ rules: {
3
+ "no-class-in-interface": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noClassInInterfaceProps", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
4
+ "no-construct-stack-suffix": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noConstructStackSuffix", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
5
+ "no-import-private": import("eslint").Rule.RuleModule;
6
+ "no-parent-name-construct-id-match": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noParentNameConstructIdMatch", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
7
+ "no-public-class-fields": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noPublicClassFields", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
8
+ "pascal-case-construct-id": import("@typescript-eslint/utils/ts-eslint").RuleModule<"pascalCaseConstructId", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
9
+ "no-mutable-public-fields": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noMutablePublicFields", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
10
+ "no-mutable-props-interface": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noMutablePropsInterface", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ "require-passing-this": import("@typescript-eslint/utils/ts-eslint").RuleModule<"requirePassingThis", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
12
+ "no-variable-construct-id": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noVariableConstructId", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ };
14
+ configs: {
15
+ recommended: {
16
+ plugins: string[];
17
+ rules: {
18
+ "cdk/no-class-in-interface": string;
19
+ "cdk/no-construct-stack-suffix": string;
20
+ "cdk/no-parent-name-construct-id-match": string;
21
+ "cdk/no-public-class-fields": string;
22
+ "cdk/pascal-case-construct-id": string;
23
+ "cdk/require-passing-this": string;
24
+ "cdk/no-variable-construct-id": string;
25
+ "cdk/no-mutable-public-fields": string;
26
+ "cdk/no-mutable-props-interface": string;
27
+ };
28
+ };
29
+ };
30
+ };
31
+ export default plugin;
package/dist/index.mjs CHANGED
@@ -1,12 +1,14 @@
1
- import { noClassInInterfaceProps } from "./no-class-in-interface.mjs";
1
+ import { noClassInInterfaceProps } from "./no-class-in-interface-props.mjs";
2
2
  import { noConstructStackSuffix } from "./no-construct-stack-suffix.mjs";
3
3
  import { noImportPrivate } from "./no-import-private.mjs";
4
4
  import { noMutablePropsInterface } from "./no-mutable-props-interface.mjs";
5
5
  import { noMutablePublicFields } from "./no-mutable-public-fields.mjs";
6
6
  import { noParentNameConstructIdMatch } from "./no-parent-name-construct-id-match.mjs";
7
7
  import { noPublicClassFields } from "./no-public-class-fields.mjs";
8
+ import { noVariableConstructId } from "./no-variable-construct-id.mjs";
8
9
  import { pascalCaseConstructId } from "./pascal-case-construct-id.mjs";
9
- var plugin = {
10
+ import { requirePassingThis } from "./require-passing-this.mjs";
11
+ const plugin = {
10
12
  rules: {
11
13
  "no-class-in-interface": noClassInInterfaceProps,
12
14
  "no-construct-stack-suffix": noConstructStackSuffix,
@@ -16,6 +18,8 @@ var plugin = {
16
18
  "pascal-case-construct-id": pascalCaseConstructId,
17
19
  "no-mutable-public-fields": noMutablePublicFields,
18
20
  "no-mutable-props-interface": noMutablePropsInterface,
21
+ "require-passing-this": requirePassingThis,
22
+ "no-variable-construct-id": noVariableConstructId,
19
23
  },
20
24
  configs: {
21
25
  recommended: {
@@ -26,6 +30,8 @@ var plugin = {
26
30
  "cdk/no-parent-name-construct-id-match": "error",
27
31
  "cdk/no-public-class-fields": "error",
28
32
  "cdk/pascal-case-construct-id": "error",
33
+ "cdk/require-passing-this": "error",
34
+ "cdk/no-variable-construct-id": "error",
29
35
  "cdk/no-mutable-public-fields": "warn",
30
36
  "cdk/no-mutable-props-interface": "warn",
31
37
  },
@@ -33,3 +39,4 @@ var plugin = {
33
39
  },
34
40
  };
35
41
  export default plugin;
42
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,MAAM,GAAG;IACb,KAAK,EAAE;QACL,uBAAuB,EAAE,uBAAuB;QAChD,2BAA2B,EAAE,sBAAsB;QACnD,mBAAmB,EAAE,eAAe;QACpC,mCAAmC,EAAE,4BAA4B;QACjE,wBAAwB,EAAE,mBAAmB;QAC7C,0BAA0B,EAAE,qBAAqB;QACjD,0BAA0B,EAAE,qBAAqB;QACjD,4BAA4B,EAAE,uBAAuB;QACrD,sBAAsB,EAAE,kBAAkB;QAC1C,0BAA0B,EAAE,qBAAqB;KAClD;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,KAAK,CAAC;YAChB,KAAK,EAAE;gBACL,2BAA2B,EAAE,OAAO;gBACpC,+BAA+B,EAAE,OAAO;gBACxC,uCAAuC,EAAE,OAAO;gBAChD,4BAA4B,EAAE,OAAO;gBACrC,8BAA8B,EAAE,OAAO;gBACvC,0BAA0B,EAAE,OAAO;gBACnC,8BAA8B,EAAE,OAAO;gBACvC,8BAA8B,EAAE,MAAM;gBACtC,gCAAgC,EAAE,MAAM;aACzC;SACF;KACF;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noClassInInterfaceProps: ESLintUtils.RuleModule<"noClassInInterfaceProps", [], unknown, ESLintUtils.RuleListener>;
@@ -1,6 +1,6 @@
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 noClassInInterfaceProps = ESLintUtils.RuleCreator.withoutDocs({
3
+ export const noClassInInterfaceProps = ESLintUtils.RuleCreator.withoutDocs({
4
4
  meta: {
5
5
  type: "problem",
6
6
  docs: {
@@ -12,23 +12,21 @@ export var noClassInInterfaceProps = ESLintUtils.RuleCreator.withoutDocs({
12
12
  schema: [],
13
13
  },
14
14
  defaultOptions: [],
15
- create: function (context) {
16
- var parserServices = ESLintUtils.getParserServices(context);
17
- var checker = parserServices.program.getTypeChecker();
15
+ create(context) {
16
+ const parserServices = ESLintUtils.getParserServices(context);
17
+ const typeChecker = parserServices.program.getTypeChecker();
18
18
  return {
19
- TSInterfaceDeclaration: function (node) {
20
- for (var _i = 0, _a = node.body.body; _i < _a.length; _i++) {
21
- var property = _a[_i];
22
- if (property.type !== "TSPropertySignature" ||
23
- property.key.type !== "Identifier") {
19
+ TSInterfaceDeclaration(node) {
20
+ for (const property of node.body.body) {
21
+ if (property.type !== AST_NODE_TYPES.TSPropertySignature ||
22
+ property.key.type !== AST_NODE_TYPES.Identifier) {
24
23
  continue;
25
24
  }
26
- var tsNode = parserServices.esTreeNodeToTSNodeMap.get(property);
27
- var type = checker.getTypeAtLocation(tsNode);
25
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(property);
26
+ const type = typeChecker.getTypeAtLocation(tsNode);
28
27
  if (!type.symbol)
29
28
  continue;
30
- // NOTE: check class type
31
- var isClass = type.symbol.flags === SymbolFlags.Class;
29
+ const isClass = type.symbol.flags === SymbolFlags.Class;
32
30
  if (!isClass)
33
31
  continue;
34
32
  context.report({
@@ -44,3 +42,4 @@ export var noClassInInterfaceProps = ESLintUtils.RuleCreator.withoutDocs({
44
42
  };
45
43
  },
46
44
  });
45
+ //# sourceMappingURL=no-class-in-interface-props.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-class-in-interface-props.mjs","sourceRoot":"","sources":["../src/no-class-in-interface-props.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQzC,MAAM,CAAC,MAAM,uBAAuB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACzE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,8CAA8C;SAC5D;QACD,QAAQ,EAAE;YACR,uBAAuB,EACrB,wIAAwI;SAC3I;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;QAC5D,OAAO;YACL,sBAAsB,CAAC,IAAI;gBACzB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAEtC,IACE,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,mBAAmB;wBACpD,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAC/C,CAAC;wBACD,SAAS;oBACX,CAAC;oBAED,MAAM,MAAM,GAAG,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAClE,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;oBACnD,IAAI,CAAC,IAAI,CAAC,MAAM;wBAAE,SAAS;oBAG3B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC;oBACxD,IAAI,CAAC,OAAO;wBAAE,SAAS;oBAEvB,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,QAAQ;wBACd,SAAS,EAAE,yBAAyB;wBACpC,IAAI,EAAE;4BACJ,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI;4BAC/B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;yBAC3B;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noConstructStackSuffix: ESLintUtils.RuleModule<"noConstructStackSuffix", [], unknown, ESLintUtils.RuleListener>;
@@ -1,6 +1,7 @@
1
- import { ESLintUtils } from "@typescript-eslint/utils";
1
+ import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
2
2
  import { toPascalCase } from "./utils/convertString.mjs";
3
- export var noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
3
+ import { isConstructOrStackType } from "./utils/typeCheck.mjs";
4
+ export const noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
4
5
  meta: {
5
6
  type: "problem",
6
7
  docs: {
@@ -12,164 +13,34 @@ export var noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
12
13
  schema: [],
13
14
  },
14
15
  defaultOptions: [],
15
- create: function (context) {
16
+ create(context) {
17
+ const parserServices = ESLintUtils.getParserServices(context);
18
+ const typeChecker = parserServices.program.getTypeChecker();
16
19
  return {
17
- ClassBody: function (node) {
18
- var _a;
19
- var parent = node.parent;
20
- if ((parent === null || parent === void 0 ? void 0 : parent.type) !== "ClassDeclaration")
20
+ NewExpression(node) {
21
+ const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
22
+ if (!isConstructOrStackType(type)) {
21
23
  return;
22
- var className = (_a = parent.id) === null || _a === void 0 ? void 0 : _a.name;
23
- if (!className)
24
- return;
25
- for (var _i = 0, _b = node.body; _i < _b.length; _i++) {
26
- var body = _b[_i];
27
- if (body.type !== "MethodDefinition" ||
28
- !["method", "constructor"].includes(body.kind) ||
29
- body.value.type !== "FunctionExpression") {
30
- continue;
31
- }
32
- validateConstructorBody(node, body.value, context);
33
24
  }
25
+ if (node.arguments.length < 2)
26
+ return;
27
+ validateConstructId(node, context, node);
34
28
  },
35
29
  };
36
30
  },
37
31
  });
38
- /**
39
- * Validate the constructor body for the parent class
40
- * - validate each statement in the constructor body
41
- */
42
- var validateConstructorBody = function (node, expression, context) {
43
- var _a;
44
- for (var _i = 0, _b = expression.body.body; _i < _b.length; _i++) {
45
- var statement = _b[_i];
46
- switch (statement.type) {
47
- case "VariableDeclaration": {
48
- var newExpression = statement.declarations[0].init;
49
- if ((newExpression === null || newExpression === void 0 ? void 0 : newExpression.type) !== "NewExpression")
50
- continue;
51
- validateConstructId(node, context, newExpression);
52
- break;
53
- }
54
- case "ExpressionStatement": {
55
- if (((_a = statement.expression) === null || _a === void 0 ? void 0 : _a.type) !== "NewExpression")
56
- break;
57
- validateStatement(node, statement, context);
58
- break;
59
- }
60
- case "IfStatement": {
61
- traverseStatements(node, statement.consequent, context);
62
- break;
63
- }
64
- case "SwitchStatement": {
65
- for (var _c = 0, _d = statement.cases; _c < _d.length; _c++) {
66
- var switchCase = _d[_c];
67
- for (var _e = 0, _f = switchCase.consequent; _e < _f.length; _e++) {
68
- var statement_1 = _f[_e];
69
- traverseStatements(node, statement_1, context);
70
- }
71
- }
72
- break;
73
- }
74
- }
75
- }
76
- };
77
- /**
78
- * Recursively traverse and validate statements in the AST
79
- * - Handles BlockStatement, ExpressionStatement, and VariableDeclaration
80
- * - Validates construct IDs
81
- */
82
- var traverseStatements = function (node, statement, context) {
83
- switch (statement.type) {
84
- case "BlockStatement": {
85
- for (var _i = 0, _a = statement.body; _i < _a.length; _i++) {
86
- var body = _a[_i];
87
- validateStatement(node, body, context);
88
- }
89
- break;
90
- }
91
- case "ExpressionStatement": {
92
- var newExpression = statement.expression;
93
- if ((newExpression === null || newExpression === void 0 ? void 0 : newExpression.type) !== "NewExpression")
94
- break;
95
- validateStatement(node, statement, context);
96
- break;
97
- }
98
- case "VariableDeclaration": {
99
- var newExpression = statement.declarations[0].init;
100
- if ((newExpression === null || newExpression === void 0 ? void 0 : newExpression.type) !== "NewExpression")
101
- break;
102
- validateConstructId(node, context, newExpression);
103
- break;
104
- }
105
- }
106
- };
107
- /**
108
- * Validate a single statement in the AST
109
- * - Handles different types of statements (Variable, Expression, If, Switch)
110
- * - Extracts and validates construct IDs from new expressions
111
- */
112
- var validateStatement = function (node, body, context) {
113
- switch (body.type) {
114
- case "VariableDeclaration": {
115
- var newExpression = body.declarations[0].init;
116
- if ((newExpression === null || newExpression === void 0 ? void 0 : newExpression.type) !== "NewExpression")
117
- break;
118
- validateConstructId(node, context, newExpression);
119
- break;
120
- }
121
- case "ExpressionStatement": {
122
- var newExpression = body.expression;
123
- if ((newExpression === null || newExpression === void 0 ? void 0 : newExpression.type) !== "NewExpression")
124
- break;
125
- validateConstructId(node, context, newExpression);
126
- break;
127
- }
128
- case "IfStatement": {
129
- validateIfStatement(node, body, context);
130
- break;
131
- }
132
- case "SwitchStatement": {
133
- validateSwitchStatement(node, body, context);
134
- break;
135
- }
136
- }
137
- };
138
- /**
139
- * Validate the `if` statement
140
- * - Validate recursively if `if` statements are nested
141
- */
142
- var validateIfStatement = function (node, ifStatement, context) {
143
- traverseStatements(node, ifStatement.consequent, context);
144
- };
145
- /**
146
- * Validate the `switch` statement
147
- * - Validate recursively if `switch` statements are nested
148
- */
149
- var validateSwitchStatement = function (node, switchStatement, context) {
150
- for (var _i = 0, _a = switchStatement.cases; _i < _a.length; _i++) {
151
- var statement = _a[_i];
152
- for (var _b = 0, _c = statement.consequent; _b < _c.length; _b++) {
153
- var _consequent = _c[_b];
154
- traverseStatements(node, _consequent, context);
155
- }
156
- }
157
- };
158
- /**
159
- * Validate that construct ID does not end with "Construct" or "Stack"
160
- */
161
- var validateConstructId = function (node, context, expression) {
32
+ const validateConstructId = (node, context, expression) => {
162
33
  if (expression.arguments.length < 2)
163
34
  return;
164
- // NOTE: Treat the second argument as ID
165
- var secondArg = expression.arguments[1];
166
- if (secondArg.type !== "Literal" || typeof secondArg.value !== "string") {
35
+ const secondArg = expression.arguments[1];
36
+ if (secondArg.type !== AST_NODE_TYPES.Literal ||
37
+ typeof secondArg.value !== "string") {
167
38
  return;
168
39
  }
169
- var formattedConstructId = toPascalCase(secondArg.value);
40
+ const formattedConstructId = toPascalCase(secondArg.value);
170
41
  if (formattedConstructId.endsWith("Construct")) {
171
42
  context.report({
172
- node: node,
43
+ node,
173
44
  messageId: "noConstructStackSuffix",
174
45
  data: {
175
46
  classType: "Construct",
@@ -180,7 +51,7 @@ var validateConstructId = function (node, context, expression) {
180
51
  }
181
52
  else if (formattedConstructId.endsWith("Stack")) {
182
53
  context.report({
183
- node: node,
54
+ node,
184
55
  messageId: "noConstructStackSuffix",
185
56
  data: {
186
57
  classType: "Stack",
@@ -190,3 +61,4 @@ var validateConstructId = function (node, context, expression) {
190
61
  });
191
62
  }
192
63
  };
64
+ //# sourceMappingURL=no-construct-stack-suffix.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-construct-stack-suffix.mjs","sourceRoot":"","sources":["../src/no-construct-stack-suffix.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;AAU/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACxE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,uEAAuE;SAC1E;QACD,QAAQ,EAAE;YACR,sBAAsB,EACpB,uEAAuE;SAC1E;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;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;AAKH,MAAM,mBAAmB,GAAG,CAC1B,IAAmB,EACnB,OAAgB,EAChB,UAAkC,EAC5B,EAAE;IACR,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,oBAAoB,GAAG,YAAY,CAAC,SAAS,CAAC,KAAe,CAAC,CAAC;IAErE,IAAI,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/C,OAAO,CAAC,MAAM,CAAC;YACb,IAAI;YACJ,SAAS,EAAE,wBAAwB;YACnC,IAAI,EAAE;gBACJ,SAAS,EAAE,WAAW;gBACtB,EAAE,EAAE,SAAS,CAAC,KAAK;gBACnB,MAAM,EAAE,WAAW;aACpB;SACF,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC;YACb,IAAI;YACJ,SAAS,EAAE,wBAAwB;YACnC,IAAI,EAAE;gBACJ,SAAS,EAAE,OAAO;gBAClB,EAAE,EAAE,SAAS,CAAC,KAAK;gBACnB,MAAM,EAAE,OAAO;aAChB;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Rule } from "eslint";
2
+ export declare const noImportPrivate: Rule.RuleModule;
@@ -1,13 +1,5 @@
1
1
  import * as path from "path";
2
- /**
3
- * Split the directory path into segments (split at `/`)
4
- * @param dirPath - The directory path to split
5
- * @returns The segments of the directory path
6
- */
7
- var getDirSegments = function (dirPath) {
8
- return dirPath.split(path.sep).filter(function (segment) { return segment !== ""; });
9
- };
10
- export var noImportPrivate = {
2
+ export const noImportPrivate = {
11
3
  meta: {
12
4
  type: "problem",
13
5
  docs: {
@@ -18,26 +10,28 @@ export var noImportPrivate = {
18
10
  },
19
11
  schema: [],
20
12
  },
21
- create: function (context) {
13
+ create(context) {
22
14
  return {
23
- ImportDeclaration: function (node) {
24
- var _a, _b;
25
- var importPath = (_b = (_a = node.source.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : "";
26
- var currentFilePath = context.filename;
27
- var currentDirPath = path.dirname(currentFilePath);
15
+ ImportDeclaration(node) {
16
+ const importPath = node.source.value?.toString() ?? "";
17
+ const currentFilePath = context.filename;
18
+ const currentDirPath = path.dirname(currentFilePath);
28
19
  if (importPath.includes("/private")) {
29
- var absoluteCurrentDirPath = path.resolve(currentDirPath);
30
- var absoluteImportPath = path.resolve(currentDirPath, importPath);
31
- // NOTE: Get the directory from the import path up to the private directory
32
- var importDirBeforePrivate = absoluteImportPath.split("/private")[0];
33
- var currentDirSegments = getDirSegments(absoluteCurrentDirPath);
34
- var importDirSegments_1 = getDirSegments(importDirBeforePrivate);
35
- if (currentDirSegments.length !== importDirSegments_1.length ||
36
- currentDirSegments.some(function (segment, index) { return segment !== importDirSegments_1[index]; })) {
37
- context.report({ node: node, messageId: "noImportPrivate" });
20
+ const absoluteCurrentDirPath = path.resolve(currentDirPath);
21
+ const absoluteImportPath = path.resolve(currentDirPath, importPath);
22
+ const importDirBeforePrivate = absoluteImportPath.split("/private")[0];
23
+ const currentDirSegments = getDirSegments(absoluteCurrentDirPath);
24
+ const importDirSegments = getDirSegments(importDirBeforePrivate);
25
+ if (currentDirSegments.length !== importDirSegments.length ||
26
+ currentDirSegments.some((segment, index) => segment !== importDirSegments[index])) {
27
+ context.report({ node, messageId: "noImportPrivate" });
38
28
  }
39
29
  }
40
30
  },
41
31
  };
42
32
  },
43
33
  };
34
+ const getDirSegments = (dirPath) => {
35
+ return dirPath.split(path.sep).filter((segment) => segment !== "");
36
+ };
37
+ //# sourceMappingURL=no-import-private.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-import-private.mjs","sourceRoot":"","sources":["../src/no-import-private.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAU7B,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,8EAA8E;SACjF;QACD,QAAQ,EAAE;YACR,eAAe,EACb,8EAA8E;SACjF;QACD,MAAM,EAAE,EAAE;KACX;IACD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAI;gBACpB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACvD,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC;gBACzC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;gBAErD,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBACpC,MAAM,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;oBAC5D,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;oBAGpE,MAAM,sBAAsB,GAC1B,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;oBAE1C,MAAM,kBAAkB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;oBAClE,MAAM,iBAAiB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;oBACjE,IACE,kBAAkB,CAAC,MAAM,KAAK,iBAAiB,CAAC,MAAM;wBACtD,kBAAkB,CAAC,IAAI,CACrB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,iBAAiB,CAAC,KAAK,CAAC,CACzD,EACD,CAAC;wBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;oBACzD,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAOF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAY,EAAE;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noMutablePropsInterface: ESLintUtils.RuleModule<"noMutablePropsInterface", [], unknown, ESLintUtils.RuleListener>;