From 272baca85abb95aa275278b0dc265e01c33d647d Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Thu, 23 Jan 2025 01:49:18 +0900 Subject: [PATCH 1/4] fix(eslint-plugin): [no-restricted-imports] support regex option --- .../src/rules/no-restricted-imports.ts | 27 ++++++++---- .../tests/rules/no-restricted-imports.test.ts | 42 +++++++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 3 +- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-restricted-imports.ts b/packages/eslint-plugin/src/rules/no-restricted-imports.ts index e8550856c2c2..8fd81eb7c811 100644 --- a/packages/eslint-plugin/src/rules/no-restricted-imports.ts +++ b/packages/eslint-plugin/src/rules/no-restricted-imports.ts @@ -267,24 +267,37 @@ export default createRule({ const restrictedPatterns = getRestrictedPatterns(options); const allowedImportTypeMatchers: Ignore[] = []; + const allowedImportTypeRegexMatchers: RegExp[] = []; for (const restrictedPattern of restrictedPatterns) { if ( typeof restrictedPattern === 'object' && restrictedPattern.allowTypeImports ) { // Following how ignore is configured in the base rule - allowedImportTypeMatchers.push( - ignore({ - allowRelativePaths: true, - ignoreCase: !restrictedPattern.caseSensitive, - }).add(restrictedPattern.group), - ); + restrictedPattern.group && + allowedImportTypeMatchers.push( + ignore({ + allowRelativePaths: true, + ignoreCase: !restrictedPattern.caseSensitive, + }).add(restrictedPattern.group), + ); + if (restrictedPattern.regex) { + allowedImportTypeRegexMatchers.push( + new RegExp( + restrictedPattern.regex, + restrictedPattern.caseSensitive ? 'u' : 'iu', + ), + ); + } } } function isAllowedTypeImportPattern(importSource: string): boolean { return ( // As long as there's one matching pattern that allows type import - allowedImportTypeMatchers.some(matcher => matcher.ignores(importSource)) + allowedImportTypeMatchers.some(matcher => + matcher.ignores(importSource), + ) || + allowedImportTypeRegexMatchers.some(regex => regex.test(importSource)) ); } diff --git a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts index 5640f285264f..b0c83aa7fc9e 100644 --- a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts +++ b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts @@ -290,6 +290,28 @@ import type { foo } from 'import2/private/bar'; }, ], }, + { + code: ` +import type { foo } from 'import1/private/bar'; +import type { foo } from 'import2/private/bar'; + `, + options: [ + { + patterns: [ + { + allowTypeImports: true, + regex: 'import1/.*', + message: 'usage of import1 private modules not allowed.', + }, + { + allowTypeImports: true, + regex: 'import2/.*', + message: 'usage of import2 private modules not allowed.', + }, + ], + }, + ], + }, { code: "import { type Bar } from 'import-foo';", options: [ @@ -722,6 +744,26 @@ import type { foo } from 'import2/private/bar'; }, ], }, + { + code: "export { foo } from 'import1/private/bar';", + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + options: [ + { + patterns: [ + { + allowTypeImports: true, + regex: 'import1/.*', + message: 'usage of import1 private modules not allowed.', + }, + ], + }, + ], + }, { code: "export * from 'import1';", errors: [ diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 6632125e3b15..970839e19c01 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -558,7 +558,8 @@ declare module 'eslint/lib/rules/no-restricted-imports' { // extended allowTypeImports?: boolean; caseSensitive?: boolean; - group: string[]; + group?: string[]; + regex?: string; message?: string; }[] | string[]; From 9f514bba638f92474717dd73731dc1dc23976cec Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Thu, 23 Jan 2025 01:50:33 +0900 Subject: [PATCH 2/4] Update no-restricted-imports.ts --- packages/eslint-plugin/src/rules/no-restricted-imports.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-restricted-imports.ts b/packages/eslint-plugin/src/rules/no-restricted-imports.ts index 8fd81eb7c811..d22f9b5d058f 100644 --- a/packages/eslint-plugin/src/rules/no-restricted-imports.ts +++ b/packages/eslint-plugin/src/rules/no-restricted-imports.ts @@ -274,13 +274,14 @@ export default createRule({ restrictedPattern.allowTypeImports ) { // Following how ignore is configured in the base rule - restrictedPattern.group && + if (restrictedPattern.group) { allowedImportTypeMatchers.push( ignore({ allowRelativePaths: true, ignoreCase: !restrictedPattern.caseSensitive, }).add(restrictedPattern.group), ); + } if (restrictedPattern.regex) { allowedImportTypeRegexMatchers.push( new RegExp( From bd8f96900d99efeee64acbbe8ff5d3aa285fde3d Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Thu, 23 Jan 2025 02:16:55 +0900 Subject: [PATCH 3/4] fixup --- .../tests/rules/no-restricted-imports.test.ts | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts index b0c83aa7fc9e..355c9df825a3 100644 --- a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts +++ b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts @@ -283,7 +283,7 @@ import type { foo } from 'import2/private/bar'; }, { allowTypeImports: true, - group: ['import2/private/*'], + group: ['import/private/*'], message: 'usage of import2 private modules not allowed.', }, ], @@ -300,13 +300,28 @@ import type { foo } from 'import2/private/bar'; patterns: [ { allowTypeImports: true, - regex: 'import1/.*', message: 'usage of import1 private modules not allowed.', + regex: 'import1/.*', }, { allowTypeImports: true, - regex: 'import2/.*', message: 'usage of import2 private modules not allowed.', + regex: 'import2/.*', + }, + ], + }, + ], + }, + { + code: "import { foo } from 'import1/private';", + options: [ + { + patterns: [ + { + allowTypeImports: true, + caseSensitive: true, + message: 'usage of import1 private modules not allowed.', + regex: 'import1/[A-Z]+', }, ], }, @@ -757,8 +772,29 @@ import type { foo } from 'import2/private/bar'; patterns: [ { allowTypeImports: true, + message: 'usage of import1 private modules not allowed.', regex: 'import1/.*', + }, + ], + }, + ], + }, + { + code: "import { foo } from 'import1/private-package';", + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + options: [ + { + patterns: [ + { + allowTypeImports: true, + caseSensitive: true, message: 'usage of import1 private modules not allowed.', + regex: 'import1/private-[a-z]*', }, ], }, From de7dd870716021269dcd21663942160b6d852e21 Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Thu, 23 Jan 2025 02:18:40 +0900 Subject: [PATCH 4/4] Update no-restricted-imports.test.ts --- .../eslint-plugin/tests/rules/no-restricted-imports.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts index 355c9df825a3..b43a52ef8d71 100644 --- a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts +++ b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts @@ -283,7 +283,7 @@ import type { foo } from 'import2/private/bar'; }, { allowTypeImports: true, - group: ['import/private/*'], + group: ['import2/private/*'], message: 'usage of import2 private modules not allowed.', }, ],