Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(turborepo): support Bun #5934

Merged
merged 11 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cli/internal/ffi/ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ func toPackageManager(packageManager string) ffi_proto.PackageManager {
return ffi_proto.PackageManager_PNPM
case "yarn":
return ffi_proto.PackageManager_YARN
case "bun":
return ffi_proto.PackageManager_BUN
default:
panic(fmt.Sprintf("Invalid package manager string: %s", packageManager))
}
Expand Down
25 changes: 20 additions & 5 deletions cli/internal/ffi/proto/messages.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions cli/internal/lockfile/bun_lockfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lockfile

import (
"github.com/vercel/turbo/cli/internal/turbopath"
)

// BunLockfile representation of bun lockfile
type BunLockfile struct {
contents []byte
}

var _ Lockfile = (*BunLockfile)(nil)

// ResolvePackage Given a package and version returns the key, resolved version, and if it was found
func (l *BunLockfile) ResolvePackage(_ turbopath.AnchoredUnixPath, _ string, _ string) (Package, error) {
// This is only used when doing calculating the transitive deps, but Rust
// implementations do this calculation on the Rust side.
panic("Unreachable")
}

// AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package
func (l *BunLockfile) AllDependencies(_ string) (map[string]string, bool) {
// This is only used when doing calculating the transitive deps, but Rust
// implementations do this calculation on the Rust side.
panic("Unreachable")
}

// DecodeBunLockfile Takes the contents of a bun lockfile and returns a struct representation
func DecodeBunLockfile(contents []byte) (*BunLockfile, error) {
return &BunLockfile{contents: contents}, nil
}

