A minimal npm package manager written in Rust. Resolves dependencies from the npm registry, downloads tarballs, and extracts them into node_modules/.
Built as a learning project to understand how package managers work under the hood.
- Reads
dependencies,devDependencies, andoptionalDependenciesfrompackage.json - Resolves transitive dependencies via concurrent BFS
- npm-compatible semver ranges (
^,~,>=,||, space-separated,*, exact versions) via node-semver - Concurrent tarball downloads and extraction into a flat
node_modules/layout - Platform filtering for optional dependencies (
os/cpufields, including negation) - Creates
node_modules/.bin/symlinks for packages withbinentries - Skips already-installed packages at the correct version
- Handles scoped packages (
@scope/pkg)
- Rust (1.70+)
- Node.js (for running installed packages)
npm install -g zonepmgit clone https://github.com/yangshun/zonepm.git
cd zonepm
cargo build --releaseThe binary will be at target/release/zpm.
# In a directory with a package.json
zpm install
# Short alias
zpm imkdir my-project && cd my-project
cat > package.json << 'EOF'
{
"dependencies": { "express": "^4.21.0" },
"devDependencies": { "lodash": "^4.17.0" }
}
EOF
zpm installdependencies:
+ express 4.22.1
devDependencies:
+ lodash 4.17.23
Done! Installed 71 packages in 0.88s.
Cargo.toml # Workspace root
crates/
cli/ # Binary crate
src/main.rs # CLI entry point (clap)
registry/ # Library crate
src/
lib.rs # Error types, shared utilities
package_json.rs # package.json parsing
resolver.rs # npm registry client + semver resolution
installer.rs # Tarball download, extraction, .bin linking
npm/
zonepm/ # Root npm package with bin shim
darwin-arm64/ # Platform-specific binary package
scripts/
build.sh # Build + copy binary into npm package
publish.sh # Publish all npm packages
tests/
fixtures/ # Shared test fixtures
# Unit tests (no network access) — 27 tests
cargo test
# Integration tests (hits real npm registry)
cargo test -- --ignored- No lockfile generation
- No global cache (re-downloads on every install)
- Flat hoisting only (first-resolved version wins)
- No peer dependency resolution
- No lifecycle scripts (
postinstall, etc.) - No workspaces support
MIT