Skip to content

Commit a55cbb7

Browse files
authoredMar 30, 2024··
feat: improve pnpm sorting (#314)
* feat: improve sorting of pnpm.overrides * fix: replace .at with .pop * feat: handle parent/child overrides ('pkgA>pkgB') * chore: simplify
1 parent af54e91 commit a55cbb7

File tree

4 files changed

+212
-224
lines changed

4 files changed

+212
-224
lines changed
 

‎index.js

+57-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import detectIndent from 'detect-indent'
33
import { detectNewlineGraceful as detectNewline } from 'detect-newline'
44
import gitHooks from 'git-hooks-list'
55
import isPlainObject from 'is-plain-obj'
6+
import semver from 'semver'
67

78
const hasOwn =
89
Object.hasOwn ||
@@ -54,6 +55,38 @@ const overProperty =
5455
: object
5556
const sortGitHooks = sortObjectBy(gitHooks)
5657

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+
5790
// https://github.com/eslint/eslint/blob/acc0e47572a9390292b4e313b4a4bf360d236358/conf/config-schema.js
5891
const eslintBaseConfigProperties = [
5992
// `files` and `excludedFiles` are only on `overrides[]`
@@ -128,6 +161,29 @@ const sortPrettierConfig = onObject(
128161

129162
const sortVolta = sortObjectBy(['node', 'npm', 'yarn'])
130163

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+
131187
// See https://docs.npmjs.com/misc/scripts
132188
const defaultNpmScripts = new Set([
133189
'install',
@@ -312,7 +368,7 @@ const fields = [
312368
/* vscode */ { key: 'galleryBanner', over: sortObject },
313369
/* vscode */ { key: 'preview' },
314370
/* vscode */ { key: 'markdown' },
315-
{ key: 'pnpm', over: sortObjectBy(undefined, true) },
371+
{ key: 'pnpm', over: sortPnpmConfig },
316372
]
317373

318374
const defaultSortOrder = fields.map(({ key }) => key)

‎package-lock.json

+135-218
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"git-hooks-list": "^3.0.0",
7474
"globby": "^13.1.2",
7575
"is-plain-obj": "^4.1.0",
76+
"semver": "^7.6.0",
7677
"sort-object-keys": "^1.1.3"
7778
},
7879
"devDependencies": {

‎tests/fields.js

+19-5
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,16 @@ test('pnpm', macro.sortObject, {
263263
path: 'pnpm',
264264
value: {
265265
overrides: {
266+
'@react-stately/selection@~3.10.3': '3.10.3',
266267
'aws-sdk@1.2345.0': '1.123.0',
267268
'react-native-notifications@^3.4.5': '3.4.5',
268269
'antd@^2.23.4': '2.23.4',
270+
'@react-stately/select@~3.1.3': '3.1.3',
271+
'@react-stately/selection@~3.7.0': '3.7.0',
272+
'@react-stately/select@3': '3.3.1',
273+
'@react-aria/selection@3.10.1>@react-stately/selection': '3.10.3',
274+
'@react-aria/selection@3.10.1>@react-aria/focus': '3.8.0',
275+
'@react-aria/selection@3.5.1>@react-stately/selection': '3.10.3',
269276
},
270277
patchedDependencies: {
271278
'esbuild-sass-plugin@1.20.0': 'foo.patch',
@@ -289,10 +296,22 @@ test('pnpm', macro.sortObject, {
289296
expect: {
290297
allowNonAppliedPatches: true,
291298
overrides: {
299+
'@react-aria/selection@3.5.1>@react-stately/selection': '3.10.3',
300+
'@react-aria/selection@3.10.1>@react-aria/focus': '3.8.0',
301+
'@react-aria/selection@3.10.1>@react-stately/selection': '3.10.3',
302+
'@react-stately/select@3': '3.3.1',
303+
'@react-stately/select@~3.1.3': '3.1.3',
304+
'@react-stately/selection@~3.7.0': '3.7.0',
305+
'@react-stately/selection@~3.10.3': '3.10.3',
292306
'antd@^2.23.4': '2.23.4',
293307
'aws-sdk@1.2345.0': '1.123.0',
294308
'react-native-notifications@^3.4.5': '3.4.5',
295309
},
310+
patchedDependencies: {
311+
'domino@4.5.6': 'bar.patch',
312+
'es5-ext@0.12.3': 'baz.patch',
313+
'esbuild-sass-plugin@1.20.0': 'foo.patch',
314+
},
296315
packageExtensions: {
297316
'@rjsf/core': {
298317
dependencies: {
@@ -305,10 +324,5 @@ test('pnpm', macro.sortObject, {
305324
},
306325
},
307326
},
308-
patchedDependencies: {
309-
'domino@4.5.6': 'bar.patch',
310-
'es5-ext@0.12.3': 'baz.patch',
311-
'esbuild-sass-plugin@1.20.0': 'foo.patch',
312-
},
313327
},
314328
})

0 commit comments

Comments
 (0)
Please sign in to comment.