@dartess/eslint-plugin 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +5 -1
- package/dist/configs/mobx.js +1 -0
- package/dist/configs/recommended.js +2 -0
- package/dist/configs/vendor-rules/best-practices.d.ts +0 -1
- package/dist/configs/vendor-rules/best-practices.js +0 -3
- package/dist/index.js +2 -0
- package/dist/rules/mobx-no-action-bound.d.ts +3 -0
- package/dist/rules/mobx-no-action-bound.js +25 -0
- package/dist/rules/mobx-require-observer.js +1 -1
- package/docs/rules/mobx-no-action-bound.md +40 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[//]: # (https://keepachangelog.com/en/1.1.0/)
|
|
4
4
|
|
|
5
|
+
## [0.10.0] - 2026-02-23
|
|
6
|
+
|
|
7
|
+
- add rule `@dartess/mobx-no-action-bound`
|
|
8
|
+
- add `@dartess/mobx-no-action-bound` to `mobx` config
|
|
9
|
+
- change `no-sequences` option `allowInParentheses` from `true` to `false`
|
|
10
|
+
- allow `mobx-require-observer` without settings because `mobx` can be used without hooks
|
|
11
|
+
|
|
5
12
|
## [0.9.0] - 2026-02-03
|
|
6
13
|
|
|
7
14
|
- add `eslint-plugin-complete` to `recommended` config
|
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ npm i -D eslint-plugin-storybook
|
|
|
70
70
|
Edit or create `eslint.config.ts` (or `eslint.config.mts`). You probably have to install `jiti` for it.
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
73
74
|
import dartessEslintPluginRecommended from '@dartess/eslint-plugin/recommended';
|
|
74
75
|
import dartessEslintPluginRecommendedPostFormat from '@dartess/eslint-plugin/recommended-post-format';
|
|
75
76
|
|
|
@@ -110,7 +111,7 @@ export default [
|
|
|
110
111
|
// @see `Fine Tuning` -> `Formatters` section below
|
|
111
112
|
|
|
112
113
|
...dartessEslintPluginRecommendedPostFormat,
|
|
113
|
-
]
|
|
114
|
+
] satisfies TSESLint.FlatConfig.ConfigArray;
|
|
114
115
|
|
|
115
116
|
```
|
|
116
117
|
|
|
@@ -154,6 +155,8 @@ This plugin requires manual setup for you build tools.
|
|
|
154
155
|
|
|
155
156
|
If you're using Mobx with legacy decorators, you have to enable rule `mobx/missing-make-observable` manually.
|
|
156
157
|
|
|
158
|
+
if you're using Mobx stores with your custom hooks, set `settings.mobx.storeHooks` [by docs](docs/rules/mobx-require-observer.md).
|
|
159
|
+
|
|
157
160
|
## Supported Rules
|
|
158
161
|
|
|
159
162
|
Each rule has emojis denoting:
|
|
@@ -179,6 +182,7 @@ Each rule has emojis denoting:
|
|
|
179
182
|
| [mobx-require-observer](docs/rules/mobx-require-observer.md) | Components using the stores must be wrapped in an `observer` | ✅ | 🔧 | |
|
|
180
183
|
| [mobx-sync-autorun](docs/rules/mobx-sync-autorun.md) | Enforce synchronous autorun callback | ✅ | | |
|
|
181
184
|
| [mobx-sync-action](docs/rules/mobx-sync-action.md) | Enforce synchronous actions | ✅ | | |
|
|
185
|
+
| [mobx-no-action-bound](docs/rules/mobx-no-action-bound.md) | Enforce using arrow functions for binging `this` to actions | ✅ | | |
|
|
182
186
|
|
|
183
187
|
## Code Reuse Policy
|
|
184
188
|
|
package/dist/configs/mobx.js
CHANGED
|
@@ -9,6 +9,7 @@ const config = [
|
|
|
9
9
|
'mobx/missing-make-observable': 'off', // useless with modern decorators syntax. TODO check original plugin?
|
|
10
10
|
'@dartess/mobx-strict-observable-components-declaration': 'error',
|
|
11
11
|
'@dartess/mobx-require-observer': 'error',
|
|
12
|
+
'@dartess/mobx-no-action-bound': 'error',
|
|
12
13
|
'@dartess/mobx-sync-autorun': 'error', // TODO implement it by types?
|
|
13
14
|
'@dartess/mobx-sync-action': 'error', // TODO implement it by types?
|
|
14
15
|
},
|
|
@@ -165,9 +165,6 @@ const rules = {
|
|
|
165
165
|
// disallow comparisons where both sides are exactly the same
|
|
166
166
|
// https://eslint.org/docs/rules/no-self-compare
|
|
167
167
|
'no-self-compare': 'error',
|
|
168
|
-
// disallow use of comma operator
|
|
169
|
-
// https://eslint.org/docs/rules/no-sequences
|
|
170
|
-
'no-sequences': 'error',
|
|
171
168
|
// disallow useless string concatenation
|
|
172
169
|
// https://eslint.org/docs/rules/no-useless-concat
|
|
173
170
|
'no-useless-concat': 'error',
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import ruleStoriesExportMeta from "./rules/stories-export-meta.js";
|
|
|
5
5
|
import ruleStoriesExportTyped from "./rules/stories-export-typed.js";
|
|
6
6
|
import ruleMobxStrictObservableComponentsDeclaration from "./rules/mobx-strict-observable-components-declaration.js";
|
|
7
7
|
import ruleMobxRequireObserver from "./rules/mobx-require-observer.js";
|
|
8
|
+
import ruleMobxNoActionBound from "./rules/mobx-no-action-bound.js";
|
|
8
9
|
import ruleImportsMaxParentDepth from "./rules/imports-max-parent-depth.js";
|
|
9
10
|
import ruleTsNamedTupleElements from "./rules/ts-named-tuple-elements.js";
|
|
10
11
|
import ruleMobxSyncAutorun from "./rules/mobx-sync-autorun.js";
|
|
@@ -23,6 +24,7 @@ const plugin = {
|
|
|
23
24
|
'mobx-sync-action': ruleMobxSyncAction,
|
|
24
25
|
'mobx-sync-autorun': ruleMobxSyncAutorun,
|
|
25
26
|
'mobx-require-observer': ruleMobxRequireObserver,
|
|
27
|
+
'mobx-no-action-bound': ruleMobxNoActionBound,
|
|
26
28
|
'stories-export-typed': ruleStoriesExportTyped,
|
|
27
29
|
'stories-export-meta': ruleStoriesExportMeta,
|
|
28
30
|
'ts-named-tuple-elements': ruleTsNamedTupleElements,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
export default ESLintUtils.RuleCreator(() => '')({
|
|
3
|
+
name: 'mobx-no-action-bound',
|
|
4
|
+
defaultOptions: [],
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'problem',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Enforce using arrow functions for binging `this` to actions',
|
|
9
|
+
},
|
|
10
|
+
messages: {
|
|
11
|
+
noActionBound: 'rewrite action with arrow function for binding `this`',
|
|
12
|
+
},
|
|
13
|
+
schema: [],
|
|
14
|
+
},
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
"Decorator[expression.object.name='action'][expression.property.name='bound']": function (node) {
|
|
18
|
+
context.report({
|
|
19
|
+
node,
|
|
20
|
+
messageId: 'noActionBound',
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -54,7 +54,7 @@ export default ESLintUtils.RuleCreator(() => '')({
|
|
|
54
54
|
const mobxSettings = context.settings.mobx;
|
|
55
55
|
const hooks = Array.isArray(mobxSettings?.storeHooks) ? mobxSettings.storeHooks : [];
|
|
56
56
|
if (hooks.length === 0) {
|
|
57
|
-
|
|
57
|
+
return {};
|
|
58
58
|
}
|
|
59
59
|
const { sourceCode } = context;
|
|
60
60
|
const program = sourceCode.ast;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Enforce using arrow functions for binging `this` to actions (mobx-no-action-bound)
|
|
2
|
+
|
|
3
|
+
Decorator `@action.bound` automatically bind methods to class instances to avoid context loss (`this`).
|
|
4
|
+
However, this can also be achieved by declaring methods as an properies with arrow functions.
|
|
5
|
+
|
|
6
|
+
This is the first problem with bound methods—their functionality is duplicated by native abilities.
|
|
7
|
+
|
|
8
|
+
In general, for optimization purposes, it's not recommended to bind _everything_; by default,
|
|
9
|
+
class methods should be on the prototype.
|
|
10
|
+
|
|
11
|
+
To resolve the dilemma of "how to avoid binding unnecessary things and avoid losing context"
|
|
12
|
+
the [`@typescript-eslint/unbound-method`](https://typescript-eslint.io/rules/unbound-method/) rule exists.
|
|
13
|
+
|
|
14
|
+
However, it can't detect whether a method is bound via an `@action.bound`. Therefore, it's best to avoid
|
|
15
|
+
using `@action.bound` at all and leave only one binding method—arrow functions with `@typescript-eslint/unbound-method`.
|
|
16
|
+
In this case you don't need think about it.
|
|
17
|
+
|
|
18
|
+
## Rule Details
|
|
19
|
+
|
|
20
|
+
Examples of **incorrect** code for this rule:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
class Store {
|
|
24
|
+
@action.bound
|
|
25
|
+
reset() {
|
|
26
|
+
this.value = null;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Examples of **correct** code for this rule:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
class Store {
|
|
35
|
+
@action
|
|
36
|
+
reset = () => {
|
|
37
|
+
this.value = null;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
```
|