@futdevpro/dynamo-eslint 1.14.2 → 1.14.4
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/.eslintrc.json +4 -0
- package/.vscode/settings.json +13 -0
- package/README.md +279 -29
- package/build/configs/base.d.ts +6 -81
- package/build/configs/base.d.ts.map +1 -1
- package/build/configs/base.js +90 -54
- package/build/configs/base.js.map +1 -1
- package/build/configs/fsm.d.ts +1 -85
- package/build/configs/fsm.d.ts.map +1 -1
- package/build/configs/fsm.js +3 -6
- package/build/configs/fsm.js.map +1 -1
- package/build/configs/ngx-package.d.ts +1 -85
- package/build/configs/ngx-package.d.ts.map +1 -1
- package/build/configs/ngx-package.js +3 -6
- package/build/configs/ngx-package.js.map +1 -1
- package/build/configs/ngx.d.ts +4 -85
- package/build/configs/ngx.d.ts.map +1 -1
- package/build/configs/ngx.js +67 -11
- package/build/configs/ngx.js.map +1 -1
- package/build/configs/nts-package.d.ts +1 -87
- package/build/configs/nts-package.d.ts.map +1 -1
- package/build/configs/nts-package.js +12 -10
- package/build/configs/nts-package.js.map +1 -1
- package/build/configs/nts.d.ts +1 -86
- package/build/configs/nts.d.ts.map +1 -1
- package/build/configs/nts.js +26 -11
- package/build/configs/nts.js.map +1 -1
- package/build/plugin/index.d.ts +2 -0
- package/build/plugin/index.d.ts.map +1 -1
- package/build/plugin/index.js +3 -0
- package/build/plugin/index.js.map +1 -1
- package/build/plugin/rules/explicit-types.d.ts +4 -0
- package/build/plugin/rules/explicit-types.d.ts.map +1 -0
- package/build/plugin/rules/explicit-types.js +165 -0
- package/build/plugin/rules/explicit-types.js.map +1 -0
- package/build/plugin/rules/explicit-types.spec.d.ts +2 -0
- package/build/plugin/rules/explicit-types.spec.d.ts.map +1 -0
- package/build/plugin/rules/explicit-types.spec.js +162 -0
- package/build/plugin/rules/explicit-types.spec.js.map +1 -0
- package/build/plugin/rules/import/no-import-type.d.ts.map +1 -1
- package/build/plugin/rules/import/no-import-type.js +23 -12
- package/build/plugin/rules/import/no-import-type.js.map +1 -1
- package/build/plugin/rules/import/no-js-import.d.ts.map +1 -1
- package/build/plugin/rules/import/no-js-import.js +22 -11
- package/build/plugin/rules/import/no-js-import.js.map +1 -1
- package/build/plugin/rules/naming-patterns.d.ts.map +1 -1
- package/build/plugin/rules/naming-patterns.js +7 -2
- package/build/plugin/rules/naming-patterns.js.map +1 -1
- package/build/scripts/dynamo-fix.d.ts +24 -0
- package/build/scripts/dynamo-fix.d.ts.map +1 -1
- package/build/scripts/dynamo-fix.js +57 -2
- package/build/scripts/dynamo-fix.js.map +1 -1
- package/build/scripts/eslintrc-audit.d.ts +24 -0
- package/build/scripts/eslintrc-audit.d.ts.map +1 -1
- package/build/scripts/eslintrc-audit.js +65 -0
- package/build/scripts/eslintrc-audit.js.map +1 -1
- package/build/scripts/fix-return-types.d.ts +25 -0
- package/build/scripts/fix-return-types.d.ts.map +1 -1
- package/build/scripts/fix-return-types.js +80 -9
- package/build/scripts/fix-return-types.js.map +1 -1
- package/build/scripts/validate-imports.d.ts +24 -0
- package/build/scripts/validate-imports.d.ts.map +1 -1
- package/build/scripts/validate-imports.js +62 -1
- package/build/scripts/validate-imports.js.map +1 -1
- package/build/scripts/validate-naming.d.ts +24 -0
- package/build/scripts/validate-naming.d.ts.map +1 -1
- package/build/scripts/validate-naming.js +72 -9
- package/build/scripts/validate-naming.js.map +1 -1
- package/eslint.config.js +9 -49
- package/futdevpro-dynamo-eslint-01.14.4.tgz +0 -0
- package/package.json +1 -1
- package/samples/.vscode/settings.json +13 -0
- package/samples/base/eslint.config.js +3 -0
- package/samples/fsm/.eslintrc.json +4 -0
- package/samples/fsm/eslint.config.js +3 -0
- package/samples/ngx/eslint.config.js +3 -0
- package/samples/ngx-package/.eslintrc.json +4 -0
- package/samples/ngx-package/eslint.config.js +3 -0
- package/samples/nts/eslint.config.js +3 -0
- package/samples/nts-package/.eslintrc.json +4 -0
- package/samples/nts-package/eslint.config.js +3 -0
- package/samples/package.json.example +26 -0
- package/src/configs/base.ts +90 -54
- package/src/configs/fsm.ts +3 -6
- package/src/configs/ngx-package.ts +3 -6
- package/src/configs/ngx.ts +67 -11
- package/src/configs/nts-package.ts +12 -10
- package/src/configs/nts.ts +26 -11
- package/src/plugin/index.ts +3 -0
- package/src/plugin/rules/explicit-types.spec.ts +190 -0
- package/src/plugin/rules/explicit-types.ts +169 -0
- package/src/plugin/rules/import/no-import-type.ts +21 -12
- package/src/plugin/rules/import/no-js-import.ts +21 -13
- package/src/plugin/rules/naming-patterns.ts +6 -2
- package/src/scripts/dynamo-fix.ts +66 -2
- package/src/scripts/eslintrc-audit.ts +73 -2
- package/src/scripts/fix-return-types.ts +93 -9
- package/src/scripts/validate-imports.ts +71 -2
- package/src/scripts/validate-naming.ts +108 -17
- package/futdevpro-dynamo-eslint-01.14.2.tgz +0 -0
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
const ntsConfig = require('./nts');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Rulesets For Dynamo Based Systems
|
|
5
5
|
* NTS-PACKAGE: Node TypeScript Package
|
|
6
|
+
* ESLint v9 Flat Config Format
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
...
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
module.exports = [
|
|
9
|
+
...ntsConfig,
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
12
|
+
rules: {
|
|
13
|
+
...ntsConfig[1].rules,
|
|
14
|
+
'@typescript-eslint/ban-types': 'off',
|
|
15
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
16
|
+
},
|
|
13
17
|
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export = config;
|
|
18
|
+
];
|
|
17
19
|
|
|
18
20
|
|
package/src/configs/nts.ts
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
const ntsBaseConfig = require('./base');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Rulesets For Dynamo Based Systems
|
|
5
5
|
* NTS: Node TypeScript
|
|
6
|
+
* ESLint v9 Flat Config Format
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
...
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
module.exports = [
|
|
9
|
+
...ntsBaseConfig,
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
...ntsBaseConfig[1].languageOptions,
|
|
14
|
+
globals: {
|
|
15
|
+
// Node.js globals
|
|
16
|
+
process: 'readonly',
|
|
17
|
+
Buffer: 'readonly',
|
|
18
|
+
global: 'readonly',
|
|
19
|
+
__dirname: 'readonly',
|
|
20
|
+
__filename: 'readonly',
|
|
21
|
+
module: 'readonly',
|
|
22
|
+
require: 'readonly',
|
|
23
|
+
exports: 'readonly',
|
|
24
|
+
console: 'readonly'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
rules: {
|
|
28
|
+
...ntsBaseConfig[1].rules,
|
|
29
|
+
'max-lines': ['warn', 1500],
|
|
30
|
+
},
|
|
14
31
|
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export = config;
|
|
32
|
+
];
|
|
18
33
|
|
|
19
34
|
|
package/src/plugin/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import explicitTypesRule from './rules/explicit-types';
|
|
1
2
|
import importOrderRule from './rules/import/import-order';
|
|
2
3
|
import namingPatternsRule from './rules/naming-patterns';
|
|
3
4
|
import noImportTypeRule from './rules/import/no-import-type';
|
|
@@ -5,6 +6,7 @@ import noJsExtensionRule from './rules/import/no-js-import';
|
|
|
5
6
|
|
|
6
7
|
export = {
|
|
7
8
|
rules: {
|
|
9
|
+
'explicit-types': explicitTypesRule,
|
|
8
10
|
'import-order': importOrderRule,
|
|
9
11
|
'no-import-type': noImportTypeRule,
|
|
10
12
|
'no-js-import': noJsExtensionRule,
|
|
@@ -14,6 +16,7 @@ export = {
|
|
|
14
16
|
configs: {
|
|
15
17
|
recommended: {
|
|
16
18
|
rules: {
|
|
19
|
+
'@futdevpro/dynamo/explicit-types': 'warn',
|
|
17
20
|
'@futdevpro/dynamo/import-order': 'warn',
|
|
18
21
|
'@futdevpro/dynamo/no-import-type': 'warn',
|
|
19
22
|
'@futdevpro/dynamo/no-js-import': 'warn',
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import explicitTypesRule from './explicit-types';
|
|
2
|
+
|
|
3
|
+
describe('| explicit-types', () => {
|
|
4
|
+
it('| should be a valid ESLint rule', () => {
|
|
5
|
+
expect(explicitTypesRule.meta?.type).toBe('suggestion');
|
|
6
|
+
expect(explicitTypesRule.meta?.docs?.description).toContain('explicit type annotations');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('| should have create function that returns visitor object', () => {
|
|
10
|
+
const mockContext = {
|
|
11
|
+
report: () => {},
|
|
12
|
+
} as any;
|
|
13
|
+
|
|
14
|
+
const result = explicitTypesRule.create(mockContext);
|
|
15
|
+
|
|
16
|
+
expect(typeof result).toBe('object');
|
|
17
|
+
expect(typeof result.FunctionDeclaration).toBe('function');
|
|
18
|
+
expect(typeof result.ArrowFunctionExpression).toBe('function');
|
|
19
|
+
expect(typeof result.VariableDeclarator).toBe('function');
|
|
20
|
+
expect(typeof result.PropertyDefinition).toBe('function');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('| should report missing return types on function declarations', () => {
|
|
24
|
+
const mockContext = {
|
|
25
|
+
report: (options: any) => {
|
|
26
|
+
expect(options.messageId).toBe('missingReturnType');
|
|
27
|
+
expect(options.data.name).toBe('testFunction');
|
|
28
|
+
},
|
|
29
|
+
} as any;
|
|
30
|
+
|
|
31
|
+
const mockNode = {
|
|
32
|
+
type: 'FunctionDeclaration' as const,
|
|
33
|
+
id: { name: 'testFunction' },
|
|
34
|
+
returnType: null,
|
|
35
|
+
params: [],
|
|
36
|
+
} as any;
|
|
37
|
+
|
|
38
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
39
|
+
rule.FunctionDeclaration(mockNode);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('| should not report when function has return type', () => {
|
|
43
|
+
const mockContext = {
|
|
44
|
+
report: (options: any) => {
|
|
45
|
+
fail('Should not report when function has return type');
|
|
46
|
+
},
|
|
47
|
+
} as any;
|
|
48
|
+
|
|
49
|
+
const mockNode = {
|
|
50
|
+
type: 'FunctionDeclaration' as const,
|
|
51
|
+
id: { name: 'testFunction' },
|
|
52
|
+
returnType: { type: 'TSTypeAnnotation' },
|
|
53
|
+
params: [],
|
|
54
|
+
} as any;
|
|
55
|
+
|
|
56
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
57
|
+
rule.FunctionDeclaration(mockNode);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('| should report missing return types on arrow functions', () => {
|
|
61
|
+
const mockContext = {
|
|
62
|
+
report: (options: any) => {
|
|
63
|
+
expect(options.messageId).toBe('missingArrowReturnType');
|
|
64
|
+
},
|
|
65
|
+
} as any;
|
|
66
|
+
|
|
67
|
+
const mockNode = {
|
|
68
|
+
type: 'ArrowFunctionExpression' as const,
|
|
69
|
+
returnType: null,
|
|
70
|
+
params: [],
|
|
71
|
+
} as any;
|
|
72
|
+
|
|
73
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
74
|
+
rule.ArrowFunctionExpression(mockNode);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('| should report missing types on variable declarations', () => {
|
|
78
|
+
const mockContext = {
|
|
79
|
+
report: (options: any) => {
|
|
80
|
+
expect(options.messageId).toBe('missingVariableType');
|
|
81
|
+
expect(options.data.name).toBe('testVar');
|
|
82
|
+
},
|
|
83
|
+
} as any;
|
|
84
|
+
|
|
85
|
+
const mockNode = {
|
|
86
|
+
type: 'VariableDeclarator' as const,
|
|
87
|
+
id: { name: 'testVar', typeAnnotation: null },
|
|
88
|
+
init: null,
|
|
89
|
+
} as any;
|
|
90
|
+
|
|
91
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
92
|
+
rule.VariableDeclarator(mockNode);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('| should not report when variable has type annotation', () => {
|
|
96
|
+
const mockContext = {
|
|
97
|
+
report: (options: any) => {
|
|
98
|
+
fail('Should not report when variable has type annotation');
|
|
99
|
+
},
|
|
100
|
+
} as any;
|
|
101
|
+
|
|
102
|
+
const mockNode = {
|
|
103
|
+
type: 'VariableDeclarator' as const,
|
|
104
|
+
id: { name: 'testVar', typeAnnotation: { type: 'TSTypeAnnotation' } },
|
|
105
|
+
init: null,
|
|
106
|
+
} as any;
|
|
107
|
+
|
|
108
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
109
|
+
rule.VariableDeclarator(mockNode);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('| should not report when variable has typed initializer', () => {
|
|
113
|
+
const mockContext = {
|
|
114
|
+
report: (options: any) => {
|
|
115
|
+
fail('Should not report when variable has typed initializer');
|
|
116
|
+
},
|
|
117
|
+
} as any;
|
|
118
|
+
|
|
119
|
+
const mockNode = {
|
|
120
|
+
type: 'VariableDeclarator' as const,
|
|
121
|
+
id: { name: 'testVar', typeAnnotation: null },
|
|
122
|
+
init: { type: 'CallExpression' },
|
|
123
|
+
} as any;
|
|
124
|
+
|
|
125
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
126
|
+
rule.VariableDeclarator(mockNode);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('| should report missing parameter types', () => {
|
|
130
|
+
const mockContext = {
|
|
131
|
+
report: (options: any) => {
|
|
132
|
+
expect(options.messageId).toBe('missingParameterType');
|
|
133
|
+
expect(options.data.name).toBe('param');
|
|
134
|
+
},
|
|
135
|
+
} as any;
|
|
136
|
+
|
|
137
|
+
const mockNode = {
|
|
138
|
+
type: 'FunctionDeclaration' as const,
|
|
139
|
+
id: { name: 'testFunction' },
|
|
140
|
+
returnType: { type: 'TSTypeAnnotation' },
|
|
141
|
+
params: [
|
|
142
|
+
{ type: 'Identifier', name: 'param', typeAnnotation: null }
|
|
143
|
+
],
|
|
144
|
+
} as any;
|
|
145
|
+
|
|
146
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
147
|
+
rule.FunctionDeclaration(mockNode);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('| should report missing class property types', () => {
|
|
151
|
+
const mockContext = {
|
|
152
|
+
report: (options: any) => {
|
|
153
|
+
expect(options.messageId).toBe('missingPropertyType');
|
|
154
|
+
expect(options.data.name).toBe('property');
|
|
155
|
+
},
|
|
156
|
+
} as any;
|
|
157
|
+
|
|
158
|
+
const mockNode = {
|
|
159
|
+
type: 'PropertyDefinition' as const,
|
|
160
|
+
key: { name: 'property' },
|
|
161
|
+
typeAnnotation: null,
|
|
162
|
+
value: null,
|
|
163
|
+
} as any;
|
|
164
|
+
|
|
165
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
166
|
+
rule.PropertyDefinition(mockNode);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('| should report missing destructuring types', () => {
|
|
170
|
+
const mockContext = {
|
|
171
|
+
report: (options: any) => {
|
|
172
|
+
expect(options.messageId).toBe('missingDestructuringType');
|
|
173
|
+
},
|
|
174
|
+
} as any;
|
|
175
|
+
|
|
176
|
+
const objectPatternNode = {
|
|
177
|
+
type: 'ObjectPattern' as const,
|
|
178
|
+
typeAnnotation: null,
|
|
179
|
+
} as any;
|
|
180
|
+
|
|
181
|
+
const arrayPatternNode = {
|
|
182
|
+
type: 'ArrayPattern' as const,
|
|
183
|
+
typeAnnotation: null,
|
|
184
|
+
} as any;
|
|
185
|
+
|
|
186
|
+
const rule = explicitTypesRule.create(mockContext);
|
|
187
|
+
rule.ObjectPattern(objectPatternNode);
|
|
188
|
+
rule.ArrayPattern(arrayPatternNode);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
const rule: Rule.RuleModule = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'suggestion',
|
|
6
|
+
docs: {
|
|
7
|
+
description: 'Enforce explicit type annotations on all TypeScript declarations',
|
|
8
|
+
recommended: true,
|
|
9
|
+
},
|
|
10
|
+
schema: [],
|
|
11
|
+
messages: {
|
|
12
|
+
missingReturnType: 'Function "{{name}}" must have an explicit return type annotation.',
|
|
13
|
+
missingArrowReturnType: 'Arrow function must have an explicit return type annotation.',
|
|
14
|
+
missingVariableType: 'Variable "{{name}}" must have an explicit type annotation.',
|
|
15
|
+
missingParameterType: 'Parameter "{{name}}" must have an explicit type annotation.',
|
|
16
|
+
missingPropertyType: 'Class property "{{name}}" must have an explicit type annotation.',
|
|
17
|
+
missingDestructuringType: 'Destructuring assignment must have explicit type annotations.',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
// Function declarations
|
|
23
|
+
FunctionDeclaration(node: any) {
|
|
24
|
+
try {
|
|
25
|
+
// Check return type
|
|
26
|
+
if (!node.returnType) {
|
|
27
|
+
context.report({
|
|
28
|
+
node,
|
|
29
|
+
messageId: 'missingReturnType',
|
|
30
|
+
data: { name: node.id?.name || 'anonymous' },
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check function parameters with defensive checks
|
|
35
|
+
if (node.params && Array.isArray(node.params)) {
|
|
36
|
+
node.params.forEach((param: any) => {
|
|
37
|
+
try {
|
|
38
|
+
if (param && param.type === 'Identifier' && !param.typeAnnotation) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: param,
|
|
41
|
+
messageId: 'missingParameterType',
|
|
42
|
+
data: { name: param.name || 'unknown' },
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
} catch (paramError) {
|
|
46
|
+
console.error('[explicit-types] Error processing function parameter:', paramError);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('[explicit-types] Error in FunctionDeclaration visitor:', error);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// Arrow functions
|
|
56
|
+
ArrowFunctionExpression(node: any) {
|
|
57
|
+
try {
|
|
58
|
+
// Check return type
|
|
59
|
+
if (!node.returnType) {
|
|
60
|
+
context.report({
|
|
61
|
+
node,
|
|
62
|
+
messageId: 'missingArrowReturnType',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check arrow function parameters with defensive checks
|
|
67
|
+
if (node.params && Array.isArray(node.params)) {
|
|
68
|
+
node.params.forEach((param: any) => {
|
|
69
|
+
try {
|
|
70
|
+
if (param && param.type === 'Identifier' && !param.typeAnnotation) {
|
|
71
|
+
context.report({
|
|
72
|
+
node: param,
|
|
73
|
+
messageId: 'missingParameterType',
|
|
74
|
+
data: { name: param.name || 'unknown' },
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
} catch (paramError) {
|
|
78
|
+
console.error('[explicit-types] Error processing arrow function parameter:', paramError);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('[explicit-types] Error in ArrowFunctionExpression visitor:', error);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Variable declarations
|
|
88
|
+
VariableDeclarator(node: any) {
|
|
89
|
+
try {
|
|
90
|
+
// Defensive check for node.id
|
|
91
|
+
if (!node.id) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!node.id.typeAnnotation) {
|
|
96
|
+
// Skip if variable is initialized with a typed value that can be inferred
|
|
97
|
+
const hasTypedInitializer = node.init && (
|
|
98
|
+
node.init.type === 'CallExpression' ||
|
|
99
|
+
node.init.type === 'NewExpression' ||
|
|
100
|
+
node.init.type === 'ArrayExpression' ||
|
|
101
|
+
node.init.type === 'ObjectExpression' ||
|
|
102
|
+
node.init.type === 'Literal'
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (!hasTypedInitializer) {
|
|
106
|
+
context.report({
|
|
107
|
+
node: node.id,
|
|
108
|
+
messageId: 'missingVariableType',
|
|
109
|
+
data: { name: (node.id as any)?.name || 'destructured' },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('[explicit-types] Error in VariableDeclarator visitor:', error);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
// Class properties
|
|
119
|
+
PropertyDefinition(node: any) {
|
|
120
|
+
try {
|
|
121
|
+
// Defensive check for node.key
|
|
122
|
+
if (!node.key) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!node.typeAnnotation && !node.value) {
|
|
127
|
+
context.report({
|
|
128
|
+
node: node.key,
|
|
129
|
+
messageId: 'missingPropertyType',
|
|
130
|
+
data: { name: (node.key as any)?.name || 'computed' },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error('[explicit-types] Error in PropertyDefinition visitor:', error);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
// Object destructuring
|
|
139
|
+
ObjectPattern(node: any) {
|
|
140
|
+
try {
|
|
141
|
+
if (!node.typeAnnotation) {
|
|
142
|
+
context.report({
|
|
143
|
+
node,
|
|
144
|
+
messageId: 'missingDestructuringType',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error('[explicit-types] Error in ObjectPattern visitor:', error);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
// Array destructuring
|
|
153
|
+
ArrayPattern(node: any) {
|
|
154
|
+
try {
|
|
155
|
+
if (!node.typeAnnotation) {
|
|
156
|
+
context.report({
|
|
157
|
+
node,
|
|
158
|
+
messageId: 'missingDestructuringType',
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('[explicit-types] Error in ArrayPattern visitor:', error);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export default rule;
|
|
@@ -15,19 +15,28 @@ const rule: Rule.RuleModule = {
|
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
ImportDeclaration(node: any) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
try {
|
|
19
|
+
// Check for import type usage
|
|
20
|
+
if (node.importKind === 'type') {
|
|
21
|
+
context.report({
|
|
22
|
+
node,
|
|
23
|
+
messageId: 'forbiddenImportType',
|
|
24
|
+
fix(fixer) {
|
|
25
|
+
try {
|
|
26
|
+
// Remove 'type' keyword
|
|
27
|
+
const importText = sourceCode.getText(node);
|
|
28
|
+
const newImportText = importText.replace(/import\s+type\s+/, 'import ');
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
return fixer.replaceText(node, newImportText);
|
|
31
|
+
} catch (fixError) {
|
|
32
|
+
console.error('[no-import-type] Error in fix function:', fixError);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('[no-import-type] Error in ImportDeclaration visitor:', error);
|
|
31
40
|
}
|
|
32
41
|
},
|
|
33
42
|
};
|
|
@@ -13,19 +13,27 @@ const rule: Rule.RuleModule = {
|
|
|
13
13
|
create(context) {
|
|
14
14
|
return {
|
|
15
15
|
ImportDeclaration(node: any) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
try {
|
|
17
|
+
const source = node.source?.value as string;
|
|
18
|
+
|
|
19
|
+
if (source && source.endsWith('.js')) {
|
|
20
|
+
context.report({
|
|
21
|
+
node: node.source,
|
|
22
|
+
messageId: 'forbiddenJsExtension',
|
|
23
|
+
fix(fixer) {
|
|
24
|
+
try {
|
|
25
|
+
// Remove .js extension
|
|
26
|
+
const newSource = source.replace(/\.js$/, '');
|
|
27
|
+
return fixer.replaceText(node.source, `'${newSource}'`);
|
|
28
|
+
} catch (fixError) {
|
|
29
|
+
console.error('[no-js-import] Error in fix function:', fixError);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('[no-js-import] Error in ImportDeclaration visitor:', error);
|
|
29
37
|
}
|
|
30
38
|
},
|
|
31
39
|
};
|
|
@@ -13,8 +13,12 @@ const rule: Rule.RuleModule = {
|
|
|
13
13
|
create(context) {
|
|
14
14
|
return {
|
|
15
15
|
Identifier(node) {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
try {
|
|
17
|
+
// Future: use dyfmUtils naming patterns to validate identifiers
|
|
18
|
+
void node;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('[naming-patterns] Error in Identifier visitor:', error);
|
|
21
|
+
}
|
|
18
22
|
},
|
|
19
23
|
};
|
|
20
24
|
},
|