From e3a0a8cef87a4f2914c7e90c0c8629ce74603215 Mon Sep 17 00:00:00 2001 From: rickh18 <7232509+rickh18@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:06:37 +0000 Subject: [PATCH 1/2] fix: support for sorting dependenciesMeta in Yarn berry --- index.js | 23 +++++- tests/_helpers.js | 35 +++++++++ tests/deps.js | 9 ++- tests/snapshots/deps.js.md | 140 +++++++++++++++++++++++++++++++++++ tests/snapshots/deps.js.snap | Bin 429 -> 685 bytes 5 files changed, 205 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 8c932512..6463a177 100755 --- a/index.js +++ b/index.js @@ -87,6 +87,27 @@ const sortObjectBySemver = sortObjectBy((a, b) => { return semver.compare(semver.minVersion(aRange), semver.minVersion(bRange)) }) +const sortObjectByIdent = (a, b) => { + const getIdent = (ident) => { + const parts = ident.split('@') + + if (ident.startsWith('@')) { + // Handle cases where ident starts with '@' + return parts.length > 2 ? parts.slice(0, -1).join('@') : ident + } + + // Handle cases where ident doesn't start with '@' + return parts.length > 1 ? parts.slice(0, -1).join('@') : ident + } + + const identA = getIdent(a) + const identB = getIdent(b) + + if (identA < identB) return -1 + if (identA > identB) return 1 + return 0 +} + // https://github.com/eslint/eslint/blob/acc0e47572a9390292b4e313b4a4bf360d236358/conf/config-schema.js const eslintBaseConfigProperties = [ // `files` and `excludedFiles` are only on `overrides[]` @@ -341,7 +362,7 @@ const fields = [ { key: 'resolutions', over: sortObject }, { key: 'dependencies', over: sortObject }, { key: 'devDependencies', over: sortObject }, - { key: 'dependenciesMeta', over: sortObjectBy(undefined, true) }, + { key: 'dependenciesMeta', over: sortObjectBy(sortObjectByIdent, true) }, { key: 'peerDependencies', over: sortObject }, // TODO: only sort depth = 2 { key: 'peerDependenciesMeta', over: sortObjectBy(undefined, true) }, diff --git a/tests/_helpers.js b/tests/_helpers.js index 711e562d..7f2ba700 100644 --- a/tests/_helpers.js +++ b/tests/_helpers.js @@ -59,6 +59,40 @@ function sortObjectAlphabetically(t, options = {}) { } } +function sortObjectWithRangeAlphabetically(t, options = {}) { + const { maxDepth = 1, expect } = options + + for (let depth = 1; depth < maxDepth + 1; depth++) { + sortObject(t, { + ...options, + value: keysToObject( + [ + '@z-package@1.2.3', + 'c-package@1.2.3', + 'b-package-package@1.2.3', + '@a-package@1.2.3', + 'b-package@1.2.3', + '@b-package', + ], + depth, + ), + expect: + expect || + keysToObject( + [ + '@a-package@1.2.3', + '@b-package', + '@z-package@1.2.3', + 'b-package@1.2.3', + 'b-package-package@1.2.3', + 'c-package@1.2.3', + ], + depth, + ), + }) + } +} + function sortObject( t, { @@ -211,6 +245,7 @@ export const macro = { sortObject, asItIs, sortObjectAlphabetically, + sortObjectWithRangeAlphabetically, testCLI, uniqueArray, uniqueAndSort, diff --git a/tests/deps.js b/tests/deps.js index c263554a..eaca27b3 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -30,10 +30,17 @@ test('peerDependenciesMeta', macro.sortObjectAlphabetically, { expect: 'snapshot', }) -// peerDependenciesMeta +// dependenciesMeta test('dependenciesMeta', macro.sortObjectAlphabetically, { path: 'dependenciesMeta', maxDepth: 2, // TODO: don't use snapshot, find a esaier way for review expect: 'snapshot', }) + +test('dependenciesMetaRange', macro.sortObjectWithRangeAlphabetically, { + path: 'dependenciesMeta', + maxDepth: 2, + // TODO: don't use snapshot, find a esaier way for review + expect: 'snapshot', +}) diff --git a/tests/snapshots/deps.js.md b/tests/snapshots/deps.js.md index 4dc7c8b2..ce3b6806 100644 --- a/tests/snapshots/deps.js.md +++ b/tests/snapshots/deps.js.md @@ -107,3 +107,143 @@ Generated by [AVA](https://avajs.dev). }`, pretty: true, } + +## dependenciesMetaRange + +> Should sort `dependenciesMeta` as object. + + { + input: `{␊ + "dependenciesMeta": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + }␊ + }`, + options: undefined, + output: `{␊ + "dependenciesMeta": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + }␊ + }`, + pretty: true, + } + +> Should sort `dependenciesMeta` as object. + + { + input: `{␊ + "dependenciesMeta": {␊ + "@z-package@1.2.3": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + },␊ + "c-package@1.2.3": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + },␊ + "b-package-package@1.2.3": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + },␊ + "@a-package@1.2.3": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + },␊ + "b-package@1.2.3": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + },␊ + "@b-package": {␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "@b-package": "@b-package"␊ + }␊ + }␊ + }`, + options: undefined, + output: `{␊ + "dependenciesMeta": {␊ + "@a-package@1.2.3": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + },␊ + "@b-package": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + },␊ + "@z-package@1.2.3": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + },␊ + "b-package@1.2.3": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + },␊ + "b-package-package@1.2.3": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + },␊ + "c-package@1.2.3": {␊ + "@a-package@1.2.3": "@a-package@1.2.3",␊ + "@b-package": "@b-package",␊ + "@z-package@1.2.3": "@z-package@1.2.3",␊ + "b-package@1.2.3": "b-package@1.2.3",␊ + "b-package-package@1.2.3": "b-package-package@1.2.3",␊ + "c-package@1.2.3": "c-package@1.2.3"␊ + }␊ + }␊ + }`, + pretty: true, + } diff --git a/tests/snapshots/deps.js.snap b/tests/snapshots/deps.js.snap index 4d621cf5dd1d162151f02d9f006f3942ec320a75..26fa3e13ca827f77953d322f49e5722dfe4da7f0 100644 GIT binary patch literal 685 zcmV;e0#f}!RzVN&hC9CK-pq9@0a}%w*<$=l8r%GC6-W z90ks4baugoCq`U^oR1&zkozw89gjy(xnN%8voJadMD*dpb(vr<$%6(=#6NPKH2VMs z06qh_1aOl82c)%6TF-{Bxg!W!U3NMhkUfxVAQldYaf38Kn){^b`Qbz?TMys0DYa#( z*nJw0QEE@^e*D*+x8ebt*=K4L>YdUN>VB$$j`8UPk_hLIWZQbzd~fWH8~=o;}oDqy~{CM?bVN*GW<^SSvZ*?XQd|Cr|;*f3X1f-54wv2e8QX>yGY3qP zPqr@`MY4Kk)m4A8-nykHNQ16)Iwf&sFP*%sbyq;HL@Pu{6E& z*i`q<>baw!l!~)-)KaTOl?p0x*!t0&-)9Z15ZLzIYjB0&B=Kuv)k>`fRQ+03l~!)eO2(?_kXI9v5G#6-)WC{>)!@{?6@5Mmg%541gq6-1x2YP zC6!<<6Mt$>Vp3{Og>G<0erZmMLUDdki9!N4s}d9vixu+00j38F@k7``{4t0R4DF>9 zhB#9T1Cc=vVWNjWN(=x40x4FA(?D^=5$6LG2cbkGN<<=jP(`!`n#DgPV-}`azKaiH~ytS)vZn9|r&c>~yNl From f473ce927e65e6a4928060c803fa844f255e5651 Mon Sep 17 00:00:00 2001 From: rickh18 <7232509+rickh18@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:55:22 +0000 Subject: [PATCH 2/2] refactor: sortObjectByIdent - renamed getIdent to getPackageName - moved getPackageName and parseNameAndVersionRange functions to outer scope. --- index.js | 61 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index 6463a177..60ecd43a 100755 --- a/index.js +++ b/index.js @@ -55,23 +55,24 @@ const overProperty = : object const sortGitHooks = sortObjectBy(gitHooks) -const sortObjectBySemver = sortObjectBy((a, b) => { - const parseNameAndVersionRange = (specifier) => { - // Ignore anything after > & rely on fallback alphanumeric sorting for that - const [nameAndVersion] = specifier.split('>') - const atMatches = [...nameAndVersion.matchAll('@')] - if ( - !atMatches.length || - (atMatches.length === 1 && atMatches[0].index === 0) - ) { - return { name: specifier } - } - const splitIndex = atMatches.pop().index - return { - name: nameAndVersion.substring(0, splitIndex), - range: nameAndVersion.substring(splitIndex + 1), - } +const parseNameAndVersionRange = (specifier) => { + // Ignore anything after > & rely on fallback alphanumeric sorting for that + const [nameAndVersion] = specifier.split('>') + const atMatches = [...nameAndVersion.matchAll('@')] + if ( + !atMatches.length || + (atMatches.length === 1 && atMatches[0].index === 0) + ) { + return { name: specifier } + } + const splitIndex = atMatches.pop().index + return { + name: nameAndVersion.substring(0, splitIndex), + range: nameAndVersion.substring(splitIndex + 1), } +} + +const sortObjectBySemver = sortObjectBy((a, b) => { const { name: aName, range: aRange } = parseNameAndVersionRange(a) const { name: bName, range: bRange } = parseNameAndVersionRange(b) @@ -87,24 +88,24 @@ const sortObjectBySemver = sortObjectBy((a, b) => { return semver.compare(semver.minVersion(aRange), semver.minVersion(bRange)) }) -const sortObjectByIdent = (a, b) => { - const getIdent = (ident) => { - const parts = ident.split('@') - - if (ident.startsWith('@')) { - // Handle cases where ident starts with '@' - return parts.length > 2 ? parts.slice(0, -1).join('@') : ident - } +const getPackageName = (ident) => { + const parts = ident.split('@') - // Handle cases where ident doesn't start with '@' - return parts.length > 1 ? parts.slice(0, -1).join('@') : ident + if (ident.startsWith('@')) { + // Handle cases where package name starts with '@' + return parts.length > 2 ? parts.slice(0, -1).join('@') : ident } - const identA = getIdent(a) - const identB = getIdent(b) + // Handle cases where package name doesn't start with '@' + return parts.length > 1 ? parts.slice(0, -1).join('@') : ident +} + +const sortObjectByIdent = (a, b) => { + const PackageNameA = getPackageName(a) + const PackageNameB = getPackageName(b) - if (identA < identB) return -1 - if (identA > identB) return 1 + if (PackageNameA < PackageNameB) return -1 + if (PackageNameA > PackageNameB) return 1 return 0 }