@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 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 import, namespace export, named-as-default, and import cycle checks | ✅ | 🔧 | |
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: 120,
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': ['error', { 'prefer-inline': true }],
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-self-import': 'error',
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 && !checkNamedAsDefault) ||
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
- ExportAllDeclaration: checkImportCycle,
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
- MemberExpression: checkNamespaceMember,
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, and import/no-named-as-default checks',
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@taiga-ui/eslint-plugin-experience-next",
3
- "version": "0.502.0",
3
+ "version": "0.503.0",
4
4
  "description": "An ESLint plugin to enforce a consistent code styles across taiga-ui projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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
  ];