angular-eslint-zoneless 1.0.2

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 (49) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +13 -0
  3. package/index.d.ts +32 -0
  4. package/index.js +111 -0
  5. package/package.json +34 -0
  6. package/rules/no-content-decorator.d.ts +3 -0
  7. package/rules/no-content-decorator.js +35 -0
  8. package/rules/no-detectchanges-testing.d.ts +3 -0
  9. package/rules/no-detectchanges-testing.js +36 -0
  10. package/rules/no-eager-change-detection.d.ts +3 -0
  11. package/rules/no-eager-change-detection.js +35 -0
  12. package/rules/no-input-decorator.d.ts +3 -0
  13. package/rules/no-input-decorator.js +34 -0
  14. package/rules/no-ngaftercontentchecked.d.ts +3 -0
  15. package/rules/no-ngaftercontentchecked.js +33 -0
  16. package/rules/no-ngaftercontentinit.d.ts +3 -0
  17. package/rules/no-ngaftercontentinit.js +33 -0
  18. package/rules/no-ngafterviewchecked.d.ts +3 -0
  19. package/rules/no-ngafterviewchecked.js +33 -0
  20. package/rules/no-ngafterviewinit.d.ts +3 -0
  21. package/rules/no-ngafterviewinit.js +33 -0
  22. package/rules/no-ngdocheck.d.ts +3 -0
  23. package/rules/no-ngdocheck.js +33 -0
  24. package/rules/no-ngonchanges.d.ts +3 -0
  25. package/rules/no-ngonchanges.js +33 -0
  26. package/rules/no-ngondestroy.d.ts +3 -0
  27. package/rules/no-ngondestroy.js +33 -0
  28. package/rules/no-ngoninit.d.ts +3 -0
  29. package/rules/no-ngoninit.js +33 -0
  30. package/rules/no-ngzone.d.ts +3 -0
  31. package/rules/no-ngzone.js +31 -0
  32. package/rules/no-output-decorator.d.ts +3 -0
  33. package/rules/no-output-decorator.js +34 -0
  34. package/rules/no-providezonechangedetection.d.ts +3 -0
  35. package/rules/no-providezonechangedetection.js +33 -0
  36. package/rules/no-subscribe-in-component-constructor.d.ts +3 -0
  37. package/rules/no-subscribe-in-component-constructor.js +35 -0
  38. package/rules/no-view-decorator.d.ts +3 -0
  39. package/rules/no-view-decorator.js +35 -0
  40. package/rules/no-zonejs-import.d.ts +3 -0
  41. package/rules/no-zonejs-import.js +31 -0
  42. package/rules/no-zonejs-testing-functions.d.ts +3 -0
  43. package/rules/no-zonejs-testing-functions.js +43 -0
  44. package/utils/angular-class-decorator.d.ts +19 -0
  45. package/utils/angular-class-decorator.js +47 -0
  46. package/utils/ast-traversal.d.ts +25 -0
  47. package/utils/ast-traversal.js +36 -0
  48. package/utils/in-constructor.d.ts +2 -0
  49. package/utils/in-constructor.js +23 -0
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2026 Cyrille Tuzi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # angular-eslint-zoneless
2
+
3
+ ESLint rules for Angular zoneless.
4
+
5
+ **Checks that a zoneless application does not use zone.js-based features and that signals/resources patterns are used, for example:**
6
+ - no zone.js import and provider
7
+ - no zone.js testing functions like `fakeAsync()`
8
+ - no `ChangeDectectionStrategy.Eager`
9
+ - no `NgZone`
10
+ - no `@Input()` and other decorators, to enforce `input()` and other signal equivalents
11
+ - no `ngOnInit()` and other component lifecycle methods, to enforce using signals and resources patterns
12
+
13
+ [The documentation is available on GitHub.](https://github.com/cyrilletuzi/angular-eslint-zoneless)
package/index.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { ConfigObject } from "@eslint/core";
2
+ declare const plugin: {
3
+ configs: {
4
+ readonly recommended: ConfigObject<import("@eslint/core").RulesConfig>;
5
+ };
6
+ meta: {
7
+ name: string;
8
+ version: string;
9
+ };
10
+ rules: {
11
+ "no-zonejs-import": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
12
+ "no-providezonechangedetection": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
13
+ "no-eager-change-detection": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
14
+ "no-ngoninit": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
15
+ "no-ngdocheck": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
16
+ "no-ngonchanges": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
17
+ "no-ngaftercontentinit": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
18
+ "no-ngaftercontentchecked": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
19
+ "no-ngafterviewinit": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
20
+ "no-ngafterviewchecked": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
21
+ "no-ngondestroy": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
22
+ "no-input-decorator": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
23
+ "no-output-decorator": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
24
+ "no-content-decorator": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
25
+ "no-view-decorator": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
26
+ "no-ngzone": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
27
+ "no-detectchanges-testing": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
28
+ "no-zonejs-testing-functions": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
29
+ "no-subscribe-in-component-constructor": import("@eslint/core").RuleDefinition<import("@eslint/core").RuleDefinitionTypeOptions>;
30
+ };
31
+ };
32
+ export = plugin;
package/index.js ADDED
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ const noContentDecorator = __importStar(require("./rules/no-content-decorator.js"));
36
+ const noDetectchangesTesting = __importStar(require("./rules/no-detectchanges-testing.js"));
37
+ const noEagerChangeDetection = __importStar(require("./rules/no-eager-change-detection.js"));
38
+ const noInputDecorator = __importStar(require("./rules/no-input-decorator.js"));
39
+ const noNgaftercontentchecked = __importStar(require("./rules/no-ngaftercontentchecked.js"));
40
+ const noNgaftercontentinit = __importStar(require("./rules/no-ngaftercontentinit.js"));
41
+ const noNgafterviewchecked = __importStar(require("./rules/no-ngafterviewchecked.js"));
42
+ const noNgafterviewinit = __importStar(require("./rules/no-ngafterviewinit.js"));
43
+ const noNgdocheck = __importStar(require("./rules/no-ngdocheck.js"));
44
+ const noNgonchanges = __importStar(require("./rules/no-ngonchanges.js"));
45
+ const noNgondestroy = __importStar(require("./rules/no-ngondestroy.js"));
46
+ const noNgoninit = __importStar(require("./rules/no-ngoninit.js"));
47
+ const noNgzone = __importStar(require("./rules/no-ngzone.js"));
48
+ const noOutputDecorator = __importStar(require("./rules/no-output-decorator.js"));
49
+ const noProvidezonechangedetection = __importStar(require("./rules/no-providezonechangedetection.js"));
50
+ const noSubscribeInComponentConstructor = __importStar(require("./rules/no-subscribe-in-component-constructor.js"));
51
+ const noViewDecorator = __importStar(require("./rules/no-view-decorator.js"));
52
+ const noZonejsImport = __importStar(require("./rules/no-zonejs-import.js"));
53
+ const noZonejsTestingFunctions = __importStar(require("./rules/no-zonejs-testing-functions.js"));
54
+ const { name, version } =
55
+ // importing here would bypass the tsconfig `"rootDir": "src"`
56
+ require("./package.json");
57
+ const plugin = {
58
+ configs: {
59
+ get recommended() {
60
+ return recommended;
61
+ }
62
+ },
63
+ meta: { name, version },
64
+ rules: {
65
+ [noZonejsImport.ruleName]: noZonejsImport.ruleDefinition,
66
+ [noProvidezonechangedetection.ruleName]: noProvidezonechangedetection.ruleDefinition,
67
+ [noEagerChangeDetection.ruleName]: noEagerChangeDetection.ruleDefinition,
68
+ [noNgoninit.ruleName]: noNgoninit.ruleDefinition,
69
+ [noNgdocheck.ruleName]: noNgdocheck.ruleDefinition,
70
+ [noNgonchanges.ruleName]: noNgonchanges.ruleDefinition,
71
+ [noNgaftercontentinit.ruleName]: noNgaftercontentinit.ruleDefinition,
72
+ [noNgaftercontentchecked.ruleName]: noNgaftercontentchecked.ruleDefinition,
73
+ [noNgafterviewinit.ruleName]: noNgafterviewinit.ruleDefinition,
74
+ [noNgafterviewchecked.ruleName]: noNgafterviewchecked.ruleDefinition,
75
+ [noNgondestroy.ruleName]: noNgondestroy.ruleDefinition,
76
+ [noInputDecorator.ruleName]: noInputDecorator.ruleDefinition,
77
+ [noOutputDecorator.ruleName]: noOutputDecorator.ruleDefinition,
78
+ [noContentDecorator.ruleName]: noContentDecorator.ruleDefinition,
79
+ [noViewDecorator.ruleName]: noViewDecorator.ruleDefinition,
80
+ [noNgzone.ruleName]: noNgzone.ruleDefinition,
81
+ [noDetectchangesTesting.ruleName]: noDetectchangesTesting.ruleDefinition,
82
+ [noZonejsTestingFunctions.ruleName]: noZonejsTestingFunctions.ruleDefinition,
83
+ [noSubscribeInComponentConstructor.ruleName]: noSubscribeInComponentConstructor.ruleDefinition,
84
+ },
85
+ };
86
+ const recommended = {
87
+ plugins: {
88
+ [name]: plugin
89
+ },
90
+ rules: {
91
+ [`${name}/${noZonejsImport.ruleName}`]: "error",
92
+ [`${name}/${noProvidezonechangedetection.ruleName}`]: "error",
93
+ [`${name}/${noEagerChangeDetection.ruleName}`]: "error",
94
+ [`${name}/${noNgoninit.ruleName}`]: "error",
95
+ [`${name}/${noNgdocheck.ruleName}`]: "error",
96
+ [`${name}/${noNgonchanges.ruleName}`]: "error",
97
+ [`${name}/${noNgaftercontentinit.ruleName}`]: "error",
98
+ [`${name}/${noNgaftercontentchecked.ruleName}`]: "error",
99
+ [`${name}/${noNgafterviewinit.ruleName}`]: "error",
100
+ [`${name}/${noNgafterviewchecked.ruleName}`]: "error",
101
+ [`${name}/${noNgondestroy.ruleName}`]: "error",
102
+ [`${name}/${noInputDecorator.ruleName}`]: "error",
103
+ [`${name}/${noOutputDecorator.ruleName}`]: "error",
104
+ [`${name}/${noContentDecorator.ruleName}`]: "error",
105
+ [`${name}/${noViewDecorator.ruleName}`]: "error",
106
+ [`${name}/${noNgzone.ruleName}`]: "error",
107
+ [`${name}/${noDetectchangesTesting.ruleName}`]: "error",
108
+ [`${name}/${noZonejsTestingFunctions.ruleName}`]: "error",
109
+ },
110
+ };
111
+ module.exports = plugin;
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "angular-eslint-zoneless",
3
+ "version": "1.0.2",
4
+ "description": "Angular zoneless lint rules for ESLint",
5
+ "keywords": [
6
+ "angular",
7
+ "eslint"
8
+ ],
9
+ "funding": {
10
+ "type": "github",
11
+ "url": "https://github.com/sponsors/cyrilletuzi"
12
+ },
13
+ "homepage": "https://github.com/cyrilletuzi/angular-eslint-zoneless#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/cyrilletuzi/angular-eslint-zoneless/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/cyrilletuzi/angular-eslint-zoneless.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Cyrille Tuzi",
23
+ "type": "commonjs",
24
+ "main": "index.js",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./index.d.ts",
28
+ "default": "./index.js"
29
+ }
30
+ },
31
+ "peerDependencies": {
32
+ "@typescript-eslint/utils": "^8.0.0"
33
+ }
34
+ }
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-content-decorator";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-content-decorator";
6
+ const messageId = "noContentDecorator";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ContentChild()\` and \`ContentChildren()\` should not be used in a zoneless application, use \`contentChild()\` and \`contentChildren()\` instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ContentChild()\` and \`ContentChildren()\` are not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_CONTENT_DECORATOR.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ Decorator(node) {
23
+ if (node.expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
24
+ node.expression.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ (node.expression.callee.name === "ContentChild" ||
26
+ node.expression.callee.name === "ContentChildren")) {
27
+ context.report({
28
+ node,
29
+ messageId,
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-detectchanges-testing";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const angular_class_decorator_1 = require("../utils/angular-class-decorator");
6
+ exports.ruleName = "no-detectchanges-testing";
7
+ const messageId = "noDetectchangesTesting";
8
+ exports.ruleDefinition = {
9
+ meta: {
10
+ type: "problem",
11
+ messages: {
12
+ [messageId]: `\`fixture.detectChanges()\` should be avoided in a zoneless application, use \`await fixture.whenStable()\` instead.`,
13
+ },
14
+ docs: {
15
+ description: `Checks that \`fixture.detectChanges()\` is not called.`,
16
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_DETECTCHANGES_TESTING.md',
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ CallExpression(node) {
23
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
24
+ node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ node.callee.property.name === "detectChanges" &&
26
+ // Report only in tests, otherwise it will report on `ChangeDetectorRef.detectChanges()`
27
+ !(0, angular_class_decorator_1.isInAngularClass)(node, ["Component", "Directive"])) {
28
+ context.report({
29
+ node,
30
+ messageId,
31
+ });
32
+ }
33
+ },
34
+ };
35
+ },
36
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-eager-change-detection";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-eager-change-detection";
6
+ const messageId = "noEagerChangeDetection";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ChangeDetectionStrategy.Eager\` and \`ChangeDetectionStrategy.Default\` should not be used in a zoneless application, use \`ChangeDetectionStrategy.OnPush\` instead (the default in Angular >= 22).`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ChangeDetectionStrategy.Eager\` and \`ChangeDetectionStrategy.Default\` are not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_EAGER_CHANGE_DETECTION.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MemberExpression(node) {
23
+ if (node.object.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.object.name === "ChangeDetectionStrategy" &&
25
+ node.property.type === utils_1.AST_NODE_TYPES.Identifier &&
26
+ (node.property.name === "Eager" || node.property.name === "Default")) {
27
+ context.report({
28
+ node,
29
+ messageId,
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-input-decorator";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-input-decorator";
6
+ const messageId = "noInputDecorator";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`Input()\` should not be used in a zoneless application, use \`input()\` instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`Input()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_INPUT_DECORATOR.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ Decorator(node) {
23
+ if (node.expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
24
+ node.expression.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ node.expression.callee.name === "Input") {
26
+ context.report({
27
+ node,
28
+ messageId,
29
+ });
30
+ }
31
+ },
32
+ };
33
+ },
34
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngaftercontentchecked";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngaftercontentchecked";
6
+ const messageId = "noNgaftercontentchecked";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngAfterContentChecked()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngAfterContentChecked()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGAFTERCONTENTCHECKED.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngAfterContentChecked") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngaftercontentinit";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngaftercontentinit";
6
+ const messageId = "noNgaftercontentinit";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngAfterContentInit()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngAfterContentInit()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGAFTERCONTENTINIT.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngAfterContentInit") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngafterviewchecked";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngafterviewchecked";
6
+ const messageId = "noNgafterviewchecked";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngAfterViewChecked()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngAfterViewChecked()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGAFTERVIEWCHECKED.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngAfterViewChecked") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngafterviewinit";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngafterviewinit";
6
+ const messageId = "noNgafterviewinit";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngAfterViewInit()\` should be avoided in a zoneless application, use signals and resources reactivity instead, or when really needed, use \`afterNextRender()\`.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngAfterViewInit()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGAFTERVIEWINIT.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngAfterViewInit") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngdocheck";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngdocheck";
6
+ const messageId = "noNgdocheck";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngDoCheck()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngDoCheck()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGDOCHECK.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngDoCheck") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngonchanges";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngonchanges";
6
+ const messageId = "noNgonchanges";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngOnChanges()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngOnChanges()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGONCHANGES.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngOnChanges") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngondestroy";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngondestroy";
6
+ const messageId = "noNgondestroy";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngOnDestroy()\` should be avoided in a zoneless application, signals and resources destroy is automatic; if really needed, use \`DestroyRef.onDestroy()\`.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngOnDestroy()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGONDESTROY.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngOnDestroy") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngoninit";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-ngoninit";
6
+ const messageId = "noNgoninit";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ngOnInit()\` should be avoided in a zoneless application, use signals and resources reactivity instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ngOnInit()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGONINIT.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ MethodDefinition(node) {
23
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.key.name === "ngOnInit") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-ngzone";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ exports.ruleName = "no-ngzone";
5
+ const messageId = "noNgzone";
6
+ exports.ruleDefinition = {
7
+ meta: {
8
+ type: "problem",
9
+ messages: {
10
+ [messageId]: `\`NgZone()\` is useless and does not work in a zoneless application.`,
11
+ },
12
+ docs: {
13
+ description: `Checks that \`NgZone()\` is not used.`,
14
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_NGZONE.md',
15
+ recommended: true,
16
+ },
17
+ schema: [],
18
+ },
19
+ create(context) {
20
+ return {
21
+ Identifier(node) {
22
+ if (node.name === 'NgZone') {
23
+ context.report({
24
+ node,
25
+ messageId,
26
+ });
27
+ }
28
+ },
29
+ };
30
+ },
31
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-output-decorator";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-output-decorator";
6
+ const messageId = "noOutputDecorator";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`Output()\` should not be used in a zoneless application, use \`output()\` instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`Output()\` is not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_OUTPUT_DECORATOR.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ Decorator(node) {
23
+ if (node.expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
24
+ node.expression.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ node.expression.callee.name === "Output") {
26
+ context.report({
27
+ node,
28
+ messageId,
29
+ });
30
+ }
31
+ },
32
+ };
33
+ },
34
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-providezonechangedetection";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-providezonechangedetection";
6
+ const messageId = "noProvidezonechangedetection";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`provideZoneChangeDetection()\` is forbidden in a zoneless application.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`provideZoneChangeDetection()\` is not called.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_PROVIDEZONECHANGEDETECTION.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ CallExpression(node) {
23
+ if (node.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
24
+ node.callee.name === "provideZoneChangeDetection") {
25
+ context.report({
26
+ node,
27
+ messageId,
28
+ });
29
+ }
30
+ },
31
+ };
32
+ },
33
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-subscribe-in-component-constructor";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const in_constructor_1 = require("../utils/in-constructor");
6
+ exports.ruleName = "no-subscribe-in-component-constructor";
7
+ const messageId = "noSubscribeInComponentConstructor";
8
+ exports.ruleDefinition = {
9
+ meta: {
10
+ type: "problem",
11
+ messages: {
12
+ [messageId]: `An observable inside a component constructor can generally be managed with \`toSignal()\` or \`rxResource()\` instead.`,
13
+ },
14
+ docs: {
15
+ description: `Checks that observables are not explicitly subscribed in components constructors.`,
16
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_SUBSCRIBE_IN_COMPONENT_CONSTRUCTOR.md',
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ CallExpression(node) {
23
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
24
+ node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ node.callee.property.name === 'subscribe' &&
26
+ (0, in_constructor_1.isInAngularComponentConstructor)(node)) {
27
+ context.report({
28
+ node,
29
+ messageId,
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-view-decorator";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-view-decorator";
6
+ const messageId = "noViewDecorator";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `\`ViewChild()\` and \`ViewChildren()\` should not be used in a zoneless application, use \`viewChild()\` and \`viewChildren()\` instead.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that \`ViewChild()\` and \`ViewChildren()\` are not used.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_VIEW_DECORATOR.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ Decorator(node) {
23
+ if (node.expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
24
+ node.expression.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
25
+ (node.expression.callee.name === "ViewChild" ||
26
+ node.expression.callee.name === "ViewChildren")) {
27
+ context.report({
28
+ node,
29
+ messageId,
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-zonejs-import";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ exports.ruleName = "no-zonejs-import";
5
+ const messageId = "noZonejsImport";
6
+ exports.ruleDefinition = {
7
+ meta: {
8
+ type: "problem",
9
+ messages: {
10
+ [messageId]: `Importing zone.js is forbidden in a zoneless application.`,
11
+ },
12
+ docs: {
13
+ description: `Checks that \`zone.js\` is not imported.`,
14
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_ZONEJS_IMPORT.md',
15
+ recommended: true,
16
+ },
17
+ schema: [],
18
+ },
19
+ create(context) {
20
+ return {
21
+ ImportDeclaration(node) {
22
+ if (node.source.value === "zone.js") {
23
+ context.report({
24
+ node,
25
+ messageId,
26
+ });
27
+ }
28
+ },
29
+ };
30
+ },
31
+ };
@@ -0,0 +1,3 @@
1
+ import type { RuleDefinition } from "@eslint/core";
2
+ export declare const ruleName = "no-zonejs-testing-functions";
3
+ export declare const ruleDefinition: RuleDefinition;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleDefinition = exports.ruleName = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ exports.ruleName = "no-zonejs-testing-functions";
6
+ const messageId = "noZonejsTestingFunctions";
7
+ exports.ruleDefinition = {
8
+ meta: {
9
+ type: "problem",
10
+ messages: {
11
+ [messageId]: `zone.js testing functions (\`fakeAsync()\`, \`discardPeriodicTasks()\`, \`flush()\`, \`flushMicrotasks()\`, \`resetFakeAsyncZone()\`, \`tick()\`, \`waitForAsync()\`) are useless and do not work in a zoneless application.`,
12
+ },
13
+ docs: {
14
+ description: `Checks that zone.js testing functions are not called.`,
15
+ url: 'https://github.com/cyrilletuzi/angular-eslint-zoneless/blob/main/docs/rules/NO_ZONEJS_TESTING_FUNCTIONS.md',
16
+ recommended: true,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ CallExpression(node) {
23
+ if (node.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
24
+ const testingFunctions = new Set([
25
+ "fakeAsync",
26
+ "discardPeriodicTasks",
27
+ "flush",
28
+ "flushMicrotasks",
29
+ "resetFakeAsyncZone",
30
+ "tick",
31
+ "waitForAsync",
32
+ ]);
33
+ if (testingFunctions.has(node.callee.name)) {
34
+ context.report({
35
+ node,
36
+ messageId,
37
+ });
38
+ }
39
+ }
40
+ },
41
+ };
42
+ },
43
+ };
@@ -0,0 +1,19 @@
1
+ import { type TSESTree } from "@typescript-eslint/utils";
2
+ export type AngularClassDecorator = "Component" | "Directive" | "Injectable" | "NgModule" | "Pipe" | "Service";
3
+ /**
4
+ * Checks if a `ClassDeclaration` has an Angular decorator and returns it.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const classDeclaration = findNearestAncestorOf(
9
+ * node,
10
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
11
+ * );
12
+ *
13
+ * if (classDeclaration && findAngularClassDecorator(classDeclaration)) {
14
+ * return true;
15
+ * }
16
+ * ```
17
+ */
18
+ export declare function findAngularClassDecorator({ decorators }: TSESTree.ClassDeclaration, allowedDecorators?: readonly AngularClassDecorator[]): AngularClassDecorator | undefined;
19
+ export declare function isInAngularClass(node: TSESTree.Node, allowedDecorators?: readonly AngularClassDecorator[]): boolean;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findAngularClassDecorator = findAngularClassDecorator;
4
+ exports.isInAngularClass = isInAngularClass;
5
+ const utils_1 = require("@typescript-eslint/utils");
6
+ const ast_traversal_1 = require("./ast-traversal");
7
+ /**
8
+ * Checks if a `ClassDeclaration` has an Angular decorator and returns it.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const classDeclaration = findNearestAncestorOf(
13
+ * node,
14
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
15
+ * );
16
+ *
17
+ * if (classDeclaration && findAngularClassDecorator(classDeclaration)) {
18
+ * return true;
19
+ * }
20
+ * ```
21
+ */
22
+ function findAngularClassDecorator({ decorators }, allowedDecorators = [
23
+ "Component", "Directive", "Injectable", "NgModule", "Pipe", "Service",
24
+ ]) {
25
+ const angularClassDecorators = new Set(allowedDecorators);
26
+ return decorators
27
+ ?.map(({ expression }) => {
28
+ if (utils_1.ASTUtils.isIdentifier(expression)) {
29
+ return expression.name;
30
+ }
31
+ return expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
32
+ utils_1.ASTUtils.isIdentifier(expression.callee)
33
+ ? expression.callee.name
34
+ : undefined;
35
+ })
36
+ .filter((item) => item !== undefined)
37
+ .find((value) => angularClassDecorators.has(value));
38
+ }
39
+ ;
40
+ function isInAngularClass(node, allowedDecorators) {
41
+ const classDeclaration = (0, ast_traversal_1.findNearestAncestorOf)(node, (node) => node.type === utils_1.AST_NODE_TYPES.ClassDeclaration);
42
+ if (classDeclaration &&
43
+ findAngularClassDecorator(classDeclaration, allowedDecorators)) {
44
+ return true;
45
+ }
46
+ return false;
47
+ }
@@ -0,0 +1,25 @@
1
+ import { type TSESTree } from "@typescript-eslint/utils";
2
+ /**
3
+ * Get the nearest ancestor node of a certain type.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const classDeclaration = getNearestNodeFrom(
8
+ * node,
9
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
10
+ * );
11
+ * ```
12
+ *
13
+ * With `notInCallback` option enabled, the traversal will stop if it encounters a `CallExpression`.
14
+ * This is needed for some rules because the injection context is lost when inside a callback.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const classDeclaration = getNearestNodeFrom(
19
+ * node,
20
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
21
+ * { notInCallback: true },
22
+ * );
23
+ * ```
24
+ */
25
+ export declare function findNearestAncestorOf<T extends TSESTree.Node>({ parent }: TSESTree.Node, predicate: (parent: TSESTree.Node) => parent is T): T | undefined;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findNearestAncestorOf = findNearestAncestorOf;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ /**
6
+ * Get the nearest ancestor node of a certain type.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const classDeclaration = getNearestNodeFrom(
11
+ * node,
12
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
13
+ * );
14
+ * ```
15
+ *
16
+ * With `notInCallback` option enabled, the traversal will stop if it encounters a `CallExpression`.
17
+ * This is needed for some rules because the injection context is lost when inside a callback.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const classDeclaration = getNearestNodeFrom(
22
+ * node,
23
+ * (node) => node.type === AST_NODE_TYPES.ClassDeclaration,
24
+ * { notInCallback: true },
25
+ * );
26
+ * ```
27
+ */
28
+ function findNearestAncestorOf({ parent }, predicate) {
29
+ while (parent && parent.type !== utils_1.AST_NODE_TYPES.Program) {
30
+ if (predicate(parent)) {
31
+ return parent;
32
+ }
33
+ parent = parent.parent;
34
+ }
35
+ return undefined;
36
+ }
@@ -0,0 +1,2 @@
1
+ import { type TSESTree } from "@typescript-eslint/utils";
2
+ export declare function isInAngularComponentConstructor(node: TSESTree.Node): boolean;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isInAngularComponentConstructor = isInAngularComponentConstructor;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const angular_class_decorator_1 = require("./angular-class-decorator");
6
+ const ast_traversal_1 = require("./ast-traversal");
7
+ function isInConstructor(node) {
8
+ const methodDefinition = (0, ast_traversal_1.findNearestAncestorOf)(node, (node) => node.type === utils_1.AST_NODE_TYPES.MethodDefinition);
9
+ if (methodDefinition?.kind === "constructor") {
10
+ return true;
11
+ }
12
+ return false;
13
+ }
14
+ function isInAngularComponentConstructor(node) {
15
+ if (isInConstructor(node)) {
16
+ const classDeclaration = (0, ast_traversal_1.findNearestAncestorOf)(node, (node) => node.type === utils_1.AST_NODE_TYPES.ClassDeclaration);
17
+ if (classDeclaration &&
18
+ (0, angular_class_decorator_1.findAngularClassDecorator)(classDeclaration, ["Component"])) {
19
+ return true;
20
+ }
21
+ }
22
+ return false;
23
+ }