From 27e4b7bf4d1357c43c147861b76fcf0f79c661d5 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Sun, 4 May 2025 07:56:07 -0700 Subject: [PATCH] feat: sort dependencies with npm algorithm, sort npm Overrides key (#358) * Sort dependencies with npm algorithm * Update _helpers.js * Add simple test * Fix tests --- index.js | 13 +++++++---- tests/deps.js | 41 +++++++++++++++++++++++++++++++++++ tests/snapshots/main.js.md | 2 ++ tests/snapshots/main.js.snap | Bin 1430 -> 1445 bytes 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 328b6af..86057ab 100755 --- a/index.js +++ b/index.js @@ -99,6 +99,10 @@ const sortObjectByIdent = (a, b) => { return 0 } +// sort deps like the npm CLI does (via the package @npmcli/package-json) +// https://github.com/npm/package-json/blob/b6465f44c727d6513db6898c7cbe41dd355cebe8/lib/update-dependencies.js#L8-L21 +const sortDependenciesLikeNpm = sortObjectBy((a, b) => a.localeCompare(b, 'en')) + // https://github.com/eslint/eslint/blob/acc0e47572a9390292b4e313b4a4bf360d236358/conf/config-schema.js const eslintBaseConfigProperties = [ // `files` and `excludedFiles` are only on `overrides[]` @@ -366,13 +370,14 @@ const fields = [ { key: 'tap', over: sortObject }, { key: 'oclif', over: sortObjectBy(undefined, true) }, { key: 'resolutions', over: sortObject }, - { key: 'dependencies', over: sortObject }, - { key: 'devDependencies', over: sortObject }, + { key: 'overrides', over: sortDependenciesLikeNpm }, + { key: 'dependencies', over: sortDependenciesLikeNpm }, + { key: 'devDependencies', over: sortDependenciesLikeNpm }, { key: 'dependenciesMeta', over: sortObjectBy(sortObjectByIdent, true) }, - { key: 'peerDependencies', over: sortObject }, + { key: 'peerDependencies', over: sortDependenciesLikeNpm }, // TODO: only sort depth = 2 { key: 'peerDependenciesMeta', over: sortObjectBy(undefined, true) }, - { key: 'optionalDependencies', over: sortObject }, + { key: 'optionalDependencies', over: sortDependenciesLikeNpm }, { key: 'bundledDependencies', over: uniqAndSortArray }, { key: 'bundleDependencies', over: uniqAndSortArray }, /* vscode */ { key: 'extensionPack', over: uniqAndSortArray }, diff --git a/tests/deps.js b/tests/deps.js index 6885d7a..ffea6a8 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -1,4 +1,5 @@ import test from 'ava' +import sortPackageJson from '../index.js' import { macro } from './_helpers.js' // `resolutions` and `dependencies` @@ -51,3 +52,43 @@ test('pnpm.overrides', macro.sortObjectWithRangeAlphabetically, { // TODO: don't use snapshot, find a esaier way for review expect: 'snapshot', }) + +test('dependencies with capital and lowercase letters', (t) => { + t.deepEqual( + sortPackageJson({ + dependencies: { + JSONStream: '^1.3.5', + axios: '^1.9.0', + 'json-schema': '^0.4.0', + }, + }), + { + dependencies: { + axios: '^1.9.0', + JSONStream: '^1.3.5', + 'json-schema': '^0.4.0', + }, + }, + ) +}) + +test('devDependencies with capital and lowercase letters', (t) => { + t.deepEqual( + sortPackageJson({ + devDependencies: { + JSONStream: '^1.3.5', + axios: '^1.9.0', + 'json-schema': '^0.4.0', + webpack: '^5.36.2', + }, + }), + { + devDependencies: { + axios: '^1.9.0', + JSONStream: '^1.3.5', + 'json-schema': '^0.4.0', + webpack: '^5.36.2', + }, + }, + ) +}) diff --git a/tests/snapshots/main.js.md b/tests/snapshots/main.js.md index 4599677..01f0824 100644 --- a/tests/snapshots/main.js.md +++ b/tests/snapshots/main.js.md @@ -82,6 +82,7 @@ Generated by [AVA](https://avajs.dev). "oclif": "oclif",␊ "optionalDependencies": "optionalDependencies",␊ "os": "os",␊ + "overrides": "overrides",␊ "packageManager": "packageManager",␊ "peerDependencies": "peerDependencies",␊ "peerDependenciesMeta": "peerDependenciesMeta",␊ @@ -203,6 +204,7 @@ Generated by [AVA](https://avajs.dev). "tap": "tap",␊ "oclif": "oclif",␊ "resolutions": "resolutions",␊ + "overrides": "overrides",␊ "dependencies": "dependencies",␊ "devDependencies": "devDependencies",␊ "dependenciesMeta": "dependenciesMeta",␊ diff --git a/tests/snapshots/main.js.snap b/tests/snapshots/main.js.snap index bf4f7745d2c2ce5c02f4694ebf69f217911a15e0..49dd97e01b0ef3e3bc8edc004ff29d165f09a229 100644 GIT binary patch literal 1445 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