@agilebot/eslint-plugin 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/index.js +59 -52
- package/lib/rules/import/monorepo.js +7 -2
- package/lib/rules/intl/id-unused.js +2 -2
- package/lib/rules/react/better-exhaustive-deps.js +44 -58
- package/lib/rules/react/prefer-named-property-access.js +1 -1
- package/lib/rules/tss/class-naming.js +1 -1
- package/lib/rules/tss/no-color-value.js +0 -1
- package/lib/rules/tss/unused-classes.js +1 -1
- package/lib/util/intl.js +6 -6
- package/lib/util/translations.js +3 -4
- package/lib/util/tss.js +12 -7
- package/package.json +12 -6
- package/lib/util/import.js +0 -71
package/lib/index.js
CHANGED
@@ -1,52 +1,59 @@
|
|
1
|
-
// @ts-check
|
2
|
-
const path = require('path');
|
3
|
-
const { globSync } = require('fast-glob');
|
4
|
-
|
5
|
-
// List all rules in rules folder
|
6
|
-
const rulesPath = path.join(__dirname, 'rules');
|
7
|
-
const ruleFiles = globSync('**/*.js', {
|
8
|
-
cwd: rulesPath
|
9
|
-
});
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
'
|
34
|
-
value: true,
|
35
|
-
regexp: true
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
'@agilebot/
|
48
|
-
'@agilebot/
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
1
|
+
// @ts-check
|
2
|
+
const path = require('node:path');
|
3
|
+
const { globSync } = require('fast-glob');
|
4
|
+
|
5
|
+
// List all rules in rules folder
|
6
|
+
const rulesPath = path.join(__dirname, 'rules');
|
7
|
+
const ruleFiles = globSync('**/*.js', {
|
8
|
+
cwd: rulesPath
|
9
|
+
});
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @type {import('eslint').Linter.RulesRecord}
|
13
|
+
*/
|
14
|
+
const rules = {};
|
15
|
+
ruleFiles.forEach(file => {
|
16
|
+
const { dir, name } = path.parse(file);
|
17
|
+
const ruleName = `${dir}/${name}`;
|
18
|
+
rules[ruleName] = require(path.join(rulesPath, file));
|
19
|
+
});
|
20
|
+
|
21
|
+
module.exports.rules = rules;
|
22
|
+
|
23
|
+
module.exports.configs = {
|
24
|
+
recommended: {
|
25
|
+
plugins: ['@agilebot'],
|
26
|
+
rules: {
|
27
|
+
'react-hooks/exhaustive-deps': 'off',
|
28
|
+
'@agilebot/react/better-exhaustive-deps': [
|
29
|
+
'warn',
|
30
|
+
{
|
31
|
+
checkMemoizedVariableIsStatic: true,
|
32
|
+
staticHooks: {
|
33
|
+
'useIpc.*': {
|
34
|
+
value: true,
|
35
|
+
regexp: true
|
36
|
+
},
|
37
|
+
useDialog: true,
|
38
|
+
useSnackbar: true,
|
39
|
+
useForm: true,
|
40
|
+
'use.*Store': {
|
41
|
+
value: true,
|
42
|
+
regexp: true
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
],
|
47
|
+
'@agilebot/react/prefer-named-property-access': 'error',
|
48
|
+
'@agilebot/react/hook-use-ref': 'warn',
|
49
|
+
'@agilebot/react/no-inline-styles': 'error',
|
50
|
+
'@agilebot/tss/unused-classes': 'warn',
|
51
|
+
'@agilebot/tss/no-color-value': 'error',
|
52
|
+
'@agilebot/tss/class-naming': 'error',
|
53
|
+
'@agilebot/import/enforce-icon-alias': 'error',
|
54
|
+
'@agilebot/import/monorepo': 'error',
|
55
|
+
'@agilebot/others/no-unnecessary-template-literals': 'error'
|
56
|
+
},
|
57
|
+
settings: {}
|
58
|
+
}
|
59
|
+
};
|
@@ -1,6 +1,7 @@
|
|
1
|
-
const { consola } = require('consola');
|
2
1
|
const { getSetting } = require('../../util/settings');
|
3
2
|
|
3
|
+
let warnedForMissingPrefix = false;
|
4
|
+
|
4
5
|
module.exports = {
|
5
6
|
meta: {
|
6
7
|
type: 'problem', // `problem`, `suggestion`, or `layout`
|
@@ -17,7 +18,11 @@ module.exports = {
|
|
17
18
|
ImportDeclaration(node) {
|
18
19
|
const prefix = getSetting(context, 'monorepo-prefix');
|
19
20
|
if (!prefix) {
|
20
|
-
|
21
|
+
if (!warnedForMissingPrefix) {
|
22
|
+
// eslint-disable-next-line no-console -- this is a CLI tool
|
23
|
+
console.error('Warning: agilebot/monorepo-prefix is not set.');
|
24
|
+
warnedForMissingPrefix = true;
|
25
|
+
}
|
21
26
|
return;
|
22
27
|
}
|
23
28
|
|
@@ -1,6 +1,3 @@
|
|
1
|
-
/* eslint-disable no-case-declarations */
|
2
|
-
/* eslint-disable no-continue */
|
3
|
-
|
4
1
|
/**
|
5
2
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
6
3
|
*
|
@@ -96,12 +93,13 @@ module.exports = {
|
|
96
93
|
};
|
97
94
|
|
98
95
|
function reportProblem(problem) {
|
99
|
-
if (
|
100
|
-
// Used to enable legacy behavior. Dangerous.
|
96
|
+
if (
|
97
|
+
enableDangerousAutofixThisMayCauseInfiniteLoops && // Used to enable legacy behavior. Dangerous.
|
101
98
|
// Keep this as an option until major IDEs upgrade (including VSCode FB ESLint extension).
|
102
|
-
|
103
|
-
|
104
|
-
|
99
|
+
Array.isArray(problem.suggest) &&
|
100
|
+
problem.suggest.length > 0
|
101
|
+
) {
|
102
|
+
problem.fix = problem.suggest[0].fix;
|
105
103
|
}
|
106
104
|
context.report(problem);
|
107
105
|
}
|
@@ -286,17 +284,14 @@ module.exports = {
|
|
286
284
|
if (name === 'useState') {
|
287
285
|
const references = resolved.references;
|
288
286
|
let writeCount = 0;
|
289
|
-
for (
|
290
|
-
if (
|
287
|
+
for (const reference of references) {
|
288
|
+
if (reference.isWrite()) {
|
291
289
|
writeCount++;
|
292
290
|
}
|
293
291
|
if (writeCount > 1) {
|
294
292
|
return false;
|
295
293
|
}
|
296
|
-
setStateCallSites.set(
|
297
|
-
references[i].identifier,
|
298
|
-
id.elements[0]
|
299
|
-
);
|
294
|
+
setStateCallSites.set(reference.identifier, id.elements[0]);
|
300
295
|
}
|
301
296
|
}
|
302
297
|
// Setter is stable.
|
@@ -304,8 +299,8 @@ module.exports = {
|
|
304
299
|
} else if (id.elements[0] === resolved.identifiers[0]) {
|
305
300
|
if (name === 'useState') {
|
306
301
|
const references = resolved.references;
|
307
|
-
for (
|
308
|
-
stateVariables.add(
|
302
|
+
for (const reference of references) {
|
303
|
+
stateVariables.add(reference.identifier);
|
309
304
|
}
|
310
305
|
}
|
311
306
|
// State variable itself is dynamic.
|
@@ -317,13 +312,11 @@ module.exports = {
|
|
317
312
|
if (
|
318
313
|
id.type === 'ArrayPattern' &&
|
319
314
|
id.elements.length === 2 &&
|
320
|
-
Array.isArray(resolved.identifiers)
|
315
|
+
Array.isArray(resolved.identifiers) && // Is second tuple value the same reference we're checking?
|
316
|
+
id.elements[1] === resolved.identifiers[0]
|
321
317
|
) {
|
322
|
-
//
|
323
|
-
|
324
|
-
// Setter is stable.
|
325
|
-
return true;
|
326
|
-
}
|
318
|
+
// Setter is stable.
|
319
|
+
return true;
|
327
320
|
}
|
328
321
|
} else if (
|
329
322
|
options.checkMemoizedVariableIsStatic &&
|
@@ -350,7 +343,7 @@ module.exports = {
|
|
350
343
|
);
|
351
344
|
|
352
345
|
if (
|
353
|
-
|
346
|
+
dependencyRefernece !== undefined &&
|
354
347
|
memoizedIsStableKnownHookValue(dependencyRefernece.resolved)
|
355
348
|
) {
|
356
349
|
continue;
|
@@ -372,7 +365,6 @@ module.exports = {
|
|
372
365
|
}
|
373
366
|
});
|
374
367
|
|
375
|
-
// eslint-disable-next-line no-lonely-if
|
376
368
|
if (options.staticHooks[name]) {
|
377
369
|
const staticParts = options.staticHooks[name];
|
378
370
|
if (staticParts === true) {
|
@@ -386,9 +378,7 @@ module.exports = {
|
|
386
378
|
Array.isArray(resolved.identifiers)
|
387
379
|
) {
|
388
380
|
// find index of the resolved ident in the array pattern
|
389
|
-
const idx = id.elements.
|
390
|
-
ident => ident === resolved.identifiers[0]
|
391
|
-
);
|
381
|
+
const idx = id.elements.indexOf(resolved.identifiers[0]);
|
392
382
|
if (idx >= 0) {
|
393
383
|
return staticParts[idx];
|
394
384
|
}
|
@@ -587,8 +577,7 @@ module.exports = {
|
|
587
577
|
// Is React managing this ref or us?
|
588
578
|
// Let's see if we can find a .current assignment.
|
589
579
|
let foundCurrentAssignment = false;
|
590
|
-
for (
|
591
|
-
const { identifier } = references[i];
|
580
|
+
for (const { identifier } of references) {
|
592
581
|
const { parent } = identifier;
|
593
582
|
if (
|
594
583
|
parent != null &&
|
@@ -764,8 +753,8 @@ module.exports = {
|
|
764
753
|
declaredDependencyNode,
|
765
754
|
null
|
766
755
|
);
|
767
|
-
} catch (
|
768
|
-
if (/Unsupported node type/.test(
|
756
|
+
} catch (err) {
|
757
|
+
if (/Unsupported node type/.test(err.message)) {
|
769
758
|
if (declaredDependencyNode.type === 'Literal') {
|
770
759
|
if (dependencies.has(declaredDependencyNode.value)) {
|
771
760
|
reportProblem({
|
@@ -795,7 +784,7 @@ module.exports = {
|
|
795
784
|
|
796
785
|
return;
|
797
786
|
}
|
798
|
-
throw
|
787
|
+
throw err;
|
799
788
|
}
|
800
789
|
|
801
790
|
let maybeID = declaredDependencyNode;
|
@@ -942,7 +931,7 @@ module.exports = {
|
|
942
931
|
return true;
|
943
932
|
}
|
944
933
|
const declaredDepKeys = declaredDependencies.map(dep => dep.key);
|
945
|
-
const sortedDeclaredDepKeys = declaredDepKeys.
|
934
|
+
const sortedDeclaredDepKeys = [...declaredDepKeys].sort();
|
946
935
|
return declaredDepKeys.join(',') === sortedDeclaredDepKeys.join(',');
|
947
936
|
}
|
948
937
|
if (areDeclaredDepsAlphabetized()) {
|
@@ -978,9 +967,7 @@ module.exports = {
|
|
978
967
|
(deps.size > 1 ? 'dependencies' : 'dependency') +
|
979
968
|
': ' +
|
980
969
|
joinEnglish(
|
981
|
-
|
982
|
-
.sort()
|
983
|
-
.map(name => "'" + formatDependency(name) + "'")
|
970
|
+
[...deps].sort().map(name => "'" + formatDependency(name) + "'")
|
984
971
|
) +
|
985
972
|
`. Either ${fixVerb} ${
|
986
973
|
deps.size > 1 ? 'them' : 'it'
|
@@ -991,7 +978,7 @@ module.exports = {
|
|
991
978
|
let extraWarning = '';
|
992
979
|
if (unnecessaryDependencies.size > 0) {
|
993
980
|
let badRef = null;
|
994
|
-
|
981
|
+
[...unnecessaryDependencies.keys()].forEach(key => {
|
995
982
|
if (badRef != null) {
|
996
983
|
return;
|
997
984
|
}
|
@@ -1004,7 +991,7 @@ module.exports = {
|
|
1004
991
|
` Mutable values like '${badRef}' aren't valid dependencies ` +
|
1005
992
|
"because mutating them doesn't re-render the component.";
|
1006
993
|
} else if (externalDependencies.size > 0) {
|
1007
|
-
const dep =
|
994
|
+
const dep = [...externalDependencies][0];
|
1008
995
|
// Don't show this warning for things that likely just got moved *inside* the callback
|
1009
996
|
// because in that case they're clearly not referring to globals.
|
1010
997
|
if (!scope.set.has(dep)) {
|
@@ -1028,8 +1015,7 @@ module.exports = {
|
|
1028
1015
|
return;
|
1029
1016
|
}
|
1030
1017
|
let isPropsOnlyUsedInMembers = true;
|
1031
|
-
for (
|
1032
|
-
const ref = refs[i];
|
1018
|
+
for (const ref of refs) {
|
1033
1019
|
const id = fastFindReferenceWithParent(
|
1034
1020
|
componentScope.block,
|
1035
1021
|
ref.identifier
|
@@ -1121,8 +1107,8 @@ module.exports = {
|
|
1121
1107
|
const references = usedDep.references;
|
1122
1108
|
let id;
|
1123
1109
|
let maybeCall;
|
1124
|
-
for (
|
1125
|
-
id =
|
1110
|
+
for (const reference of references) {
|
1111
|
+
id = reference.identifier;
|
1126
1112
|
maybeCall = id.parent;
|
1127
1113
|
// Try to see if we have setState(someExpr(missingDep)).
|
1128
1114
|
while (maybeCall != null && maybeCall !== componentScope.block) {
|
@@ -1146,7 +1132,7 @@ module.exports = {
|
|
1146
1132
|
form: 'reducer'
|
1147
1133
|
};
|
1148
1134
|
} else {
|
1149
|
-
const resolved =
|
1135
|
+
const resolved = reference.resolved;
|
1150
1136
|
if (resolved != null) {
|
1151
1137
|
// If it's a parameter *and* a missing dep,
|
1152
1138
|
// it must be a prop or something inside a prop.
|
@@ -1189,7 +1175,7 @@ module.exports = {
|
|
1189
1175
|
case 'updater':
|
1190
1176
|
extraWarning = ` You can also do a functional update '${
|
1191
1177
|
setStateRecommendation.setter
|
1192
|
-
}(${setStateRecommendation.missingDep.
|
1178
|
+
}(${setStateRecommendation.missingDep.slice(
|
1193
1179
|
0,
|
1194
1180
|
1
|
1195
1181
|
)} => ...)' if you only need '${
|
@@ -1224,13 +1210,13 @@ module.exports = {
|
|
1224
1210
|
suggest: [
|
1225
1211
|
{
|
1226
1212
|
desc: `Update the dependencies array to be: [${suggestedDeps
|
1227
|
-
.map(formatDependency)
|
1213
|
+
.map(element => formatDependency(element))
|
1228
1214
|
.join(', ')}]`,
|
1229
1215
|
fix(fixer) {
|
1230
1216
|
// TODO: consider preserving the comments or formatting?
|
1231
1217
|
return fixer.replaceText(
|
1232
1218
|
declaredDependenciesNode,
|
1233
|
-
`[${suggestedDeps.map(formatDependency).join(', ')}]`
|
1219
|
+
`[${suggestedDeps.map(element => formatDependency(element)).join(', ')}]`
|
1234
1220
|
);
|
1235
1221
|
}
|
1236
1222
|
}
|
@@ -1520,7 +1506,7 @@ function collectRecommendations({
|
|
1520
1506
|
declaredDependencies.forEach(({ key }) => {
|
1521
1507
|
// Does this declared dep satisfy a real need?
|
1522
1508
|
if (satisfyingDependencies.has(key)) {
|
1523
|
-
if (suggestedDependencies.
|
1509
|
+
if (!suggestedDependencies.includes(key)) {
|
1524
1510
|
// Good one.
|
1525
1511
|
suggestedDependencies.push(key);
|
1526
1512
|
} else {
|
@@ -1536,7 +1522,7 @@ function collectRecommendations({
|
|
1536
1522
|
// Such as resetting scroll when ID changes.
|
1537
1523
|
// Consider them legit.
|
1538
1524
|
// The exception is ref.current which is always wrong.
|
1539
|
-
if (suggestedDependencies.
|
1525
|
+
if (!suggestedDependencies.includes(key)) {
|
1540
1526
|
suggestedDependencies.push(key);
|
1541
1527
|
}
|
1542
1528
|
} else {
|
@@ -1681,12 +1667,12 @@ function scanForConstructions({
|
|
1681
1667
|
while (currentScope !== scope && currentScope != null) {
|
1682
1668
|
currentScope = currentScope.upper;
|
1683
1669
|
}
|
1684
|
-
if (
|
1685
|
-
// This reference is outside the Hook callback.
|
1670
|
+
if (
|
1671
|
+
currentScope !== scope && // This reference is outside the Hook callback.
|
1686
1672
|
// It can only be legit if it's the deps array.
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1673
|
+
!isAncestorNodeOf(declaredDependenciesNode, reference.identifier)
|
1674
|
+
) {
|
1675
|
+
return true;
|
1690
1676
|
}
|
1691
1677
|
}
|
1692
1678
|
return false;
|
@@ -1837,11 +1823,11 @@ function getReactiveHookCallbackIndex(calleeNode, options) {
|
|
1837
1823
|
let name;
|
1838
1824
|
try {
|
1839
1825
|
name = analyzePropertyChain(node, null);
|
1840
|
-
} catch (
|
1841
|
-
if (/Unsupported node type/.test(
|
1826
|
+
} catch (err) {
|
1827
|
+
if (/Unsupported node type/.test(err.message)) {
|
1842
1828
|
return 0;
|
1843
1829
|
}
|
1844
|
-
throw
|
1830
|
+
throw err;
|
1845
1831
|
}
|
1846
1832
|
return options.additionalHooks.test(name) ? 0 : -1;
|
1847
1833
|
}
|
@@ -1863,7 +1849,7 @@ function fastFindReferenceWithParent(start, target) {
|
|
1863
1849
|
const queue = [start];
|
1864
1850
|
let item = null;
|
1865
1851
|
|
1866
|
-
while (queue.length) {
|
1852
|
+
while (queue.length > 0) {
|
1867
1853
|
item = queue.shift();
|
1868
1854
|
|
1869
1855
|
if (isSameIdentifier(item, target)) {
|
@@ -1882,7 +1868,7 @@ function fastFindReferenceWithParent(start, target) {
|
|
1882
1868
|
value.parent = item;
|
1883
1869
|
queue.push(value);
|
1884
1870
|
} else if (Array.isArray(value)) {
|
1885
|
-
// eslint-disable-next-line no-loop-func
|
1871
|
+
// eslint-disable-next-line no-loop-func -- FIXME
|
1886
1872
|
value.forEach(val => {
|
1887
1873
|
if (isNodeLike(val)) {
|
1888
1874
|
val.parent = item;
|
@@ -40,7 +40,7 @@ function* updateImportStatement(context, fixer, key) {
|
|
40
40
|
}
|
41
41
|
|
42
42
|
// Named imports section is present and current key is not imported yet - add it to named imports section
|
43
|
-
yield fixer.insertTextAfter(importNode.specifiers.
|
43
|
+
yield fixer.insertTextAfter([...importNode.specifiers].pop(), `, ${key}`);
|
44
44
|
}
|
45
45
|
|
46
46
|
/** @type {import('eslint').Rule.RuleModule} */
|
@@ -25,7 +25,6 @@ module.exports = {
|
|
25
25
|
function checkColorLiteral(value) {
|
26
26
|
if (value.type === 'Literal' && typeof value.value === 'string') {
|
27
27
|
const colorCodePattern =
|
28
|
-
// eslint-disable-next-line max-len
|
29
28
|
/#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
|
30
29
|
const isColorCode = colorCodePattern.test(value.value);
|
31
30
|
if (isColorCode) {
|
package/lib/util/intl.js
CHANGED
@@ -9,13 +9,13 @@ function findFormatMessageAttrNode(node, attrName) {
|
|
9
9
|
// Find formatMessage usages
|
10
10
|
if (
|
11
11
|
node.type === 'CallExpression' &&
|
12
|
-
(node.callee.name === 'formatMessage' || node.callee.name === '$t')
|
12
|
+
(node.callee.name === 'formatMessage' || node.callee.name === '$t') &&
|
13
|
+
node.arguments.length > 0 &&
|
14
|
+
node.arguments[0].properties
|
13
15
|
) {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
);
|
18
|
-
}
|
16
|
+
return node.arguments[0].properties.find(
|
17
|
+
a => a.key && a.key.name === attrName
|
18
|
+
);
|
19
19
|
}
|
20
20
|
|
21
21
|
// Find intl.formatMessage usages
|
package/lib/util/translations.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
const
|
3
|
-
const
|
4
|
-
const { tsImport } = require('./import');
|
1
|
+
const fs = require('node:fs');
|
2
|
+
const path = require('node:path');
|
3
|
+
const { tsImport } = require('@agilebot/eslint-utils');
|
5
4
|
const { getSetting } = require('./settings');
|
6
5
|
|
7
6
|
/**
|
package/lib/util/tss.js
CHANGED
@@ -12,7 +12,7 @@ function getBasicIdentifier(node) {
|
|
12
12
|
|
13
13
|
if (node.type === 'TemplateLiteral') {
|
14
14
|
// Handle template literals, e.g., classes[`foo`]
|
15
|
-
if (node.expressions.length) {
|
15
|
+
if (node.expressions.length > 0) {
|
16
16
|
// Template literals with expressions, e.g., classes[`foo${bar}`]
|
17
17
|
return null;
|
18
18
|
}
|
@@ -25,12 +25,17 @@ function getBasicIdentifier(node) {
|
|
25
25
|
|
26
26
|
// Helper function to recursively get the base identifier from a MemberExpression node
|
27
27
|
function getBaseIdentifier(node) {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
switch (node.type) {
|
29
|
+
case 'Identifier': {
|
30
|
+
return node;
|
31
|
+
}
|
32
|
+
case 'CallExpression': {
|
33
|
+
return getBaseIdentifier(node.callee);
|
34
|
+
}
|
35
|
+
case 'MemberExpression': {
|
36
|
+
return getBaseIdentifier(node.object);
|
37
|
+
}
|
38
|
+
// No default
|
34
39
|
}
|
35
40
|
return null;
|
36
41
|
}
|
package/package.json
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
{
|
2
2
|
"name": "@agilebot/eslint-plugin",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.4",
|
4
4
|
"description": "Agilebot's ESLint plugin",
|
5
5
|
"main": "lib",
|
6
6
|
"license": "MIT",
|
7
|
+
"keywords": [
|
8
|
+
"eslint",
|
9
|
+
"eslint-plugin"
|
10
|
+
],
|
7
11
|
"repository": {
|
8
12
|
"url": "sh-agilebot/frontend-toolkit",
|
9
13
|
"directory": "packages/eslint-plugin"
|
10
14
|
},
|
11
15
|
"homepage": "https://github.com/sh-agilebot/frontend-toolkit/tree/master/packages/eslint-plugin#readme",
|
16
|
+
"engines": {
|
17
|
+
"node": "^18.18.0 || >=20.0.0"
|
18
|
+
},
|
12
19
|
"dependencies": {
|
13
20
|
"@typescript-eslint/utils": "^7.1.1",
|
14
|
-
"
|
15
|
-
|
16
|
-
|
17
|
-
"
|
18
|
-
"sucrase": "^3.35.0"
|
21
|
+
"fast-glob": "^3.3.2"
|
22
|
+
},
|
23
|
+
"peerDependencies": {
|
24
|
+
"eslint": "^7.0.0 || ^8.0.0"
|
19
25
|
},
|
20
26
|
"files": [
|
21
27
|
"lib"
|
package/lib/util/import.js
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
const path = require('path');
|
2
|
-
const jiti = require('jiti');
|
3
|
-
const { transform } = require('sucrase');
|
4
|
-
const { getTsconfig } = require('get-tsconfig');
|
5
|
-
|
6
|
-
/**
|
7
|
-
* import ts module, like require, but support ts
|
8
|
-
* @param {*} modulePath - module path
|
9
|
-
*/
|
10
|
-
function tsImport(modulePath) {
|
11
|
-
if (!modulePath) {
|
12
|
-
return;
|
13
|
-
}
|
14
|
-
/** try to delete cache first */
|
15
|
-
try {
|
16
|
-
if (require.cache[modulePath]) {
|
17
|
-
delete require.cache[modulePath];
|
18
|
-
}
|
19
|
-
} catch (err) {
|
20
|
-
/* empty */
|
21
|
-
}
|
22
|
-
|
23
|
-
try {
|
24
|
-
return require(modulePath);
|
25
|
-
} catch (err) {
|
26
|
-
const tsconfig = getTsconfig(modulePath);
|
27
|
-
const { paths, baseUrl } = tsconfig.config.compilerOptions;
|
28
|
-
let basePath = path.dirname(tsconfig.path);
|
29
|
-
basePath = path.resolve(basePath, baseUrl);
|
30
|
-
|
31
|
-
const alias = resolveTsconfigPathsToAlias(paths, basePath);
|
32
|
-
|
33
|
-
return jiti(__filename, {
|
34
|
-
interopDefault: true,
|
35
|
-
cache: false,
|
36
|
-
debug: !!process.env.DEBUG,
|
37
|
-
transform: options => {
|
38
|
-
return transform(options.source, {
|
39
|
-
transforms: ['imports', 'typescript']
|
40
|
-
});
|
41
|
-
},
|
42
|
-
alias
|
43
|
-
})(modulePath);
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
/**
|
48
|
-
* Resolve tsconfig.json paths to Webpack aliases
|
49
|
-
* @param {string} paths - tsconfig.json paths
|
50
|
-
* @param {string} basePath - Path from tsconfig to Webpack config to create absolute aliases
|
51
|
-
* @return {object} - Webpack alias config
|
52
|
-
*/
|
53
|
-
function resolveTsconfigPathsToAlias(paths, basePath = __dirname) {
|
54
|
-
const aliases = {};
|
55
|
-
|
56
|
-
Object.keys(paths).forEach(item => {
|
57
|
-
const key = item.replace('/*', '');
|
58
|
-
const value = path.resolve(
|
59
|
-
basePath,
|
60
|
-
paths[item][0].replace('/*', '').replace('*', '')
|
61
|
-
);
|
62
|
-
|
63
|
-
aliases[key] = value;
|
64
|
-
});
|
65
|
-
|
66
|
-
return aliases;
|
67
|
-
}
|
68
|
-
|
69
|
-
module.exports = {
|
70
|
-
tsImport
|
71
|
-
};
|