@@ -3,6 +3,7 @@ import detectIndent from 'detect-indent'
3
3
import { detectNewlineGraceful as detectNewline } from 'detect-newline'
4
4
import gitHooks from 'git-hooks-list'
5
5
import isPlainObject from 'is-plain-obj'
6
+ import semver from 'semver'
6
7
7
8
const hasOwn =
8
9
Object . hasOwn ||
@@ -54,6 +55,38 @@ const overProperty =
54
55
: object
55
56
const sortGitHooks = sortObjectBy ( gitHooks )
56
57
58
+ const sortObjectBySemver = sortObjectBy ( ( a , b ) => {
59
+ const parseNameAndVersionRange = ( specifier ) => {
60
+ // Ignore anything after > & rely on fallback alphanumeric sorting for that
61
+ const [ nameAndVersion ] = specifier . split ( '>' )
62
+ const atMatches = [ ...nameAndVersion . matchAll ( '@' ) ]
63
+ if (
64
+ ! atMatches . length ||
65
+ ( atMatches . length === 1 && atMatches [ 0 ] . index === 0 )
66
+ ) {
67
+ return { name : specifier }
68
+ }
69
+ const splitIndex = atMatches . pop ( ) . index
70
+ return {
71
+ name : nameAndVersion . substring ( 0 , splitIndex ) ,
72
+ range : nameAndVersion . substring ( splitIndex + 1 ) ,
73
+ }
74
+ }
75
+ const { name : aName , range : aRange } = parseNameAndVersionRange ( a )
76
+ const { name : bName , range : bRange } = parseNameAndVersionRange ( b )
77
+
78
+ if ( aName !== bName ) {
79
+ return aName . localeCompare ( bName )
80
+ }
81
+ if ( ! aRange ) {
82
+ return - 1
83
+ }
84
+ if ( ! bRange ) {
85
+ return 1
86
+ }
87
+ return semver . compare ( semver . minVersion ( aRange ) , semver . minVersion ( bRange ) )
88
+ } )
89
+
57
90
// https://github.com/eslint/eslint/blob/acc0e47572a9390292b4e313b4a4bf360d236358/conf/config-schema.js
58
91
const eslintBaseConfigProperties = [
59
92
// `files` and `excludedFiles` are only on `overrides[]`
@@ -128,6 +161,29 @@ const sortPrettierConfig = onObject(
128
161
129
162
const sortVolta = sortObjectBy ( [ 'node' , 'npm' , 'yarn' ] )
130
163
164
+ const pnpmBaseConfigProperties = [
165
+ 'peerDependencyRules' ,
166
+ 'neverBuiltDependencies' ,
167
+ 'onlyBuiltDependencies' ,
168
+ 'onlyBuiltDependenciesFile' ,
169
+ 'allowedDeprecatedVersions' ,
170
+ 'allowNonAppliedPatches' ,
171
+ 'updateConfig' ,
172
+ 'auditConfig' ,
173
+ 'requiredScripts' ,
174
+ 'supportedArchitectures' ,
175
+ 'overrides' ,
176
+ 'patchedDependencies' ,
177
+ 'packageExtensions' ,
178
+ ]
179
+
180
+ const sortPnpmConfig = onObject (
181
+ pipe ( [
182
+ sortObjectBy ( pnpmBaseConfigProperties , true ) ,
183
+ overProperty ( 'overrides' , sortObjectBySemver ) ,
184
+ ] ) ,
185
+ )
186
+
131
187
// See https://docs.npmjs.com/misc/scripts
132
188
const defaultNpmScripts = new Set ( [
133
189
'install' ,
@@ -312,7 +368,7 @@ const fields = [
312
368
/* vscode */ { key : 'galleryBanner' , over : sortObject } ,
313
369
/* vscode */ { key : 'preview' } ,
314
370
/* vscode */ { key : 'markdown' } ,
315
- { key : 'pnpm' , over : sortObjectBy ( undefined , true ) } ,
371
+ { key : 'pnpm' , over : sortPnpmConfig } ,
316
372
]
317
373
318
374
const defaultSortOrder = fields . map ( ( { key } ) => key )
0 commit comments