This document covers Bun's npm registry interaction system, including authentication, package metadata retrieval, tarball downloading, and network request handling. This is the network-facing component of the package manager that communicates with npm registries to fetch package information and files.
For dependency resolution logic, see Dependency Resolution. For installation execution and extraction, see Installation Pipeline and Lockfile.
The registry configuration is managed through the Registry.Scope structure, which encapsulates registry URLs, authentication credentials, and request configuration.
Registry Configuration Flow
Sources: src/install/npm.zig196-376
The Registry.Scope struct contains all configuration for accessing a registry:
| Field | Type | Purpose |
|---|---|---|
name | string | Scope name (e.g., "@myorg") |
url | URL | Registry base URL |
url_hash | u64 | Hash of URL for fast lookups |
token | string | Bearer token for authentication |
auth | string | Base64-encoded username:password |
user | string | Raw username:password string |
Sources: src/install/npm.zig201-221
Registry URLs can embed authentication parameters in the pathname. The fromAPI method parses these special suffixes:
:_authToken=<token> - Bearer token:_auth=<base64> - Base64 encoded credentials:username=<user> - Username component:_password=<pass> - Password componentURL Authentication Extraction Process
Sources: src/install/npm.zig232-375
Environment variables are automatically resolved using DotEnv.Loader.getAuto(), allowing values like $NPM_TOKEN to be substituted at runtime.
Sources: src/install/npm.zig337-353
Package metadata is fetched from the registry using HTTP GET requests with specialized headers for npm compatibility.
Package Metadata Request Flow
Sources: src/install/npm.zig393-457
The metadata request includes specific headers for npm compatibility:
| Header | Value | Purpose |
|---|---|---|
accept | application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */* | Request compact manifest format |
accept-encoding | gzip, deflate | Enable compression |
authorization | Bearer <token> | Authentication |
npm-auth-type | legacy or web | Auth protocol version |
npm-command | Command name | Track client operations |
user-agent | Bun version + platform | Client identification |
if-none-match | <etag> | Conditional request for caching |
if-modified-since | <date> | Conditional request for caching |
Sources: src/install/npm.zig29-78
The getPackageMetadata function processes different HTTP status codes:
HTTP Status Code Processing
Sources: src/install/npm.zig403-432
The response body is parsed from JSON into a PackageManifest structure, which contains version information, dependencies, distribution metadata, and integrity checksums.
Sources: src/install/npm.zig393-457
Once a specific package version is resolved, the tarball URL is constructed according to npm registry conventions.
Tarball URLs follow the pattern:
{registry}/{full-name}/-/{short-name}-{version}.tgz
For scoped packages like @scope/package:
full-name = @scope/packageshort-name = package (without scope)Tarball URL Construction
Sources: src/install/extract_tarball.zig29-102
The buildURL function handles different version formats:
{name}-{major}.{minor}.{patch}.tgz{name}-{major}.{minor}.{patch}-{pre}.tgz{name}-{major}.{minor}.{patch}+{build}.tgz{name}-{major}.{minor}.{patch}-{pre}+{build}.tgzSources: src/install/extract_tarball.zig59-101
Tarball Verification Flow
Sources: src/install/extract_tarball.zig13-27
The Integrity structure supports multiple hash algorithms (SHA-512, SHA-1) and verifies downloaded content matches the expected checksum from the package manifest.
Bun supports multiple authentication methods for npm registries, with automatic selection based on configuration.
Authentication Method Selection
Sources: src/install/npm.zig201-376
Packages with scopes (e.g., @myorg/package) can use scope-specific registry configuration:
The scope name is extracted from the package name and matched against configured scopes. If found, the scope's authentication credentials are used instead of the default registry.
Sources: src/install/npm.zig218-230
The whoami function verifies authentication by calling the /-/whoami endpoint:
{registry}/-/whoamiusername fieldSources: src/install/npm.zig8-146
The network layer uses AsyncHTTP for all registry requests with support for retries, concurrency control, and connection pooling.
Network Request Lifecycle
Sources: src/install/npm.zig88-109 test/cli/install/bun-install.test.ts106-206
The --network-concurrency flag limits simultaneous HTTP requests:
Sources: test/cli/install/bun-install.test.ts74-206
Error Handling and Retry Flow
Sources: test/cli/install/bun-install.test.ts341-398
Common error scenarios:
| Error Type | Status | Handling |
|---|---|---|
ConnectionRefused | N/A | Retry with backoff |
ConnectionClosed | N/A | Retry with backoff |
| Package not found | 404 | Report to user, no retry |
| Auth failed | 401 | Report auth error, no retry |
| Server error | 5xx | Retry with backoff |
| Bad request | 400 | Report error, no retry |
Sources: test/cli/install/bun-install.test.ts342-398 src/install/npm.zig148-194
When registry requests fail, Bun provides detailed error messages with context.
Error Response Processing
The responseError function handles error responses:
error field if presentSources: src/install/npm.zig148-194
Example error output:
<red>404<r> Not Found: https://registry.npmjs.org/nonexistent-package
- '[email protected]' does not exist in this registry
Registry responses may include an npm-notice header with important announcements. Bun displays these to users after successful operations:
Note: <notice text>
Sources: src/install/npm.zig123-127
| Entity | Location | Purpose |
|---|---|---|
Registry.Scope | src/install/npm.zig201-376 | Registry configuration and auth |
getPackageMetadata() | src/install/npm.zig393-457 | Fetch package manifest from registry |
buildURL() | src/install/extract_tarball.zig29-102 | Construct tarball download URL |
responseError() | src/install/npm.zig148-194 | Format and display error responses |
whoami() | src/install/npm.zig8-146 | Verify authentication credentials |
AsyncHTTP | src/bun.zig647-649 | HTTP client for async requests |
PackageManifest | Referenced in npm.zig | Parsed package metadata structure |
Registry configuration is loaded from multiple sources with precedence:
--registry)bunfig.toml [install] and [install.scopes] sectionspackage.json publishConfig.registry field$VAR substitution)https://registry.npmjs.org/Refresh this wiki