@simplysm/lint 14.0.48 → 14.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @simplysm/lint
2
2
 
3
- Simplysm 모노레포 전용 ESLint 플러그인 및 공유 Flat Config 설정. 커스텀 규칙 8개와 권장 설정을 제공한다.
3
+ Simplysm 모노레포 전용 ESLint 플러그인 및 공유 Flat Config 설정. 커스텀 규칙 9개와 권장 설정을 제공한다.
4
4
 
5
5
  ## Installation
6
6
 
@@ -14,7 +14,7 @@ npm install @simplysm/lint
14
14
 
15
15
  | API | Type | Description |
16
16
  |-----|------|-------------|
17
- | `default` | object | `{ rules: {...} }` 형태의 ESLint 플러그인 객체. 8개의 커스텀 규칙을 포함한다 |
17
+ | `default` | object | `{ rules: {...} }` 형태의 ESLint 플러그인 객체. 9개의 커스텀 규칙을 포함한다 |
18
18
 
19
19
  #### Rules
20
20
 
@@ -25,6 +25,7 @@ npm install @simplysm/lint
25
25
  | `ts-no-throw-not-implemented-error` | suggestion | - | `@simplysm/core-common`의 `NotImplementedError` 사용을 경고한다. named import, aliased import, namespace import 모두 감지. 동적 import는 미감지 |
26
26
  | `ts-no-unused-injects` | problem | autofix | 미사용 Angular `inject()` 필드를 감지하여 제거한다. 클래스 내 `inject()` 호출로 초기화된 프로퍼티 중 다른 곳에서 참조되지 않는 필드를 보고 |
27
27
  | `ts-no-unused-protected-readonly` | problem | autofix | Angular `@Component` 클래스의 미사용 `protected readonly` 필드를 감지하여 제거한다. 인라인 템플릿과 클래스 본문 모두에서 참조 여부를 확인 |
28
+ | `ng-no-async-effect` | problem | - | `@angular/core`의 `effect()`에 async 함수를 직접 전달하는 것을 금지한다. `await` 이후의 signal read가 의존성으로 추적되지 않는 함정을 방지. named/aliased/namespace import 모두 감지. 비동기 작업은 `void untracked(async () => { ... })` 내부에서 수행하도록 유도 |
28
29
  | `ng-template-no-todo-comments` | problem | - | HTML 템플릿 내 `<!-- TODO: ... -->` 주석을 경고한다. raw text regex 방식으로 동작 |
29
30
  | `ng-template-no-strict-null-check` | problem | - | Angular 템플릿에서 `=== null`, `!== null`, `=== undefined`, `!== undefined` 사용을 금지한다. `== null` / `!= null`로 통일하도록 강제. autofix 미제공(인라인 템플릿 offset 매핑 문제) |
30
31
  | `ng-template-sd-require-binding-attrs` | problem | autofix | `sd-*` 컴포넌트에서 허용 목록 외 plain attribute 사용을 금지하고 Angular property binding(`[attr]="..."`)을 강제한다 |
@@ -61,7 +62,7 @@ npm install @simplysm/lint
61
62
  |----------|-------------|
62
63
  | `commonRules` | `eqeqeq` (`null` 비교만 `==` 허용), `no-warning-comments`, `no-self-compare`, `array-callback-return` |
63
64
  | `noNodeBuiltinsRules` | `Buffer` 전역 사용 금지, `buffer`/`events`/`eventemitter3` import 금지 |
64
- | `noDirectEnvAccessRules` | `process.env` 및 `import.meta.env` 직접 접근 금지 (`env("...")` 사용 강제), `NODE_ENV` 환경변수 사용 금지 |
65
+ | `noDirectEnvAccessRules` | `process.env` 및 `import.meta.env` 직접 접근 금지 (`env("...")` 사용 강제), `NODE_ENV` 환경변수 사용 금지, `=== undefined` / `!== undefined` 비교 금지 (`== null` / `!= null` 사용 강제) |
65
66
  | `unusedImportsRules` | 미사용 import 자동 제거 (`_` 접두사 변수 무시) |
66
67
 
67
68
  #### Ignores
