feat(turborepo-lockfiles): update bun.lock support to match Bun's current implementation (#10729)
## Description
Updates Turborepo's bun.lock parser to better align with Bun's current
lockfile format implementation. This addresses version detection issues,
adds support for new lockfile fields, and implements v1 optimizations.
## Testing Instructions
```bash
# Unit tests
cargo test -p turborepo-lockfiles
# Specific Bun tests
cargo test -p turborepo-lockfiles bun
# Run with coverage (requires llvm-tools-preview)
cargo coverage
```
### Test Results
- ✅ All 238 lockfile tests pass
- ✅ 72 Bun-specific tests (43 newly added)
- ✅ No regressions in existing functionality
## Background
While investigating Turborepo's bun.lock support against Bun's
implementation (`src/install/lockfile/bun.lock.zig`), I identified
several gaps:
1. **Critical**: `global_change()` only detected package manager
changes, not lockfile version changes
2. **Missing features**: Several fields were not parsed (catalogs,
overrides, trusted dependencies)
3. **Performance**: V1 workspace optimizations were not implemented
4. **Compatibility**: Platform-specific constraints (os/cpu) were
ignored
## Changes
### Core Fixes
1. **Version Detection**
- Added `LockfileVersion` enum for v0/v1 handling
- Fixed `global_change()` to detect version changes (prevents incorrect
cache hits)
- Added `bun_global_change()` for API consistency with other package
managers
2. **New Field Support**
```rust
pub struct BunLockfileData {
lockfile_version: i32,
workspaces: Map<String, WorkspaceEntry>,
packages: Map<String, PackageEntry>,
patched_dependencies: Map<String, String>,
trusted_dependencies: Vec<String>, // NEW
overrides: Map<String, String>, // NEW
catalog: Map<String, String>, // NEW
catalogs: Map<String, Map<String, String>>, // NEW
}
```
3. **Platform Constraints**
```rust
pub enum Negatable {
None, // No constraint
Single(String), // "darwin"
Multiple(Vec<String>), // ["x64", "arm64"]
Not(Vec<String>), // ["\!win32", "\!freebsd"]
}
```
### Feature Implementations
| Feature | Implementation | Tests Added |
|---------|---------------|-------------|
| Catalog Resolution | `resolve_catalog_version()` method | 11 |
| Overrides | `apply_overrides()` method | 3 |
| V1 Workspaces | Direct resolution from workspaces section | 10 |
| Platform Constraints | `Negatable` type with serde support | 6 |
| Subgraph Filtering | Smart metadata filtering | 2 |
| Integration Tests | Combined feature scenarios | 11 |
### Resolution Order
The implementation follows this precedence: **catalog → override →
patch**
## Areas of Uncertainty
I want to be transparent about areas where I'm less confident or made
assumptions:
1. **V1 Behavior Beyond Workspaces**: While I implemented the workspace
optimization mentioned in Bun's source, there may be other v1-specific
behaviors I'm not aware of.
2. **Trusted Dependencies**: I parse and filter these, but I'm unsure if
Turborepo needs to actually use this information for any
security/installation decisions.
3. **Platform Constraint Application**: The `Negatable::allows()` method
is implemented but unused. I'm not sure where in Turborepo's
architecture platform filtering should actually occur.
4. **Catalog Precedence**: I assumed catalogs should be resolved before
overrides based on the code structure, but this precedence isn't
explicitly documented.
5. **Error Handling**: Some edge cases (like circular workspace
dependencies or conflicting overrides) may not be handled optimally.
## Potential Issues
1. **Performance**: The catalog resolution adds an extra lookup step
during package resolution. For large monorepos with many catalog
references, this could impact performance.
2. **Backward Compatibility**: While I've maintained compatibility with
existing lockfiles, the changes to `global_change()` will cause cache
invalidation for projects upgrading Turborepo.
3. **Incomplete Platform Support**: The platform constraints are parsed
but not actively used for filtering during dependency resolution.
## Questions for Reviewers
1. Should platform constraints actually filter dependencies during
resolution, or is parsing/preserving them sufficient?
2. Is the catalog resolution precedence (catalog → override → patch)
correct?
3. Should trusted dependencies affect any Turborepo behavior?
4. Are there other v1-specific optimizations beyond workspace handling
that should be implemented?
5. Should the `UnsupportedVersion` error be recoverable or fatal?
## Known Limitations
1. **Trusted dependencies** are parsed but don't affect installation
behavior
2. **Platform constraints** are parsed but not used for dependency
filtering (would need higher-level changes)
3. **libc field** is not implemented (marked TODO in Bun source)
4. The `Negatable::allows()` method for platform matching is unused
(added for completeness)
## Additional Context
This is a draft PR as I would appreciate feedback on the implementation
approach, particularly in areas where I made assumptions about intended
behavior.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.ai>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Anthony Shew <anthony.shew@vercel.com>
Co-authored-by: Anthony Shew <anthonyshew@gmail.com>