@taiga-ui/eslint-plugin-experience-next 0.502.0 → 0.503.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 +1 -1
- package/index.d.ts +4 -1
- package/index.esm.js +301 -11
- package/package.json +1 -1
- package/rules/recommended/import-integrity.d.ts +4 -1
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ from third-party plugins. The exact severities and file globs live in
|
|
|
80
80
|
| [flat-exports](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/flat-exports.md) | Spread nested arrays when exporting Angular entity collections | | 🔧 | |
|
|
81
81
|
| [host-attributes-sort](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/host-attributes-sort.md) | Sort Angular host metadata attributes using configurable attribute groups | ✅ | 🔧 | |
|
|
82
82
|
| [html-logical-properties](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/html-logical-properties.md) | Enforce logical CSS properties over directional ones in Angular template style bindings | ✅ | 🔧 | |
|
|
83
|
-
| [import-integrity](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/import-integrity.md) | Fast default
|
|
83
|
+
| [import-integrity](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/import-integrity.md) | Fast import default, namespace, cycle, duplicate, named-as-default, and self-import checks | ✅ | 🔧 | |
|
|
84
84
|
| [injection-token-description](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/injection-token-description.md) | Require `InjectionToken` descriptions to include the token name | ✅ | 🔧 | |
|
|
85
85
|
| [no-commonjs-import-patterns](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/no-commonjs-import-patterns.md) | Disallow legacy CommonJS interop import patterns | ✅ | | |
|
|
86
86
|
| [no-deep-imports](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/no-deep-imports.md) | Disables deep imports of Taiga UI packages | ✅ | 🔧 | |
|
package/index.d.ts
CHANGED
|
@@ -38,11 +38,14 @@ declare const plugin: {
|
|
|
38
38
|
'html-logical-properties': import("eslint").Rule.RuleModule & {
|
|
39
39
|
name: string;
|
|
40
40
|
};
|
|
41
|
-
'import-integrity': import("@typescript-eslint/utils/ts-eslint").RuleModule<"importCycle" | "missingDefaultExport" | "namedAsDefault" | "unknownNamespaceMember", [({
|
|
41
|
+
'import-integrity': import("@typescript-eslint/utils/ts-eslint").RuleModule<"duplicateImport" | "importCycle" | "missingDefaultExport" | "namedAsDefault" | "namedAsDefaultMember" | "selfImport" | "unknownNamespaceMember", [({
|
|
42
42
|
checkCycles?: boolean;
|
|
43
43
|
checkDefaultImports?: boolean;
|
|
44
|
+
checkDuplicateImports?: boolean;
|
|
44
45
|
checkNamedAsDefault?: boolean;
|
|
46
|
+
checkNamedAsDefaultMembers?: boolean;
|
|
45
47
|
checkNamespaceMembers?: boolean;
|
|
48
|
+
checkSelfImports?: boolean;
|
|
46
49
|
ignoreExternalDefaultImports?: boolean;
|
|
47
50
|
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
48
51
|
name: string;
|
package/index.esm.js
CHANGED
|
@@ -867,7 +867,7 @@ var recommended = defineConfig([
|
|
|
867
867
|
'error',
|
|
868
868
|
{
|
|
869
869
|
methods: 'above',
|
|
870
|
-
printWidth:
|
|
870
|
+
printWidth: 90,
|
|
871
871
|
properties: 'above',
|
|
872
872
|
},
|
|
873
873
|
],
|
|
@@ -875,19 +875,20 @@ var recommended = defineConfig([
|
|
|
875
875
|
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
|
876
876
|
'guard-for-in': 'error',
|
|
877
877
|
'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
|
|
878
|
-
'import/default': 'off',
|
|
878
|
+
'import/default': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
879
879
|
'import/enforce-node-protocol-usage': ['error', 'always'],
|
|
880
880
|
'import/export': 'off',
|
|
881
881
|
'import/first': 'error',
|
|
882
|
-
'import/namespace': 'off',
|
|
882
|
+
'import/namespace': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
883
883
|
'import/newline-after-import': ['error', { count: 1 }],
|
|
884
884
|
'import/no-absolute-path': 'error',
|
|
885
|
-
'import/no-cycle': 'off',
|
|
886
|
-
'import/no-duplicates':
|
|
885
|
+
'import/no-cycle': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
886
|
+
'import/no-duplicates': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
887
887
|
'import/no-extraneous-dependencies': 'off',
|
|
888
888
|
'import/no-mutable-exports': 'error',
|
|
889
|
-
'import/no-named-as-default': 'off',
|
|
890
|
-
'import/no-
|
|
889
|
+
'import/no-named-as-default': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
890
|
+
'import/no-named-as-default-member': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
891
|
+
'import/no-self-import': 'off', // Covered by @taiga-ui/experience-next/import-integrity.
|
|
891
892
|
'import/no-unresolved': 'off',
|
|
892
893
|
'import/no-useless-path-segments': ['error', { noUselessIndex: true }],
|
|
893
894
|
'import/no-webpack-loader-syntax': 'error',
|
|
@@ -247753,6 +247754,56 @@ function resolveModuleFileName(program, containingFile, moduleSpecifier) {
|
|
|
247753
247754
|
}
|
|
247754
247755
|
return resolved.resolvedFileName;
|
|
247755
247756
|
}
|
|
247757
|
+
function getModuleSpecifierPath(moduleSpecifier) {
|
|
247758
|
+
const queryIndex = moduleSpecifier.indexOf('?');
|
|
247759
|
+
return queryIndex === -1 ? moduleSpecifier : moduleSpecifier.slice(0, queryIndex);
|
|
247760
|
+
}
|
|
247761
|
+
function resolveModuleKey(program, containingFile, moduleSpecifier, canonicalFileName) {
|
|
247762
|
+
const moduleSpecifierPath = getModuleSpecifierPath(moduleSpecifier);
|
|
247763
|
+
const resolved = resolveModule(program, containingFile, moduleSpecifierPath);
|
|
247764
|
+
if (!resolved) {
|
|
247765
|
+
return moduleSpecifier;
|
|
247766
|
+
}
|
|
247767
|
+
const queryIndex = moduleSpecifier.indexOf('?');
|
|
247768
|
+
const query = queryIndex === -1 ? '' : moduleSpecifier.slice(queryIndex);
|
|
247769
|
+
return `${canonicalFileName(resolved.resolvedFileName)}${query}`;
|
|
247770
|
+
}
|
|
247771
|
+
function getDefaultImportName(node) {
|
|
247772
|
+
const defaultImport = node.specifiers.find((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportDefaultSpecifier);
|
|
247773
|
+
return defaultImport?.local.name ?? null;
|
|
247774
|
+
}
|
|
247775
|
+
function hasNamespaceImport(node) {
|
|
247776
|
+
return node.specifiers.some((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportNamespaceSpecifier);
|
|
247777
|
+
}
|
|
247778
|
+
function hasTypeOnlyDefaultImport(node) {
|
|
247779
|
+
return node.importKind === 'type' && getDefaultImportName(node) !== null;
|
|
247780
|
+
}
|
|
247781
|
+
function hasImportAttributes(node) {
|
|
247782
|
+
const record = node;
|
|
247783
|
+
const attributes = record['attributes'];
|
|
247784
|
+
const assertions = record['assertions'];
|
|
247785
|
+
return ((Array.isArray(attributes) && attributes.length > 0) ||
|
|
247786
|
+
(Array.isArray(assertions) && assertions.length > 0));
|
|
247787
|
+
}
|
|
247788
|
+
function hasProblematicImportComments(node, sourceCode) {
|
|
247789
|
+
const text = sourceCode.getText(node);
|
|
247790
|
+
return (text.includes('/*') ||
|
|
247791
|
+
text.includes('//') ||
|
|
247792
|
+
sourceCode
|
|
247793
|
+
.getCommentsBefore(node)
|
|
247794
|
+
.some((comment) => comment.loc.end.line >= node.loc.start.line - 1) ||
|
|
247795
|
+
sourceCode
|
|
247796
|
+
.getCommentsAfter(node)
|
|
247797
|
+
.some((comment) => comment.loc.start.line === node.loc.end.line));
|
|
247798
|
+
}
|
|
247799
|
+
function getNamedSpecifierText(node, specifier, sourceCode) {
|
|
247800
|
+
const text = sourceCode.getText(specifier);
|
|
247801
|
+
const isTypeOnly = node.importKind === 'type' || specifier.importKind === 'type';
|
|
247802
|
+
return isTypeOnly && !text.trimStart().startsWith('type ') ? `type ${text}` : text;
|
|
247803
|
+
}
|
|
247804
|
+
function getNamedSpecifierKey(text) {
|
|
247805
|
+
return text.trim().replace(/^type\s+/, '');
|
|
247806
|
+
}
|
|
247756
247807
|
function importDeclarationHasRuntimeEdge(node) {
|
|
247757
247808
|
const importClause = node.importClause;
|
|
247758
247809
|
if (!importClause) {
|
|
@@ -248250,12 +248301,167 @@ const rule$K = createRule({
|
|
|
248250
248301
|
const { checker, esTreeNodeToTSNodeMap, sourceCode, tsProgram } = getTypeAwareRuleContext(context);
|
|
248251
248302
|
const checkCycles = context.options[0]?.checkCycles ?? true;
|
|
248252
248303
|
const checkDefaultImports = context.options[0]?.checkDefaultImports ?? true;
|
|
248304
|
+
const checkDuplicateImports = context.options[0]?.checkDuplicateImports ?? true;
|
|
248253
248305
|
const checkNamedAsDefault = context.options[0]?.checkNamedAsDefault ?? true;
|
|
248306
|
+
const checkNamedAsDefaultMembers = context.options[0]?.checkNamedAsDefaultMembers ?? true;
|
|
248254
248307
|
const checkNamespaceMembers = context.options[0]?.checkNamespaceMembers ?? true;
|
|
248308
|
+
const checkSelfImports = context.options[0]?.checkSelfImports ?? true;
|
|
248255
248309
|
const ignoreExternalDefaultImports = context.options[0]?.ignoreExternalDefaultImports ?? true;
|
|
248256
248310
|
const canonicalFileName = createCanonicalFileName();
|
|
248257
248311
|
const currentFileName = canonicalFileName(context.filename);
|
|
248312
|
+
const defaultImports = new Map();
|
|
248313
|
+
const duplicateImportMaps = {
|
|
248314
|
+
importsByModule: new Map(),
|
|
248315
|
+
namespaceImportsByModule: new Map(),
|
|
248316
|
+
};
|
|
248258
248317
|
const namespaceImports = new Map();
|
|
248318
|
+
function getDuplicateImportMap(node) {
|
|
248319
|
+
return hasNamespaceImport(node)
|
|
248320
|
+
? duplicateImportMaps.namespaceImportsByModule
|
|
248321
|
+
: duplicateImportMaps.importsByModule;
|
|
248322
|
+
}
|
|
248323
|
+
function collectDuplicateImport(node) {
|
|
248324
|
+
if (!checkDuplicateImports) {
|
|
248325
|
+
return;
|
|
248326
|
+
}
|
|
248327
|
+
const moduleKey = resolveModuleKey(tsProgram, context.filename, node.source.value, canonicalFileName);
|
|
248328
|
+
const importsByModule = getDuplicateImportMap(node);
|
|
248329
|
+
const imports = importsByModule.get(moduleKey) ?? [];
|
|
248330
|
+
imports.push(node);
|
|
248331
|
+
importsByModule.set(moduleKey, imports);
|
|
248332
|
+
}
|
|
248333
|
+
function buildImportRemovalFix(fixer, node) {
|
|
248334
|
+
const [start, end] = node.range;
|
|
248335
|
+
const lineStart = sourceCode.text.lastIndexOf('\n', start - 1) + 1;
|
|
248336
|
+
const removeStart = /^\s*$/.test(sourceCode.text.slice(lineStart, start))
|
|
248337
|
+
? lineStart
|
|
248338
|
+
: start;
|
|
248339
|
+
const removeEnd = sourceCode.text[end] === '\n' ? end + 1 : end;
|
|
248340
|
+
return [fixer.removeRange([removeStart, removeEnd])];
|
|
248341
|
+
}
|
|
248342
|
+
function buildDuplicateImportFix(fixer, first, rest) {
|
|
248343
|
+
const nodes = [first, ...rest];
|
|
248344
|
+
if (nodes.some((node) => hasNamespaceImport(node) ||
|
|
248345
|
+
hasTypeOnlyDefaultImport(node) ||
|
|
248346
|
+
hasImportAttributes(node) ||
|
|
248347
|
+
hasProblematicImportComments(node, sourceCode))) {
|
|
248348
|
+
return null;
|
|
248349
|
+
}
|
|
248350
|
+
const defaultNames = new Set(nodes.flatMap((node) => {
|
|
248351
|
+
const name = getDefaultImportName(node);
|
|
248352
|
+
return name ? [name] : [];
|
|
248353
|
+
}));
|
|
248354
|
+
if (defaultNames.size > 1) {
|
|
248355
|
+
return null;
|
|
248356
|
+
}
|
|
248357
|
+
const namedSpecifiersByKey = new Map();
|
|
248358
|
+
for (const node of nodes) {
|
|
248359
|
+
for (const specifier of node.specifiers) {
|
|
248360
|
+
if (specifier.type !== dist$3.AST_NODE_TYPES.ImportSpecifier) {
|
|
248361
|
+
continue;
|
|
248362
|
+
}
|
|
248363
|
+
const text = getNamedSpecifierText(node, specifier, sourceCode).trim();
|
|
248364
|
+
const key = getNamedSpecifierKey(text);
|
|
248365
|
+
const existing = namedSpecifiersByKey.get(key);
|
|
248366
|
+
const isTypeOnly = text.startsWith('type ');
|
|
248367
|
+
if (!existing || (existing.startsWith('type ') && !isTypeOnly)) {
|
|
248368
|
+
namedSpecifiersByKey.set(key, text);
|
|
248369
|
+
}
|
|
248370
|
+
}
|
|
248371
|
+
}
|
|
248372
|
+
const namedSpecifiers = [...namedSpecifiersByKey.values()];
|
|
248373
|
+
const [defaultName = null] = defaultNames;
|
|
248374
|
+
const bindings = [
|
|
248375
|
+
...(defaultName ? [defaultName] : []),
|
|
248376
|
+
...(namedSpecifiers.length > 0
|
|
248377
|
+
? [`{${namedSpecifiers.join(', ')}}`]
|
|
248378
|
+
: []),
|
|
248379
|
+
];
|
|
248380
|
+
const sourceText = sourceCode.getText(first.source);
|
|
248381
|
+
const semi = sourceCode.getText(first).endsWith(';') ? ';' : '';
|
|
248382
|
+
const replacement = bindings.length === 0
|
|
248383
|
+
? `import ${sourceText}${semi}`
|
|
248384
|
+
: `import ${bindings.join(', ')} from ${sourceText}${semi}`;
|
|
248385
|
+
return [
|
|
248386
|
+
fixer.replaceText(first, replacement),
|
|
248387
|
+
...rest.flatMap((node) => buildImportRemovalFix(fixer, node)),
|
|
248388
|
+
];
|
|
248389
|
+
}
|
|
248390
|
+
function reportDuplicateImports(importsByModule) {
|
|
248391
|
+
for (const nodes of importsByModule.values()) {
|
|
248392
|
+
if (nodes.length < 2) {
|
|
248393
|
+
continue;
|
|
248394
|
+
}
|
|
248395
|
+
const [first, ...rest] = nodes;
|
|
248396
|
+
if (!first) {
|
|
248397
|
+
continue;
|
|
248398
|
+
}
|
|
248399
|
+
const moduleSpecifier = first.source.value;
|
|
248400
|
+
context.report({
|
|
248401
|
+
data: { moduleSpecifier },
|
|
248402
|
+
fix: (fixer) => buildDuplicateImportFix(fixer, first, rest),
|
|
248403
|
+
messageId: 'duplicateImport',
|
|
248404
|
+
node: first.source,
|
|
248405
|
+
});
|
|
248406
|
+
for (const node of rest) {
|
|
248407
|
+
context.report({
|
|
248408
|
+
data: { moduleSpecifier },
|
|
248409
|
+
messageId: 'duplicateImport',
|
|
248410
|
+
node: node.source,
|
|
248411
|
+
});
|
|
248412
|
+
}
|
|
248413
|
+
}
|
|
248414
|
+
}
|
|
248415
|
+
function reportAllDuplicateImports() {
|
|
248416
|
+
if (!checkDuplicateImports) {
|
|
248417
|
+
return;
|
|
248418
|
+
}
|
|
248419
|
+
reportDuplicateImports(duplicateImportMaps.importsByModule);
|
|
248420
|
+
reportDuplicateImports(duplicateImportMaps.namespaceImportsByModule);
|
|
248421
|
+
}
|
|
248422
|
+
function checkSelfImport(moduleSpecifier, node) {
|
|
248423
|
+
if (!checkSelfImports ||
|
|
248424
|
+
context.filename === '<text>' ||
|
|
248425
|
+
moduleSpecifier.includes('?')) {
|
|
248426
|
+
return;
|
|
248427
|
+
}
|
|
248428
|
+
const resolved = resolveModule(tsProgram, context.filename, getModuleSpecifierPath(moduleSpecifier));
|
|
248429
|
+
if (!resolved ||
|
|
248430
|
+
canonicalFileName(resolved.resolvedFileName) !== currentFileName) {
|
|
248431
|
+
return;
|
|
248432
|
+
}
|
|
248433
|
+
context.report({
|
|
248434
|
+
messageId: 'selfImport',
|
|
248435
|
+
node,
|
|
248436
|
+
});
|
|
248437
|
+
}
|
|
248438
|
+
function checkDeclarationSelfImport(node) {
|
|
248439
|
+
if (!node.source || typeof node.source.value !== 'string') {
|
|
248440
|
+
return;
|
|
248441
|
+
}
|
|
248442
|
+
checkSelfImport(node.source.value, node.source);
|
|
248443
|
+
}
|
|
248444
|
+
function checkRequireSelfImport(node) {
|
|
248445
|
+
if (node.callee.type !== dist$3.AST_NODE_TYPES.Identifier ||
|
|
248446
|
+
node.callee.name !== 'require' ||
|
|
248447
|
+
node.arguments.length !== 1) {
|
|
248448
|
+
return;
|
|
248449
|
+
}
|
|
248450
|
+
const [moduleSpecifier] = node.arguments;
|
|
248451
|
+
if (moduleSpecifier?.type !== dist$3.AST_NODE_TYPES.Literal ||
|
|
248452
|
+
typeof moduleSpecifier.value !== 'string') {
|
|
248453
|
+
return;
|
|
248454
|
+
}
|
|
248455
|
+
checkSelfImport(moduleSpecifier.value, moduleSpecifier);
|
|
248456
|
+
}
|
|
248457
|
+
function checkDynamicSelfImport(node) {
|
|
248458
|
+
const { source } = node;
|
|
248459
|
+
if (source.type !== dist$3.AST_NODE_TYPES.Literal ||
|
|
248460
|
+
typeof source.value !== 'string') {
|
|
248461
|
+
return;
|
|
248462
|
+
}
|
|
248463
|
+
checkSelfImport(source.value, source);
|
|
248464
|
+
}
|
|
248259
248465
|
function checkImportCycle(node) {
|
|
248260
248466
|
if (!checkCycles) {
|
|
248261
248467
|
return;
|
|
@@ -248377,7 +248583,9 @@ const rule$K = createRule({
|
|
|
248377
248583
|
return newImports.join('\n');
|
|
248378
248584
|
}
|
|
248379
248585
|
function checkDefaultImport(node) {
|
|
248380
|
-
if ((!checkDefaultImports &&
|
|
248586
|
+
if ((!checkDefaultImports &&
|
|
248587
|
+
!checkNamedAsDefault &&
|
|
248588
|
+
!checkNamedAsDefaultMembers) ||
|
|
248381
248589
|
node.importKind === 'type') {
|
|
248382
248590
|
return;
|
|
248383
248591
|
}
|
|
@@ -248404,6 +248612,17 @@ const rule$K = createRule({
|
|
|
248404
248612
|
return;
|
|
248405
248613
|
}
|
|
248406
248614
|
const exportNames = getNamespaceImportExportNames(checker, esTreeNodeToTSNodeMap, node);
|
|
248615
|
+
if (checkNamedAsDefaultMembers && exportNames) {
|
|
248616
|
+
const [variable] = sourceCode.getDeclaredVariables(defaultImport);
|
|
248617
|
+
if (variable) {
|
|
248618
|
+
defaultImports.set(defaultImport.local.name, {
|
|
248619
|
+
exportNames,
|
|
248620
|
+
moduleSpecifier,
|
|
248621
|
+
node: defaultImport,
|
|
248622
|
+
variable,
|
|
248623
|
+
});
|
|
248624
|
+
}
|
|
248625
|
+
}
|
|
248407
248626
|
if (!checkNamedAsDefault ||
|
|
248408
248627
|
!hasNamedValueExport(exportNames, defaultImport.local.name)) {
|
|
248409
248628
|
return;
|
|
@@ -248414,6 +248633,49 @@ const rule$K = createRule({
|
|
|
248414
248633
|
node: defaultImport,
|
|
248415
248634
|
});
|
|
248416
248635
|
}
|
|
248636
|
+
function reportNamedAsDefaultMember(defaultImportIdentifier, memberName, reportNode) {
|
|
248637
|
+
if (!checkNamedAsDefaultMembers || !memberName || memberName === 'default') {
|
|
248638
|
+
return;
|
|
248639
|
+
}
|
|
248640
|
+
const usage = defaultImports.get(defaultImportIdentifier.name);
|
|
248641
|
+
if (!usage ||
|
|
248642
|
+
!hasNamedValueExport(usage.exportNames, memberName) ||
|
|
248643
|
+
getResolvedVariable(sourceCode, defaultImportIdentifier) !==
|
|
248644
|
+
usage.variable) {
|
|
248645
|
+
return;
|
|
248646
|
+
}
|
|
248647
|
+
context.report({
|
|
248648
|
+
data: {
|
|
248649
|
+
defaultName: usage.node.local.name,
|
|
248650
|
+
memberName,
|
|
248651
|
+
moduleSpecifier: usage.moduleSpecifier,
|
|
248652
|
+
},
|
|
248653
|
+
messageId: 'namedAsDefaultMember',
|
|
248654
|
+
node: reportNode,
|
|
248655
|
+
});
|
|
248656
|
+
}
|
|
248657
|
+
function checkNamedAsDefaultMemberExpression(node) {
|
|
248658
|
+
if (!checkNamedAsDefaultMembers ||
|
|
248659
|
+
defaultImports.size === 0 ||
|
|
248660
|
+
node.object.type !== dist$3.AST_NODE_TYPES.Identifier) {
|
|
248661
|
+
return;
|
|
248662
|
+
}
|
|
248663
|
+
reportNamedAsDefaultMember(node.object, getMemberExpressionPropertyName(node), node.property);
|
|
248664
|
+
}
|
|
248665
|
+
function checkNamedAsDefaultMemberDestructuring(node) {
|
|
248666
|
+
if (!checkNamedAsDefaultMembers ||
|
|
248667
|
+
defaultImports.size === 0 ||
|
|
248668
|
+
node.id.type !== dist$3.AST_NODE_TYPES.ObjectPattern ||
|
|
248669
|
+
node.init?.type !== dist$3.AST_NODE_TYPES.Identifier) {
|
|
248670
|
+
return;
|
|
248671
|
+
}
|
|
248672
|
+
for (const property of node.id.properties) {
|
|
248673
|
+
if (property.type !== dist$3.AST_NODE_TYPES.Property) {
|
|
248674
|
+
continue;
|
|
248675
|
+
}
|
|
248676
|
+
reportNamedAsDefaultMember(node.init, getObjectPropertyName(property), property.key);
|
|
248677
|
+
}
|
|
248678
|
+
}
|
|
248417
248679
|
function checkNamedAsDefaultExport(node) {
|
|
248418
248680
|
if (!checkNamedAsDefault ||
|
|
248419
248681
|
node.exportKind === 'type' ||
|
|
@@ -248529,28 +248791,44 @@ const rule$K = createRule({
|
|
|
248529
248791
|
});
|
|
248530
248792
|
}
|
|
248531
248793
|
return {
|
|
248532
|
-
|
|
248794
|
+
CallExpression: checkRequireSelfImport,
|
|
248795
|
+
ExportAllDeclaration(node) {
|
|
248796
|
+
checkImportCycle(node);
|
|
248797
|
+
checkDeclarationSelfImport(node);
|
|
248798
|
+
},
|
|
248533
248799
|
ExportNamedDeclaration(node) {
|
|
248534
248800
|
checkImportCycle(node);
|
|
248801
|
+
checkDeclarationSelfImport(node);
|
|
248535
248802
|
checkNamedAsDefaultExport(node);
|
|
248536
248803
|
},
|
|
248537
248804
|
ImportDeclaration(node) {
|
|
248538
248805
|
checkImportCycle(node);
|
|
248806
|
+
checkDeclarationSelfImport(node);
|
|
248807
|
+
collectDuplicateImport(node);
|
|
248539
248808
|
checkDefaultImport(node);
|
|
248540
248809
|
collectNamespaceImport(node);
|
|
248541
248810
|
},
|
|
248542
|
-
|
|
248811
|
+
ImportExpression: checkDynamicSelfImport,
|
|
248812
|
+
MemberExpression(node) {
|
|
248813
|
+
checkNamedAsDefaultMemberExpression(node);
|
|
248814
|
+
checkNamespaceMember(node);
|
|
248815
|
+
},
|
|
248816
|
+
'Program:exit': reportAllDuplicateImports,
|
|
248817
|
+
VariableDeclarator: checkNamedAsDefaultMemberDestructuring,
|
|
248543
248818
|
};
|
|
248544
248819
|
},
|
|
248545
248820
|
meta: {
|
|
248546
248821
|
docs: {
|
|
248547
|
-
description: 'Fast replacement for import/default, import/namespace, import/no-cycle,
|
|
248822
|
+
description: 'Fast replacement for import/default, import/namespace, import/no-cycle, import/no-duplicates, import/no-named-as-default, import/no-named-as-default-member, and import/no-self-import checks',
|
|
248548
248823
|
},
|
|
248549
248824
|
fixable: 'code',
|
|
248550
248825
|
messages: {
|
|
248826
|
+
duplicateImport: '"{{moduleSpecifier}}" imported multiple times.',
|
|
248551
248827
|
importCycle: 'Import cycle detected: {{cyclePath}}.',
|
|
248552
248828
|
missingDefaultExport: 'No default export found in "{{moduleSpecifier}}".',
|
|
248553
248829
|
namedAsDefault: 'Using exported name "{{name}}" as identifier for default export.',
|
|
248830
|
+
namedAsDefaultMember: 'Default import "{{defaultName}}" from "{{moduleSpecifier}}" also has a named export "{{memberName}}". Use a named import instead.',
|
|
248831
|
+
selfImport: 'Module imports itself.',
|
|
248554
248832
|
unknownNamespaceMember: 'Namespace import "{{namespaceName}}" from "{{moduleSpecifier}}" has no exported member "{{memberName}}".',
|
|
248555
248833
|
},
|
|
248556
248834
|
schema: [
|
|
@@ -248565,14 +248843,26 @@ const rule$K = createRule({
|
|
|
248565
248843
|
description: 'Report default imports from modules without a default export. Defaults to true.',
|
|
248566
248844
|
type: 'boolean',
|
|
248567
248845
|
},
|
|
248846
|
+
checkDuplicateImports: {
|
|
248847
|
+
description: 'Report repeated import declarations for the same resolved module. Defaults to true.',
|
|
248848
|
+
type: 'boolean',
|
|
248849
|
+
},
|
|
248568
248850
|
checkNamedAsDefault: {
|
|
248569
248851
|
description: 'Report default imports and default re-exports named after a named export from the same module. Defaults to true.',
|
|
248570
248852
|
type: 'boolean',
|
|
248571
248853
|
},
|
|
248854
|
+
checkNamedAsDefaultMembers: {
|
|
248855
|
+
description: 'Report property access or destructuring of default imports when the property name is a named export from the same module. Defaults to true.',
|
|
248856
|
+
type: 'boolean',
|
|
248857
|
+
},
|
|
248572
248858
|
checkNamespaceMembers: {
|
|
248573
248859
|
description: 'Report static namespace import member accesses that are not exported by the imported module. Defaults to true.',
|
|
248574
248860
|
type: 'boolean',
|
|
248575
248861
|
},
|
|
248862
|
+
checkSelfImports: {
|
|
248863
|
+
description: 'Report imports, re-exports, dynamic imports, and require() calls that resolve to the current file. Defaults to true.',
|
|
248864
|
+
type: 'boolean',
|
|
248865
|
+
},
|
|
248576
248866
|
ignoreExternalDefaultImports: {
|
|
248577
248867
|
description: 'Skip default import checks for modules resolved from external libraries. Defaults to true.',
|
|
248578
248868
|
type: 'boolean',
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
-
type MessageId = 'importCycle' | 'missingDefaultExport' | 'namedAsDefault' | 'unknownNamespaceMember';
|
|
2
|
+
type MessageId = 'duplicateImport' | 'importCycle' | 'missingDefaultExport' | 'namedAsDefault' | 'namedAsDefaultMember' | 'selfImport' | 'unknownNamespaceMember';
|
|
3
3
|
type Options = [
|
|
4
4
|
{
|
|
5
5
|
checkCycles?: boolean;
|
|
6
6
|
checkDefaultImports?: boolean;
|
|
7
|
+
checkDuplicateImports?: boolean;
|
|
7
8
|
checkNamedAsDefault?: boolean;
|
|
9
|
+
checkNamedAsDefaultMembers?: boolean;
|
|
8
10
|
checkNamespaceMembers?: boolean;
|
|
11
|
+
checkSelfImports?: boolean;
|
|
9
12
|
ignoreExternalDefaultImports?: boolean;
|
|
10
13
|
}?
|
|
11
14
|
];
|