@@ -8,9 +8,13 @@ import type {
88 Options ,
99 Group ,
1010} from './sort-imports/types'
11- import type { DeprecatedCustomGroupsOption } from '../types/common-options'
11+ import type {
12+ DeprecatedCustomGroupsOption ,
13+ CustomGroupsOption ,
14+ } from '../types/common-options'
1215
1316import {
17+ buildCustomGroupsArrayJsonSchema ,
1418 partitionByCommentJsonSchema ,
1519 partitionByNewLineJsonSchema ,
1620 newlinesBetweenJsonSchema ,
@@ -25,8 +29,10 @@ import {
2529 ORDER_ERROR ,
2630} from '../utils/report-errors'
2731import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
32+ import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
2833import { validateSideEffectsConfiguration } from './sort-imports/validate-side-effects-configuration'
2934import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
35+ import { getCustomGroupOverriddenOptions } from '../utils/get-custom-groups-compare-options'
3036import { readClosestTsConfigByPath } from './sort-imports/read-closest-ts-config-by-path'
3137import { validateGroupsConfiguration } from '../utils/validate-groups-configuration'
3238import { getOptionsWithCleanGroups } from '../utils/get-options-with-clean-groups'
@@ -35,8 +41,12 @@ import { isSideEffectOnlyGroup } from './sort-imports/is-side-effect-only-group'
3541import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
3642import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
3743import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
44+ import { doesCustomGroupMatch } from '../utils/does-custom-group-match'
45+ import { singleCustomGroupJsonSchema } from './sort-imports/types'
3846import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
47+ import { allModifiers , allSelectors } from './sort-imports/types'
3948import { createEslintRule } from '../utils/create-eslint-rule'
49+ import { allDeprecatedSelectors } from './sort-imports/types'
4050import { reportAllErrors } from '../utils/report-all-errors'
4151import { shouldPartition } from '../utils/should-partition'
4252import { computeGroup } from '../utils/compute-group'
@@ -89,32 +99,34 @@ export default createEslintRule<Options, MESSAGE_ID>({
8999 } as const ) ,
90100 )
91101
92- validateGroupsConfiguration ( {
93- allowedPredefinedGroups : [
94- 'side-effect-style' ,
95- 'external-type' ,
96- 'internal-type' ,
97- 'builtin-type' ,
98- 'sibling-type' ,
99- 'parent-type' ,
100- 'side-effect' ,
101- 'index-type' ,
102- 'internal' ,
103- 'external' ,
104- 'sibling' ,
105- 'unknown' ,
106- 'builtin' ,
107- 'parent' ,
108- 'index' ,
109- 'style' ,
110- 'type' ,
111- ] ,
112- allowedCustomGroups : [
113- ...Object . keys ( options . customGroups . type ?? { } ) ,
114- ...Object . keys ( options . customGroups . value ?? { } ) ,
115- ] ,
116- options,
117- } )
102+ if ( Array . isArray ( options . customGroups ) ) {
103+ validateGeneratedGroupsConfiguration ( {
104+ options : {
105+ ...options ,
106+ customGroups : options . customGroups ,
107+ } ,
108+ selectors : allSelectors ,
109+ modifiers : allModifiers ,
110+ } )
111+ } else {
112+ let generatedGroups = generatePredefinedGroups ( {
113+ cache : cachedGroupsByModifiersAndSelectors ,
114+ selectors : allSelectors ,
115+ modifiers : allModifiers ,
116+ } )
117+ validateGroupsConfiguration ( {
118+ allowedCustomGroups : [
119+ ...Object . keys ( options . customGroups . type ?? { } ) ,
120+ ...Object . keys ( options . customGroups . value ?? { } ) ,
121+ ] ,
122+ allowedPredefinedGroups : [
123+ ...generatedGroups ,
124+ ...allDeprecatedSelectors ,
125+ 'unknown' ,
126+ ] ,
127+ options,
128+ } )
129+ }
118130 validateCustomSortConfiguration ( options )
119131 validateNewlinesAndPartitionConfiguration ( options )
120132 validateSideEffectsConfiguration ( options )
@@ -162,11 +174,14 @@ export default createEslintRule<Options, MESSAGE_ID>({
162174
163175 if ( node . type !== 'VariableDeclaration' && node . importKind === 'type' ) {
164176 if ( node . type === 'ImportDeclaration' ) {
165- group = computeGroupExceptUnknown ( {
166- customGroups : options . customGroups . type ,
167- options,
168- name,
169- } )
177+ if ( ! Array . isArray ( options . customGroups ) ) {
178+ // For deprecated `customGroups.type`
179+ group = computeGroupExceptUnknown ( {
180+ customGroups : options . customGroups . type ,
181+ options,
182+ name,
183+ } )
184+ }
170185
171186 for ( let selector of commonSelectors ) {
172187 selectors . push ( `${ selector } -type` )
@@ -176,23 +191,29 @@ export default createEslintRule<Options, MESSAGE_ID>({
176191 selectors . push ( 'type' )
177192 modifiers . push ( 'type' )
178193
179- group ??= computeGroupExceptUnknown ( {
180- selectors,
181- modifiers,
182- options,
183- name,
184- } )
194+ if ( ! group && ! Array . isArray ( options . customGroups ) ) {
195+ group = computeGroupExceptUnknown ( {
196+ customGroups : [ ] ,
197+ selectors,
198+ modifiers,
199+ options,
200+ name,
201+ } )
202+ }
185203 }
186204
187205 let isSideEffect = isSideEffectImport ( { sourceCode, node } )
188206 let isStyleValue = isStyle ( name )
189207 let isStyleSideEffect = isSideEffect && isStyleValue
190208
191- group ??= computeGroupExceptUnknown ( {
192- customGroups : options . customGroups . value ,
193- options,
194- name,
195- } )
209+ if ( ! group && ! Array . isArray ( options . customGroups ) ) {
210+ // For deprecated `customGroups.value`
211+ group = computeGroupExceptUnknown ( {
212+ customGroups : options . customGroups . value ,
213+ options,
214+ name,
215+ } )
216+ }
196217
197218 if ( isStyleSideEffect ) {
198219 selectors . push ( 'side-effect-style' )
@@ -212,8 +233,11 @@ export default createEslintRule<Options, MESSAGE_ID>({
212233
213234 group ??=
214235 computeGroupExceptUnknown ( {
215- modifiers,
236+ customGroups : Array . isArray ( options . customGroups )
237+ ? options . customGroups
238+ : [ ] ,
216239 selectors,
240+ modifiers,
217241 options,
218242 name,
219243 } ) ?? 'unknown'
@@ -269,19 +293,39 @@ export default createEslintRule<Options, MESSAGE_ID>({
269293 ) : SortImportsSortingNode [ ] =>
270294 sortNodesByGroups ( {
271295 getOptionsByGroupNumber : groupNumber => {
296+ let customGroupOverriddenOptions =
297+ getCustomGroupOverriddenOptions ( {
298+ options : {
299+ ...options ,
300+ customGroups : Array . isArray ( options . customGroups )
301+ ? options . customGroups
302+ : [ ] ,
303+ } ,
304+ groupNumber,
305+ } )
306+
272307 if ( options . sortSideEffects ) {
273308 return {
274- options,
309+ options : {
310+ ...options ,
311+ ...customGroupOverriddenOptions ,
312+ } ,
275313 }
276314 }
315+ let overriddenOptions = {
316+ ...options ,
317+ ...customGroupOverriddenOptions ,
318+ }
277319 return {
278320 options : {
279- ...options ,
321+ ...overriddenOptions ,
280322 type :
281- options . groups [ groupNumber ] &&
282- isSideEffectOnlyGroup ( options . groups [ groupNumber ] )
323+ overriddenOptions . groups [ groupNumber ] &&
324+ isSideEffectOnlyGroup (
325+ overriddenOptions . groups [ groupNumber ] ,
326+ )
283327 ? 'unsorted'
284- : options . type ,
328+ : overriddenOptions . type ,
285329 } ,
286330 }
287331 } ,
@@ -300,7 +344,9 @@ export default createEslintRule<Options, MESSAGE_ID>({
300344 } ,
301345 options : {
302346 ...options ,
303- customGroups : [ ] ,
347+ customGroups : Array . isArray ( options . customGroups )
348+ ? options . customGroups
349+ : [ ] ,
304350 } ,
305351 sortNodesExcludingEslintDisabled,
306352 sourceCode,
@@ -330,19 +376,24 @@ export default createEslintRule<Options, MESSAGE_ID>({
330376 properties : {
331377 ...commonJsonSchemas ,
332378 customGroups : {
333- properties : {
334- value : {
335- description : 'Specifies custom groups for value imports.' ,
336- type : 'object' ,
337- } ,
338- type : {
339- description : 'Specifies custom groups for type imports.' ,
379+ oneOf : [
380+ {
381+ properties : {
382+ value : {
383+ description : 'Specifies custom groups for value imports.' ,
384+ type : 'object' ,
385+ } ,
386+ type : {
387+ description : 'Specifies custom groups for type imports.' ,
388+ type : 'object' ,
389+ } ,
390+ } ,
391+ description : 'Specifies custom groups.' ,
392+ additionalProperties : false ,
340393 type : 'object' ,
341394 } ,
342- } ,
343- description : 'Specifies custom groups.' ,
344- additionalProperties : false ,
345- type : 'object' ,
395+ buildCustomGroupsArrayJsonSchema ( { singleCustomGroupJsonSchema } ) ,
396+ ] ,
346397 } ,
347398 maxLineLength : {
348399 description : 'Specifies the maximum line length.' ,
@@ -524,7 +575,7 @@ let computeGroupExceptUnknown = ({
524575 Required < Options [ 0 ] > ,
525576 'tsconfigRootDir' | 'maxLineLength' | 'customGroups'
526577 >
527- customGroups ? : DeprecatedCustomGroupsOption | undefined
578+ customGroups : DeprecatedCustomGroupsOption | CustomGroupsOption | undefined
528579 selectors ?: Selector [ ]
529580 modifiers ?: Modifier [ ]
530581 name : string
@@ -538,6 +589,13 @@ let computeGroupExceptUnknown = ({
538589 } )
539590 : [ ]
540591 let computedCustomGroup = computeGroup ( {
592+ customGroupMatcher : customGroup =>
593+ doesCustomGroupMatch ( {
594+ modifiers : modifiers ! ,
595+ selectors : selectors ! ,
596+ elementName : name ,
597+ customGroup,
598+ } ) ,
541599 options : {
542600 ...options ,
543601 customGroups,
0 commit comments