| Crates.io | sort-package-json |
| lib.rs | sort-package-json |
| version | 0.0.10 |
| created_at | 2025-12-05 11:17:12.476959+00 |
| updated_at | 2026-01-23 04:48:13.226659+00 |
| description | A Rust implementation of sort-package-json that sorts package.json files according to well-established npm conventions |
| homepage | |
| repository | https://github.com/oxc-project/sort-package-json |
| max_upload_size | |
| id | 1968028 |
| size | 51,261 |
A Rust implementation that sorts package.json files according to well-established npm conventions.
Note on Compatibility: This crate is not compatible with the original sort-package-json npm package. While both tools sort package.json files, this Rust implementation uses different sorting groupings that we believe are clearer and easier to navigate. The field order is inspired by both the original sort-package-json and Prettier's package.json sorting, but organized into more intuitive logical groups.
_) sorted lastAdd to your Cargo.toml:
[dependencies]
sort-package-json = "0.0.5"
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let contents = fs::read_to_string("package.json")?;
let sorted = sort_package_json::sort_package_json(&contents)?;
fs::write("package.json", sorted)?;
Ok(())
}
With custom options:
use sort_package_json::{sort_package_json_with_options, SortOptions};
let options = SortOptions { pretty: false };
let sorted = sort_package_json_with_options(&contents, &options)?;
To test on a repository, run the included example which recursively finds and sorts all package.json files:
cargo run --example simple [PATH]
If no path is provided, it defaults to the current directory.
Given an unsorted package.json:
{
"version": "1.0.0",
"dependencies": { "foo": "1.0.0" },
"name": "my-package",
"scripts": { "test": "vitest" }
}
After sorting:
{
"name": "my-package",
"version": "1.0.0",
"scripts": { "test": "vitest" },
"dependencies": { "foo": "1.0.0" }
}
Fields are sorted into 12 logical groups, followed by unknown fields alphabetically, then private fields (starting with _) at the end. The complete field order is based on both the original sort-package-json and prettier's package.json sorting implementations.
{
// 1. Core Package Metadata
"$schema": "https://json.schemastore.org/package.json",
"name": "my-package",
"displayName": "My Package",
"version": "1.0.0",
"private": true,
"description": "A sample package",
"categories": ["linters", "formatters"],
"keywords": ["sample", "test"],
"homepage": "https://example.com",
"bugs": { "url": "https://github.com/user/repo/issues", "email": "support@example.com" },
// 2. License & People
"license": "MIT",
"author": { "name": "Author", "email": "author@example.com", "url": "https://example.com" },
"maintainers": [{ "name": "Maintainer", "email": "maintainer@example.com" }],
"contributors": [{ "name": "Contributor", "email": "contributor@example.com" }],
// 3. Repository & Funding
"repository": { "type": "git", "url": "https://github.com/user/repo.git" },
"funding": { "type": "github", "url": "https://github.com/sponsors/user" },
// 4. Package Content & Distribution
"bin": { "my-cli": "./bin/cli.js" },
"directories": { "lib": "lib", "bin": "bin", "man": "man", "doc": "doc" },
"workspaces": ["packages/*"],
"files": ["dist", "lib", "src/index.js"],
"os": ["darwin", "linux"],
"cpu": ["x64", "arm64"],
// 5. Package Entry Points
"type": "module",
"sideEffects": false,
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"browser": "./dist/browser.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"default": "./dist/index.mjs",
},
},
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" },
// 6. Scripts
"scripts": {
"build": "tsup",
"test": "vitest",
"lint": "eslint .",
},
// 7. Dependencies
"dependencies": { "lodash": "^4.17.21" },
"devDependencies": { "typescript": "^5.0.0", "vitest": "^1.0.0" },
"peerDependencies": { "react": ">=18.0.0" },
"peerDependenciesMeta": { "react": { "optional": true } },
"optionalDependencies": { "fsevents": "^2.3.0" },
"bundledDependencies": ["internal-lib"],
"overrides": { "semver": "^7.5.4" },
// 8. Git Hooks & Commit Tools
"simple-git-hooks": { "pre-commit": "npx lint-staged" },
"lint-staged": { "*.ts": ["eslint --fix", "prettier --write"] },
"commitlint": { "extends": ["@commitlint/config-conventional"] },
// 9. VSCode Extension Specific
"contributes": { "commands": [] },
"activationEvents": ["onLanguage:javascript"],
"icon": "icon.png",
// 10. Build & Tool Configuration
"browserslist": ["> 1%", "last 2 versions"],
"prettier": { "semi": false, "singleQuote": true },
"eslintConfig": { "extends": ["eslint:recommended"] },
// 11. Testing
"jest": { "testEnvironment": "node" },
"c8": { "include": ["src/**"] },
// 12. Runtime & Package Manager
"engines": { "node": ">=18.0.0" },
"packageManager": "pnpm@8.0.0",
"pnpm": { "overrides": {} },
// Unknown fields (sorted alphabetically)
"customField": "value",
"myConfig": {},
// Private fields (sorted alphabetically, always last)
"_internal": "hidden",
"_private": "data",
}
We use serde_json instead of simd-json because:
cargo build --release
cargo test
Tests use snapshot testing via insta. To review and accept snapshot changes:
cargo insta review
Or to accept all changes:
cargo insta accept
MIT