// GlobalChange checks if there are any differences between lockfiles that would completely invalidate
// the cache.
func (l *BunLockfile) GlobalChange(other Lockfile) bool {
_, ok := other.(*BunLockfile)
return !ok
}
3 changes: 3 additions & 0 deletions cli/internal/lockfile/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ func AllTransitiveClosures(
if lf, ok := lockFile.(*YarnLockfile); ok {
return rustTransitiveDeps(lf.contents, "yarn", workspaces, nil)
}
if lf, ok := lockFile.(*BunLockfile); ok {
return rustTransitiveDeps(lf.contents, "bun", workspaces, nil)
}

g := new(errgroup.Group)
c := make(chan closureMsg, len(workspaces))
Expand Down
16 changes: 15 additions & 1 deletion cli/internal/packagemanager/berry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import (
"github.com/vercel/turbo/cli/internal/turbopath"
)

const berryLockfile = "yarn.lock"

var nodejsBerry = PackageManager{
Name: "nodejs-berry",
Slug: "yarn",
Command: "yarn",
Specfile: "package.json",
Lockfile: "yarn.lock",
Lockfile: berryLockfile,
PackageDir: "node_modules",
ArgSeparator: func(_userArgs []string) []string { return nil },

Expand Down Expand Up @@ -43,6 +45,18 @@ var nodejsBerry = PackageManager{
return true, nil
},

GetLockfileName: func(_ turbopath.AbsoluteSystemPath) string {
return berryLockfile
},

GetLockfilePath: func(projectDirectory turbopath.AbsoluteSystemPath) turbopath.AbsoluteSystemPath {
return projectDirectory.UntypedJoin(berryLockfile)
},

GetLockfileContents: func(projectDirectory turbopath.AbsoluteSystemPath) ([]byte, error) {
return projectDirectory.UntypedJoin(berryLockfile).ReadFile()
},

UnmarshalLockfile: func(rootPackageJSON *fs.PackageJSON, contents []byte) (lockfile.Lockfile, error) {
var resolutions map[string]string
if untypedResolutions, ok := rootPackageJSON.RawJSON["resolutions"]; ok {
Expand Down
81 changes: 81 additions & 0 deletions cli/internal/packagemanager/bun.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package packagemanager

import (
"fmt"
"os/exec"

"github.com/vercel/turbo/cli/internal/fs"
"github.com/vercel/turbo/cli/internal/lockfile"
"github.com/vercel/turbo/cli/internal/turbopath"
)

const command = "bun"
const bunLockfile = "bun.lockb"

func getLockfilePath(rootPath turbopath.AbsoluteSystemPath) turbopath.AbsoluteSystemPath {
return rootPath.UntypedJoin(bunLockfile)
}

var nodejsBun = PackageManager{
Name: "nodejs-bun",
Slug: "bun",
Command: command,
Specfile: "package.json",
Lockfile: bunLockfile,
PackageDir: "node_modules",
ArgSeparator: func(userArgs []string) []string {
// Bun swallows a single "--" token. If the user is passing "--", we need
// to prepend our own so that the user's doesn't get swallowed. If they are not
// passing their own, we don't need the "--" token and can avoid the warning.
for _, arg := range userArgs {
if arg == "--" {
return []string{"--"}
}
}
return nil
},

getWorkspaceGlobs: func(rootpath turbopath.AbsoluteSystemPath) ([]string, error) {
pkg, err := fs.ReadPackageJSON(rootpath.UntypedJoin("package.json"))
if err != nil {
return nil, fmt.Errorf("package.json: %w", err)
}
if len(pkg.Workspaces) == 0 {
return nil, fmt.Errorf("package.json: no workspaces found. Turborepo requires Bun workspaces to be defined in the root package.json")
}
return pkg.Workspaces, nil
},

getWorkspaceIgnores: func(pm PackageManager, rootpath turbopath.AbsoluteSystemPath) ([]string, error) {
// Matches upstream values:
// Key code: https://github.com/oven-sh/bun/blob/f267c1d097923a2d2992f9f60a6dd365fe706512/src/install/lockfile.zig#L3057
return []string{
"**/node_modules",
"**/.git",
}, nil
},

canPrune: func(cwd turbopath.AbsoluteSystemPath) (bool, error) {
return false, nil
},

GetLockfileName: func(rootPath turbopath.AbsoluteSystemPath) string {
return bunLockfile
},

GetLockfilePath: func(rootPath turbopath.AbsoluteSystemPath) turbopath.AbsoluteSystemPath {
return getLockfilePath(rootPath)
},

GetLockfileContents: func(projectDirectory turbopath.AbsoluteSystemPath) ([]byte, error) {
lockfilePath := getLockfilePath(projectDirectory)
nathanhammond marked this conversation as resolved.
Show resolved Hide resolved
cmd := exec.Command(command, lockfilePath.ToString())
cmd.Dir = projectDirectory.ToString()

return cmd.Output()
},

UnmarshalLockfile: func(_rootPackageJSON *fs.PackageJSON, contents []byte) (lockfile.Lockfile, error) {
return lockfile.DecodeBunLockfile(contents)
},
}
16 changes: 15 additions & 1 deletion cli/internal/packagemanager/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
"github.com/vercel/turbo/cli/internal/turbopath"
)

const npmLockfile = "package-lock.json"

var nodejsNpm = PackageManager{
Name: "nodejs-npm",
Slug: "npm",
Command: "npm",
Specfile: "package.json",
Lockfile: "package-lock.json",
Lockfile: npmLockfile,
PackageDir: "node_modules",
ArgSeparator: func(_userArgs []string) []string { return []string{"--"} },

Expand Down Expand Up @@ -42,6 +44,18 @@ var nodejsNpm = PackageManager{
return true, nil
},

GetLockfileName: func(_ turbopath.AbsoluteSystemPath) string {
return npmLockfile
},

GetLockfilePath: func(projectDirectory turbopath.AbsoluteSystemPath) turbopath.AbsoluteSystemPath {
return projectDirectory.UntypedJoin(npmLockfile)
},

GetLockfileContents: func(projectDirectory turbopath.AbsoluteSystemPath) ([]byte, error) {
return projectDirectory.UntypedJoin(npmLockfile).ReadFile()
},
nathanhammond marked this conversation as resolved.
Show resolved Hide resolved

UnmarshalLockfile: func(_rootPackageJSON *fs.PackageJSON, contents []byte) (lockfile.Lockfile, error) {
return lockfile.DecodeNpmLockfile(contents)
},
Expand Down
Loading
Loading