@tianjos/eslint-plugin-elegant 0.2.0 → 0.3.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/README.md +14 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -0
- package/dist/rules/no-null.d.ts +4 -0
- package/dist/rules/no-null.js +34 -0
- package/dist/rules/no-static-members.d.ts +7 -0
- package/dist/rules/no-static-members.js +48 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,6 +81,8 @@ The `recommended` config enables every custom rule plus the native
|
|
|
81
81
|
| `elegant/no-logic-in-constructor` | custom | Any constructor code beyond `this.field = value` stores and a `super(...)` call | `error` |
|
|
82
82
|
| `elegant/no-getters-setters` | custom | `get`/`set` accessors (and `getX`/`setX` methods with `{ methods: true }`) | `error` |
|
|
83
83
|
| `elegant/no-instanceof` | custom | Use of the `instanceof` operator | `error` |
|
|
84
|
+
| `elegant/no-static-members` | custom | Static methods, properties, accessors, and blocks (`allowReadonly` to permit constants) | `error` |
|
|
85
|
+
| `elegant/no-null` | custom | The `null` literal as a value (type annotations and direct `return null` excepted) | `error` |
|
|
84
86
|
| `max-params` | native | Functions declaring more than `max` parameters | `warn` (max 3) |
|
|
85
87
|
|
|
86
88
|
### Rule details
|
|
@@ -114,6 +116,18 @@ The `recommended` config enables every custom rule plus the native
|
|
|
114
116
|
- **`no-instanceof`** — `instanceof` is type discrimination that belongs inside a
|
|
115
117
|
polymorphic method on the object. Pairs with `no-type-assertion` to keep
|
|
116
118
|
type-based branching out of the codebase.
|
|
119
|
+
- **`no-static-members`** — static state and behavior cannot be injected,
|
|
120
|
+
substituted, or mocked. Prefer instances (with dependency injection) and a
|
|
121
|
+
module-level `const` for shared values. The `{ allowReadonly: true }` option
|
|
122
|
+
permits `static readonly` constants. Note this also flags `static` factory
|
|
123
|
+
methods (`static create()`), which are common; relax per-file if your design
|
|
124
|
+
relies on them.
|
|
125
|
+
- **`no-null`** — completes `no-null-return` by banning the `null` literal as a
|
|
126
|
+
value everywhere (`const x = null`, `x === null`, `fn(null)`), pushing absence
|
|
127
|
+
into explicit types or `undefined`. `null` in type positions (`string | null`)
|
|
128
|
+
and a direct `return null` (owned by `no-null-return`) are left alone. This is
|
|
129
|
+
strict and will flag idioms like `JSON.stringify(x, null, 2)` — relax it in the
|
|
130
|
+
files where you interoperate with null-based APIs.
|
|
117
131
|
|
|
118
132
|
## Configuration
|
|
119
133
|
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,14 @@ declare const rules: {
|
|
|
28
28
|
'no-instanceof': TSESLint.RuleModule<"noInstanceof", [], unknown, TSESLint.RuleListener> & {
|
|
29
29
|
name: string;
|
|
30
30
|
};
|
|
31
|
+
'no-static-members': TSESLint.RuleModule<"staticMember", [{
|
|
32
|
+
allowReadonly: boolean;
|
|
33
|
+
}], unknown, TSESLint.RuleListener> & {
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
'no-null': TSESLint.RuleModule<"noNull", [], unknown, TSESLint.RuleListener> & {
|
|
37
|
+
name: string;
|
|
38
|
+
};
|
|
31
39
|
};
|
|
32
40
|
type Plugin = {
|
|
33
41
|
meta: {
|
package/dist/index.js
CHANGED
|
@@ -7,8 +7,10 @@ const no_boolean_param_1 = __importDefault(require("./rules/no-boolean-param"));
|
|
|
7
7
|
const no_getters_setters_1 = __importDefault(require("./rules/no-getters-setters"));
|
|
8
8
|
const no_instanceof_1 = __importDefault(require("./rules/no-instanceof"));
|
|
9
9
|
const no_logic_in_constructor_1 = __importDefault(require("./rules/no-logic-in-constructor"));
|
|
10
|
+
const no_null_1 = __importDefault(require("./rules/no-null"));
|
|
10
11
|
const no_null_return_1 = __importDefault(require("./rules/no-null-return"));
|
|
11
12
|
const no_public_mutable_props_1 = __importDefault(require("./rules/no-public-mutable-props"));
|
|
13
|
+
const no_static_members_1 = __importDefault(require("./rules/no-static-members"));
|
|
12
14
|
const no_type_assertion_1 = __importDefault(require("./rules/no-type-assertion"));
|
|
13
15
|
const { name, version } = require('../package.json');
|
|
14
16
|
const rules = {
|
|
@@ -20,6 +22,8 @@ const rules = {
|
|
|
20
22
|
'no-logic-in-constructor': no_logic_in_constructor_1.default,
|
|
21
23
|
'no-getters-setters': no_getters_setters_1.default,
|
|
22
24
|
'no-instanceof': no_instanceof_1.default,
|
|
25
|
+
'no-static-members': no_static_members_1.default,
|
|
26
|
+
'no-null': no_null_1.default,
|
|
23
27
|
};
|
|
24
28
|
const plugin = {
|
|
25
29
|
meta: { name, version },
|
|
@@ -38,6 +42,8 @@ plugin.configs.recommended = {
|
|
|
38
42
|
'elegant/no-logic-in-constructor': 'error',
|
|
39
43
|
'elegant/no-getters-setters': 'error',
|
|
40
44
|
'elegant/no-instanceof': 'error',
|
|
45
|
+
'elegant/no-static-members': 'error',
|
|
46
|
+
'elegant/no-null': 'error',
|
|
41
47
|
'max-params': ['warn', { max: 3 }],
|
|
42
48
|
},
|
|
43
49
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
4
|
+
const createRule_1 = require("../utils/createRule");
|
|
5
|
+
exports.default = (0, createRule_1.createRule)({
|
|
6
|
+
name: 'no-null',
|
|
7
|
+
meta: {
|
|
8
|
+
type: 'suggestion',
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Disallow the `null` literal as a value. Model absence with an explicit domain type, an Optional/Maybe, or by throwing. Null inside type annotations is allowed; direct `return null` is owned by `no-null-return`.',
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noNull: 'Avoid the null literal. Model absence explicitly instead of leaking null into the code.',
|
|
14
|
+
},
|
|
15
|
+
schema: [],
|
|
16
|
+
},
|
|
17
|
+
defaultOptions: [],
|
|
18
|
+
create(context) {
|
|
19
|
+
return {
|
|
20
|
+
Literal(node) {
|
|
21
|
+
if (node.value !== null || node.raw !== 'null') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Direct `return null;` is the domain of `no-null-return`.
|
|
25
|
+
const { parent } = node;
|
|
26
|
+
if (parent.type === utils_1.AST_NODE_TYPES.ReturnStatement &&
|
|
27
|
+
parent.argument === node) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
context.report({ node, messageId: 'noNull' });
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Options = [{
|
|
2
|
+
allowReadonly: boolean;
|
|
3
|
+
}];
|
|
4
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"staticMember", Options, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createRule_1 = require("../utils/createRule");
|
|
4
|
+
exports.default = (0, createRule_1.createRule)({
|
|
5
|
+
name: 'no-static-members',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'suggestion',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Disallow static members. Static state and behavior cannot be injected, substituted, or mocked; prefer instances and a module-level value when you need a constant.',
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
staticMember: 'Avoid static members. Use an injectable instance, or a module-level constant for shared values.',
|
|
13
|
+
},
|
|
14
|
+
schema: [
|
|
15
|
+
{
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: { allowReadonly: { type: 'boolean' } },
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
defaultOptions: [{ allowReadonly: false }],
|
|
23
|
+
create(context, [{ allowReadonly }]) {
|
|
24
|
+
const reportKey = (key) => {
|
|
25
|
+
context.report({ node: key, messageId: 'staticMember' });
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
MethodDefinition(node) {
|
|
29
|
+
if (node.static) {
|
|
30
|
+
reportKey(node.key);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
PropertyDefinition(node) {
|
|
34
|
+
if (node.static && !(allowReadonly && node.readonly)) {
|
|
35
|
+
reportKey(node.key);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
AccessorProperty(node) {
|
|
39
|
+
if (node.static) {
|
|
40
|
+
reportKey(node.key);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
StaticBlock(node) {
|
|
44
|
+
context.report({ node, messageId: 'staticMember' });
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tianjos/eslint-plugin-elegant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Opinionated ESLint rules for elegant, behavior-rich TypeScript: no flag arguments, no type assertions, no null returns, no public mutable state, and small focused classes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|