@@ -1,5 +1,8 @@
1
1
  declare const _default: {
2
2
  rules: {
3
+ "ng-no-async-effect": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAsyncEffect", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
4
+ name: string;
5
+ };
3
6
  "ng-template-no-strict-null-check": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noStrictNullCheck", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
4
7
  name: string;
5
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-plugin.d.ts","sourceRoot":"","sources":["../src/eslint-plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,wBAWE"}
1
+ {"version":3,"file":"eslint-plugin.d.ts","sourceRoot":"","sources":["../src/eslint-plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,wBAYE"}
@@ -1,3 +1,4 @@
1
+ import ngNoAsyncEffect from "./rules/ng-no-async-effect.js";
1
2
  import ngTemplateNoStrictNullCheck from "./rules/ng-template-no-strict-null-check.js";
2
3
  import ngTemplateNoTodoComments from "./rules/ng-template-no-todo-comments.js";
3
4
  import ngTemplateSdRequireBindingAttrs from "./rules/ng-template-sd-require-binding-attrs.js";
@@ -8,6 +9,7 @@ import tsNoUnusedInjects from "./rules/ts-no-unused-injects.js";
8
9
  import tsNoUnusedProtectedReadonly from "./rules/ts-no-unused-protected-readonly.js";
9
10
  export default {
10
11
  rules: {
12
+ "ng-no-async-effect": ngNoAsyncEffect,
11
13
  "ng-template-no-strict-null-check": ngTemplateNoStrictNullCheck,
12
14
  "ng-template-no-todo-comments": ngTemplateNoTodoComments,
13
15
  "ng-template-sd-require-binding-attrs": ngTemplateSdRequireBindingAttrs,
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-plugin.js","sourceRoot":"","sources":["../src/eslint-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,MAAM,0CAA0C,CAAC;AACnF,OAAO,wBAAwB,MAAM,sCAAsC,CAAC;AAC5E,OAAO,+BAA+B,MAAM,8CAA8C,CAAC;AAC3F,OAAO,aAAa,MAAM,yBAAyB,CAAC;AACpD,OAAO,4BAA4B,MAAM,0CAA0C,CAAC;AACpF,OAAO,4BAA4B,MAAM,2CAA2C,CAAC;AACrF,OAAO,iBAAiB,MAAM,8BAA8B,CAAC;AAC7D,OAAO,2BAA2B,MAAM,yCAAyC,CAAC;AAElF,eAAe;IACb,KAAK,EAAE;QACL,kCAAkC,EAAE,2BAA2B;QAC/D,8BAA8B,EAAE,wBAAwB;QACxD,sCAAsC,EAAE,+BAA+B;QACvE,iBAAiB,EAAE,aAAa;QAChC,kCAAkC,EAAE,4BAA4B;QAChE,mCAAmC,EAAE,4BAA4B;QACjE,sBAAsB,EAAE,iBAAiB;QACzC,iCAAiC,EAAE,2BAA2B;KAC/D;CACF,CAAC"}
1
+ {"version":3,"file":"eslint-plugin.js","sourceRoot":"","sources":["../src/eslint-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AACzD,OAAO,2BAA2B,MAAM,0CAA0C,CAAC;AACnF,OAAO,wBAAwB,MAAM,sCAAsC,CAAC;AAC5E,OAAO,+BAA+B,MAAM,8CAA8C,CAAC;AAC3F,OAAO,aAAa,MAAM,yBAAyB,CAAC;AACpD,OAAO,4BAA4B,MAAM,0CAA0C,CAAC;AACpF,OAAO,4BAA4B,MAAM,2CAA2C,CAAC;AACrF,OAAO,iBAAiB,MAAM,8BAA8B,CAAC;AAC7D,OAAO,2BAA2B,MAAM,yCAAyC,CAAC;AAElF,eAAe;IACb,KAAK,EAAE;QACL,oBAAoB,EAAE,eAAe;QACrC,kCAAkC,EAAE,2BAA2B;QAC/D,8BAA8B,EAAE,wBAAwB;QACxD,sCAAsC,EAAE,+BAA+B;QACvE,iBAAiB,EAAE,aAAa;QAChC,kCAAkC,EAAE,4BAA4B;QAChE,mCAAmC,EAAE,4BAA4B;QACjE,sBAAsB,EAAE,iBAAiB;QACzC,iCAAiC,EAAE,2BAA2B;KAC/D;CACF,CAAC"}
@@ -95,7 +95,6 @@ export default tseslint.config({
95
95
  "**/node_modules/**",
96
96
  "**/dist/**",
97
97
  "**/.*/**",
98
- "**/_*/**",
99
98
  ],
100
99
  }, {
101
100
  languageOptions: {
@@ -206,6 +205,7 @@ export default tseslint.config({
206
205
  ],
207
206
  "@typescript-eslint/only-throw-error": "error",
208
207
  "@typescript-eslint/no-array-delete": "error",
208
+ "@simplysm/ng-no-async-effect": "error",
209
209
  "@simplysm/no-hard-private": "error",
210
210
  "@simplysm/no-subpath-imports-from-simplysm": "error",
211
211
  "@simplysm/ts-no-throw-not-implemented-error": "warn",
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-recommended.js","sourceRoot":"","sources":["../src/eslint-recommended.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eslint-recommended.js","sourceRoot":"","sources":["../src/eslint-recommended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `@angular/core`의 `effect()`에 async 함수를 직접 전달하는 것을 금지하는 ESLint 규칙.
3
+ *
4
+ * @remarks
5
+ * `effect(async () => { ... })`처럼 effect 콜백을 async로 선언하면, `await` 이후에 읽은 signal은
6
+ * 반응형(reactive) 컨텍스트를 벗어나 의존성으로 추적되지 않는다. 또한 콜백의 반환값이 `Promise<void>`가
7
+ * 되어 `EffectCleanupFn` 등록 기능도 사용할 수 없다.
8
+ *
9
+ * 비동기 작업이 필요한 경우 다음 패턴을 사용한다.
10
+ *
11
+ * ```typescript
12
+ * effect(() => {
13
+ * this.someSignal();
14
+ * void untracked(async () => {
15
+ * await this.doAsync();
16
+ * });
17
+ * });
18
+ * ```
19
+ *
20
+ * 지원하는 import 형태:
21
+ * - named import: `import { effect } from "@angular/core"`
22
+ * - aliased import: `import { effect as ngEffect } from "@angular/core"`
23
+ * - namespace import: `import * as ng from "@angular/core"` → `ng.effect(...)`
24
+ *
25
+ * 다른 모듈에서 import한 `effect` 또는 로컬에 선언된 `effect`는 감지하지 않는다.
26
+ */
27
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAsyncEffect", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
28
+ name: string;
29
+ };
30
+ export default _default;
31
+ //# sourceMappingURL=ng-no-async-effect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-no-async-effect.d.ts","sourceRoot":"","sources":["../../src/rules/ng-no-async-effect.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;;AACH,wBAgGG"}
@@ -0,0 +1,110 @@
1
+ import { AST_NODE_TYPES, ASTUtils } from "@typescript-eslint/utils";
2
+ import { createRule } from "../utils/create-rule.js";
3
+ /**
4
+ * `@angular/core`의 `effect()`에 async 함수를 직접 전달하는 것을 금지하는 ESLint 규칙.
5
+ *
6
+ * @remarks
7
+ * `effect(async () => { ... })`처럼 effect 콜백을 async로 선언하면, `await` 이후에 읽은 signal은
8
+ * 반응형(reactive) 컨텍스트를 벗어나 의존성으로 추적되지 않는다. 또한 콜백의 반환값이 `Promise<void>`가
9
+ * 되어 `EffectCleanupFn` 등록 기능도 사용할 수 없다.
10
+ *
11
+ * 비동기 작업이 필요한 경우 다음 패턴을 사용한다.
12
+ *
13
+ * ```typescript
14
+ * effect(() => {
15
+ * this.someSignal();
16
+ * void untracked(async () => {
17
+ * await this.doAsync();
18
+ * });
19
+ * });
20
+ * ```
21
+ *
22
+ * 지원하는 import 형태:
23
+ * - named import: `import { effect } from "@angular/core"`
24
+ * - aliased import: `import { effect as ngEffect } from "@angular/core"`
25
+ * - namespace import: `import * as ng from "@angular/core"` → `ng.effect(...)`
26
+ *
27
+ * 다른 모듈에서 import한 `effect` 또는 로컬에 선언된 `effect`는 감지하지 않는다.
28
+ */
29
+ export default createRule({
30
+ name: "ng-no-async-effect",
31
+ meta: {
32
+ type: "problem",
33
+ docs: {
34
+ description: "Angular effect()에 async 함수를 직접 전달하지 못하도록 합니다",
35
+ },
36
+ schema: [],
37
+ messages: {
38
+ noAsyncEffect: "effect()에 async 함수를 직접 전달하지 마세요. " +
39
+ "await 이후의 signal read는 의존성으로 추적되지 않습니다. " +
40
+ "비동기 작업은 `void untracked(async () => { ... })` 내부에서 수행하세요.",
41
+ },
42
+ },
43
+ defaultOptions: [],
44
+ create(context) {
45
+ /**
46
+ * 식별자가 @angular/core에서 import되었는지 확인한다.
47
+ * @param identifier - 확인할 식별자
48
+ * @param expectedImportedName - named import에서 확인할 원래 이름 (namespace import의 경우 undefined)
49
+ */
50
+ function isImportedFromAngularCore(identifier, expectedImportedName) {
51
+ const scope = context.sourceCode.getScope(identifier);
52
+ const variable = ASTUtils.findVariable(scope, identifier.name);
53
+ if (!variable)
54
+ return false;
55
+ for (const def of variable.defs) {
56
+ if (def.type !== "ImportBinding")
57
+ continue;
58
+ if (def.parent.type !== AST_NODE_TYPES.ImportDeclaration)
59
+ continue;
60
+ if (def.parent.source.value !== "@angular/core")
61
+ continue;
62
+ // named/aliased import: import { effect } 또는 import { effect as ngEffect }
63
+ if (def.node.type === AST_NODE_TYPES.ImportSpecifier && expectedImportedName != null) {
64
+ const imported = def.node.imported;
65
+ if (imported.type === AST_NODE_TYPES.Identifier &&
66
+ imported.name === expectedImportedName) {
67
+ return true;
68
+ }
69
+ }
70
+ // namespace import: import * as ng
71
+ if (def.node.type === AST_NODE_TYPES.ImportNamespaceSpecifier &&
72
+ expectedImportedName == null) {
73
+ return true;
74
+ }
75
+ }
76
+ return false;
77
+ }
78
+ return {
79
+ CallExpression(node) {
80
+ let isAngularEffect = false;
81
+ // 케이스 1: effect(...) 또는 aliased된 effect (named import)
82
+ if (node.callee.type === AST_NODE_TYPES.Identifier) {
83
+ isAngularEffect = isImportedFromAngularCore(node.callee, "effect");
84
+ }
85
+ // 케이스 2: ng.effect(...) (namespace import)
86
+ else if (node.callee.type === AST_NODE_TYPES.MemberExpression &&
87
+ node.callee.property.type === AST_NODE_TYPES.Identifier &&
88
+ node.callee.property.name === "effect" &&
89
+ node.callee.object.type === AST_NODE_TYPES.Identifier) {
90
+ isAngularEffect = isImportedFromAngularCore(node.callee.object, undefined);
91
+ }
92
+ if (!isAngularEffect)
93
+ return;
94
+ const firstArg = node.arguments.at(0);
95
+ if (firstArg == null)
96
+ return;
97
+ const isAsyncFunction = (firstArg.type === AST_NODE_TYPES.ArrowFunctionExpression ||
98
+ firstArg.type === AST_NODE_TYPES.FunctionExpression) &&
99
+ firstArg.async;
100
+ if (!isAsyncFunction)
101
+ return;
102
+ context.report({
103
+ node: firstArg,
104
+ messageId: "noAsyncEffect",
105
+ });
106
+ },
107
+ };
108
+ },
109
+ });
110
+ //# sourceMappingURL=ng-no-async-effect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-no-async-effect.js","sourceRoot":"","sources":["../../src/rules/ng-no-async-effect.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ng-template-no-strict-null-check.js","sourceRoot":"","sources":["../../src/rules/ng-template-no-strict-null-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD;;;;;;GAMG;AACH,eAAe,UAAU,CAAC;IACxB,IAAI,EAAE,kCAAkC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,8GAA8G;SACjH;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,iBAAiB,EACf,mDAAmD;SACtD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,yBAAyB,CAAC,OAAgB,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAEtC,OAAO;YACL,iCAAiC,CAC/B,IAKC;gBAED,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;gBACxC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACrC,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;oBAAE,OAAO;gBAEtC,MAAM,OAAO,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAClD,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;gBACzC,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;gBAE3C,MAAM,UAAU,GAAG,GAAG,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,SAAS,IAAI,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;gBAC5G,MAAM,eAAe,GAAG,GAAG,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,OAAO,OAAO,CAAC;gBAEhF,MAAM,GAAG,GAAG,cAAc,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAmB,CAAC,CAAC;gBAEhF,OAAO,CAAC,MAAM,CAAC;oBACb,GAAG;oBACH,SAAS,EAAE,mBAAmB;oBAC9B,IAAI,EAAE;wBACJ,MAAM,EAAE,UAAU;wBAClB,WAAW,EAAE,eAAe;qBAC7B;iBACF,CAAC,CAAC;YACL,CAAC;SACO,CAAC;IACb,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,IAAyB;IAC3C,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAClB,IAA8C,EAC9C,UAAiC;IAEjC,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"ng-template-no-strict-null-check.js","sourceRoot":"","sources":["../../src/rules/ng-template-no-strict-null-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD;;;;;;GAMG;AACH,eAAe,UAAU,CAAC;IACxB,IAAI,EAAE,kCAAkC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,8GAA8G;SACjH;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,iBAAiB,EACf,mDAAmD;SACtD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAEtC,OAAO;YACL,iCAAiC,CAC/B,IAKC;gBAED,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;gBACxC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACrC,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;oBAAE,OAAO;gBAEtC,MAAM,OAAO,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAClD,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;gBACzC,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;gBAE3C,MAAM,UAAU,GAAG,GAAG,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,SAAS,IAAI,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;gBAC5G,MAAM,eAAe,GAAG,GAAG,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,OAAO,OAAO,CAAC;gBAEhF,MAAM,GAAG,GAAG,cAAc,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAmB,CAAC,CAAC;gBAEhF,OAAO,CAAC,MAAM,CAAC;oBACb,GAAG;oBACH,SAAS,EAAE,mBAAmB;oBAC9B,IAAI,EAAE;wBACJ,MAAM,EAAE,UAAU;wBAClB,WAAW,EAAE,eAAe;qBAC7B;iBACF,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,IAAyB;IAC3C,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAClB,IAA8C,EAC9C,UAAiC;IAEjC,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ng-template-sd-require-binding-attrs.js","sourceRoot":"","sources":["../../src/rules/ng-template-sd-require-binding-attrs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-template-sd-require-binding-attrs.js","sourceRoot":"","sources":["../../src/rules/ng-template-sd-require-binding-attrs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/lint",
3
- "version": "14.0.48",
3
+ "version": "14.0.50",
4
4
  "description": "심플리즘 패키지 - ESLint plugin",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -28,7 +28,7 @@
28
28
  "dependencies": {
29
29
  "@angular-eslint/utils": "^21.3.1",
30
30
  "@angular/compiler": "^21.2.9",
31
- "@typescript-eslint/utils": "^8.58.2",
31
+ "@typescript-eslint/utils": "^8.59.0",
32
32
  "angular-eslint": "^21.3.1",
33
33
  "eslint": "^9.39.4",
34
34
  "eslint-import-resolver-typescript": "^4.4.4",
@@ -36,10 +36,10 @@
36
36
  "eslint-plugin-unused-imports": "^4.4.1",
37
37
  "globals": "^17.5.0",
38
38
  "typescript": "^5.9.3",
39
- "typescript-eslint": "^8.58.2"
39
+ "typescript-eslint": "^8.59.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20.19.39",
43
- "@typescript-eslint/rule-tester": "^8.58.2"
43
+ "@typescript-eslint/rule-tester": "^8.59.0"
44
44
  }
45
45
  }
@@ -1,3 +1,4 @@
1
+ import ngNoAsyncEffect from "./rules/ng-no-async-effect";
1
2
  import ngTemplateNoStrictNullCheck from "./rules/ng-template-no-strict-null-check";
2
3
  import ngTemplateNoTodoComments from "./rules/ng-template-no-todo-comments";
3
4
  import ngTemplateSdRequireBindingAttrs from "./rules/ng-template-sd-require-binding-attrs";
@@ -9,6 +10,7 @@ import tsNoUnusedProtectedReadonly from "./rules/ts-no-unused-protected-readonly
9
10
 
10
11
  export default {
11
12
  rules: {
13
+ "ng-no-async-effect": ngNoAsyncEffect,
12
14
  "ng-template-no-strict-null-check": ngTemplateNoStrictNullCheck,
13
15
  "ng-template-no-todo-comments": ngTemplateNoTodoComments,
14
16
  "ng-template-sd-require-binding-attrs": ngTemplateSdRequireBindingAttrs,
@@ -103,7 +103,6 @@ export default tseslint.config(
103
103
  "**/node_modules/**",
104
104
  "**/dist/**",
105
105
  "**/.*/**",
106
- "**/_*/**",
107
106
  ],
108
107
  },
109
108
  {
@@ -226,6 +225,7 @@ export default tseslint.config(
226
225
  "@typescript-eslint/only-throw-error": "error",
227
226
  "@typescript-eslint/no-array-delete": "error",
228
227
 
228
+ "@simplysm/ng-no-async-effect": "error",
229
229
  "@simplysm/no-hard-private": "error",
230
230
  "@simplysm/no-subpath-imports-from-simplysm": "error",
231
231
  "@simplysm/ts-no-throw-not-implemented-error": "warn",
@@ -0,0 +1,126 @@
1
+ import { AST_NODE_TYPES, ASTUtils, type TSESTree } from "@typescript-eslint/utils";
2
+ import { createRule } from "../utils/create-rule";
3
+
4
+ /**
5
+ * `@angular/core`의 `effect()`에 async 함수를 직접 전달하는 것을 금지하는 ESLint 규칙.
6
+ *
7
+ * @remarks
8
+ * `effect(async () => { ... })`처럼 effect 콜백을 async로 선언하면, `await` 이후에 읽은 signal은
9
+ * 반응형(reactive) 컨텍스트를 벗어나 의존성으로 추적되지 않는다. 또한 콜백의 반환값이 `Promise<void>`가
10
+ * 되어 `EffectCleanupFn` 등록 기능도 사용할 수 없다.
11
+ *
12
+ * 비동기 작업이 필요한 경우 다음 패턴을 사용한다.
13
+ *
14
+ * ```typescript
15
+ * effect(() => {
16
+ * this.someSignal();
17
+ * void untracked(async () => {
18
+ * await this.doAsync();
19
+ * });
20
+ * });
21
+ * ```
22
+ *
23
+ * 지원하는 import 형태:
24
+ * - named import: `import { effect } from "@angular/core"`
25
+ * - aliased import: `import { effect as ngEffect } from "@angular/core"`
26
+ * - namespace import: `import * as ng from "@angular/core"` → `ng.effect(...)`
27
+ *
28
+ * 다른 모듈에서 import한 `effect` 또는 로컬에 선언된 `effect`는 감지하지 않는다.
29
+ */
30
+ export default createRule({
31
+ name: "ng-no-async-effect",
32
+ meta: {
33
+ type: "problem",
34
+ docs: {
35
+ description: "Angular effect()에 async 함수를 직접 전달하지 못하도록 합니다",
36
+ },
37
+ schema: [],
38
+ messages: {
39
+ noAsyncEffect:
40
+ "effect()에 async 함수를 직접 전달하지 마세요. " +
41
+ "await 이후의 signal read는 의존성으로 추적되지 않습니다. " +
42
+ "비동기 작업은 `void untracked(async () => { ... })` 내부에서 수행하세요.",
43
+ },
44
+ },
45
+ defaultOptions: [],
46
+ create(context) {
47
+ /**
48
+ * 식별자가 @angular/core에서 import되었는지 확인한다.
49
+ * @param identifier - 확인할 식별자
50
+ * @param expectedImportedName - named import에서 확인할 원래 이름 (namespace import의 경우 undefined)
51
+ */
52
+ function isImportedFromAngularCore(
53
+ identifier: TSESTree.Identifier,
54
+ expectedImportedName: string | undefined,
55
+ ): boolean {
56
+ const scope = context.sourceCode.getScope(identifier);
57
+ const variable = ASTUtils.findVariable(scope, identifier.name);
58
+ if (!variable) return false;
59
+
60
+ for (const def of variable.defs) {
61
+ if (def.type !== "ImportBinding") continue;
62
+ if (def.parent.type !== AST_NODE_TYPES.ImportDeclaration) continue;
63
+ if (def.parent.source.value !== "@angular/core") continue;
64
+
65
+ // named/aliased import: import { effect } 또는 import { effect as ngEffect }
66
+ if (def.node.type === AST_NODE_TYPES.ImportSpecifier && expectedImportedName != null) {
67
+ const imported = def.node.imported;
68
+ if (
69
+ imported.type === AST_NODE_TYPES.Identifier &&
70
+ imported.name === expectedImportedName
71
+ ) {
72
+ return true;
73
+ }
74
+ }
75
+
76
+ // namespace import: import * as ng
77
+ if (
78
+ def.node.type === AST_NODE_TYPES.ImportNamespaceSpecifier &&
79
+ expectedImportedName == null
80
+ ) {
81
+ return true;
82
+ }
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+ return {
89
+ CallExpression(node: TSESTree.CallExpression) {
90
+ let isAngularEffect = false;
91
+
92
+ // 케이스 1: effect(...) 또는 aliased된 effect (named import)
93
+ if (node.callee.type === AST_NODE_TYPES.Identifier) {
94
+ isAngularEffect = isImportedFromAngularCore(node.callee, "effect");
95
+ }
96
+
97
+ // 케이스 2: ng.effect(...) (namespace import)
98
+ else if (
99
+ node.callee.type === AST_NODE_TYPES.MemberExpression &&
100
+ node.callee.property.type === AST_NODE_TYPES.Identifier &&
101
+ node.callee.property.name === "effect" &&
102
+ node.callee.object.type === AST_NODE_TYPES.Identifier
103
+ ) {
104
+ isAngularEffect = isImportedFromAngularCore(node.callee.object, undefined);
105
+ }
106
+
107
+ if (!isAngularEffect) return;
108
+
109
+ const firstArg = node.arguments.at(0);
110
+ if (firstArg == null) return;
111
+
112
+ const isAsyncFunction =
113
+ (firstArg.type === AST_NODE_TYPES.ArrowFunctionExpression ||
114
+ firstArg.type === AST_NODE_TYPES.FunctionExpression) &&
115
+ firstArg.async;
116
+
117
+ if (!isAsyncFunction) return;
118
+
119
+ context.report({
120
+ node: firstArg,
121
+ messageId: "noAsyncEffect",
122
+ });
123
+ },
124
+ };
125
+ },
126
+ });
@@ -24,7 +24,7 @@ export default createRule({
24
24
  },
25
25
  defaultOptions: [],
26
26
  create(context) {
27
- const parserServices = getTemplateParserServices(context as never);
27
+ const parserServices = getTemplateParserServices(context);
28
28
  const sourceCode = context.sourceCode;
29
29
 
30
30
  return {
@@ -59,7 +59,7 @@ export default createRule({
59
59
  },
60
60
  });
61
61
  },
62
- } as never;
62
+ };
63
63
  },
64
64
  });
65
65
 
@@ -48,7 +48,7 @@ export default createRule({
48
48
  },
49
49
  defaultOptions: [{}] as [RuleOptions],
50
50
  create(context) {
51
- const parserServices = getTemplateParserServices(context as never);
51
+ const parserServices = getTemplateParserServices(context);
52
52
  const userOptions = context.options.at(0) ?? {};
53
53
  const selectorPrefixes = userOptions.selectorPrefixes ?? DEFAULT_OPTIONS.selectorPrefixes;
54
54
  const allowAttributes = userOptions.allowAttributes ?? DEFAULT_OPTIONS.allowAttributes;
@@ -106,6 +106,6 @@ export default createRule({
106
106
  });
107
107
  }
108
108
  },
109
- } as never;
109
+ };
110
110
  },
111
111
  });