Skip to content

Commit

Permalink
new: Add Bun tier 1 support. (#1163)
Browse files Browse the repository at this point in the history
* Add tier 1.

* Update tests.

* Bump version.

* Fix tests.
  • Loading branch information
milesj committed Nov 20, 2023
1 parent 3211ede commit dd7e02a
Show file tree
Hide file tree
Showing 82 changed files with 436 additions and 204 deletions.
22 changes: 14 additions & 8 deletions .yarn/versions/fd881e15.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
releases:
"@moonrepo/cli": minor
"@moonrepo/core-linux-arm64-gnu": minor
"@moonrepo/core-linux-arm64-musl": minor
"@moonrepo/core-linux-x64-gnu": minor
"@moonrepo/core-linux-x64-musl": minor
"@moonrepo/core-macos-arm64": minor
"@moonrepo/core-macos-x64": minor
"@moonrepo/core-windows-x64-msvc": minor
'@moonrepo/cli': minor
'@moonrepo/core-linux-arm64-gnu': minor
'@moonrepo/core-linux-arm64-musl': minor
'@moonrepo/core-linux-x64-gnu': minor
'@moonrepo/core-linux-x64-musl': minor
'@moonrepo/core-macos-arm64': minor
'@moonrepo/core-macos-x64': minor
'@moonrepo/core-windows-x64-msvc': minor
'@moonrepo/types': minor

declined:
- '@moonrepo/report'
- '@moonrepo/runtime'
- website
23 changes: 23 additions & 0 deletions Cargo.lock

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

6 changes: 6 additions & 0 deletions crates/bun/lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ publish = false

[dependencies]
moon_lang = { path = "../../core/lang" }
moon_utils = { path = "../../core/utils" }
cached = { workspace = true }
miette = { workspace = true }
once_cell = { workspace = true }
rustc-hash = { workspace = true }
yarn-lock-parser = "0.5.0"
53 changes: 53 additions & 0 deletions crates/bun/lang/src/bun_lockb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use cached::proc_macro::cached;
use miette::IntoDiagnostic;
use moon_lang::LockfileDependencyVersions;
use moon_utils::regex;
use once_cell::sync::Lazy;
use rustc_hash::FxHashMap;
use yarn_lock_parser::{parse_str, Entry};

static REPLACE_WS_VERSION: Lazy<regex::Regex> =
Lazy::new(|| regex::create_regex("version \"workspace:([^\"]+)\"").unwrap());

#[cached(result)]
pub fn load_lockfile_dependencies(
lockfile_text: String,
) -> miette::Result<LockfileDependencyVersions> {
let mut deps: LockfileDependencyVersions = FxHashMap::default();

// Lockfile explodes: https://github.com/robertohuertasm/yarn-lock-parser/issues/15
let mut lockfile_text = lockfile_text
.lines()
.filter_map(|line| {
if line.starts_with("# bun") {
None
} else if line.contains("version \"workspace:") {
Some(
REPLACE_WS_VERSION
.replace(line, "version \"0.0.0\"")
.to_string(),
)
} else {
Some(line.to_owned())
}
})
.collect::<Vec<_>>()
.join("\n");

lockfile_text.push('\n');

// Bun lockfiles are binary, but can be represented as text in Yarn v1 format!
let entries: Vec<Entry> = parse_str(&lockfile_text).into_diagnostic()?;

for entry in entries {
// All workspace dependencies have empty integrities, so we will skip them
if entry.integrity.is_empty() {
continue;
}

let dep = deps.entry(entry.name.to_owned()).or_default();
dep.push(entry.integrity.to_owned());
}

Ok(deps)
}
4 changes: 4 additions & 0 deletions crates/bun/lang/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
mod bun_lockb;

use moon_lang::{DependencyManager, Language};

pub use bun_lockb::*;

pub const BUN: Language = Language {
binary: "bun",
file_exts: &["js", "jsx", "cjs", "mjs", "ts", "tsx", "cts", "mts"],
Expand Down
15 changes: 15 additions & 0 deletions crates/bun/tool/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "moon_bun_tool"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
moon_config = { path = "../../../nextgen/config" }
moon_logger = { path = "../../core/logger" }
moon_platform_runtime = { path = "../../../nextgen/platform-runtime" }
moon_terminal = { path = "../../core/terminal" }
moon_tool = { path = "../../core/tool" }
miette = { workspace = true }
proto_core = { workspace = true }
rustc-hash = { workspace = true }
101 changes: 101 additions & 0 deletions crates/bun/tool/src/bun_tool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use moon_config::BunConfig;
use moon_logger::debug;
use moon_platform_runtime::RuntimeReq;
use moon_terminal::{print_checkpoint, Checkpoint};
use moon_tool::{async_trait, load_tool_plugin, use_global_tool_on_path, Tool};
use proto_core::{Id, ProtoEnvironment, Tool as ProtoTool, UnresolvedVersionSpec};
use rustc_hash::FxHashMap;
use std::path::PathBuf;

pub struct BunTool {
pub config: BunConfig,

pub global: bool,

pub tool: ProtoTool,
}

impl BunTool {
pub async fn new(
proto: &ProtoEnvironment,
config: &BunConfig,
req: &RuntimeReq,
) -> miette::Result<BunTool> {
let mut bun = BunTool {
config: config.to_owned(),
global: false,
tool: load_tool_plugin(&Id::raw("bun"), proto, config.plugin.as_ref().unwrap()).await?,
};

if use_global_tool_on_path() || req.is_global() {
bun.global = true;
bun.config.version = None;
} else {
bun.config.version = req.to_spec();
};

Ok(bun)
}
}

#[async_trait]
impl Tool for BunTool {
fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
self
}

fn get_bin_path(&self) -> miette::Result<PathBuf> {
Ok(PathBuf::from("bun"))
}

async fn setup(
&mut self,
last_versions: &mut FxHashMap<String, UnresolvedVersionSpec>,
) -> miette::Result<u8> {
let mut installed = 0;

let Some(version) = &self.config.version else {
return Ok(installed);
};

if self.global {
debug!("Using global binary in PATH");
} else if self.tool.is_setup(version).await? {
debug!("Bun has already been setup");

// When offline and the tool doesn't exist, fallback to the global binary
} else if proto_core::is_offline() {
debug!(
"No internet connection and Bun has not been setup, falling back to global binary in PATH"
);

self.global = true;

// Otherwise try and install the tool
} else {
let setup = match last_versions.get("bun") {
Some(last) => version != last,
None => true,
};

if setup || !self.tool.get_tool_dir().exists() {
print_checkpoint(format!("installing bun {version}"), Checkpoint::Setup);

if self.tool.setup(version, false).await? {
last_versions.insert("bun".into(), version.to_owned());
installed += 1;
}
}
}

self.tool.locate_globals_dir().await?;

Ok(installed)
}

async fn teardown(&mut self) -> miette::Result<()> {
self.tool.teardown().await?;

Ok(())
}
}
3 changes: 3 additions & 0 deletions crates/bun/tool/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod bun_tool;

pub use bun_tool::*;
3 changes: 3 additions & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ moon_action_graph = { path = "../../nextgen/action-graph" }
moon_action_pipeline = { path = "../core/action-pipeline" }
moon_actions = { path = "../core/actions" }
moon_api = { path = "../../nextgen/api" }
moon_bun_lang = { path = "../bun/lang" }
# moon_bun_platform = { path = "../bun/platform" }
moon_bun_tool = { path = "../bun/tool" }
moon_cache = { path = "../../nextgen/cache" }
moon_codegen = { path = "../../nextgen/codegen" }
moon_common = { path = "../../nextgen/common" }
Expand Down
6 changes: 6 additions & 0 deletions crates/cli/src/commands/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use starbase::system;
#[value(rename_all = "lowercase")]
pub enum BinTool {
// JavaScript
Bun,
Node,
Npm,
Pnpm,
Expand Down Expand Up @@ -51,6 +52,11 @@ fn not_configured() -> ! {
#[system]
pub async fn bin(args: ArgsRef<BinArgs>) {
match &args.tool {
BinTool::Bun => {
let bun = PlatformManager::read().get(PlatformType::Bun)?.get_tool()?;

is_installed(*bun);
}
BinTool::Node => {
let node = PlatformManager::read()
.get(PlatformType::Node)?
Expand Down
24 changes: 24 additions & 0 deletions crates/cli/src/commands/docker/prune.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::MANIFEST_NAME;
use crate::commands::docker::scaffold::DockerManifest;
use moon::generate_project_graph;
use moon_bun_tool::BunTool;
use moon_config::PlatformType;
use moon_node_lang::{PackageJson, NODE};
use moon_node_tool::NodeTool;
Expand All @@ -17,6 +18,16 @@ use starbase_utils::fs;
use starbase_utils::json;
use std::path::Path;

pub async fn prune_bun(
_bun: &BunTool,
_workspace_root: &Path,
_project_graph: &ProjectGraph,
_manifest: &DockerManifest,
) -> AppResult {
// TODO
Ok(())
}

pub async fn prune_node(
node: &NodeTool,
workspace_root: &Path,
Expand Down Expand Up @@ -87,6 +98,19 @@ pub async fn prune(workspace: ResourceMut<Workspace>) {
let platform = PlatformManager::read().get(platform_type)?;

match platform.get_type() {
PlatformType::Bun => {
prune_bun(
platform
.get_tool()?
.as_any()
.downcast_ref::<BunTool>()
.unwrap(),
&workspace.root,
&project_graph,
&manifest,
)
.await?;
}
PlatformType::Node => {
prune_node(
platform
Expand Down
2 changes: 2 additions & 0 deletions crates/core/moon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ pub async fn load_workspace_from(path: &Path) -> miette::Result<Workspace> {
// Primarily for testing
registry.reset();

// TODO bun

if let Some(deno_config) = &workspace.toolchain_config.deno {
registry.register(
PlatformType::Deno,
Expand Down
8 changes: 8 additions & 0 deletions crates/core/platform-detector/src/task_platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use moon_config::PlatformType;
use moon_utils::regex::{self, UNIX_SYSTEM_COMMAND, WINDOWS_SYSTEM_COMMAND};
use once_cell::sync::Lazy;

static BUN_COMMANDS: Lazy<regex::Regex> =
Lazy::new(|| regex::create_regex("^(bun|bunx)$").unwrap());

static DENO_COMMANDS: Lazy<regex::Regex> = Lazy::new(|| regex::create_regex("^(deno)$").unwrap());

static RUST_COMMANDS: Lazy<regex::Regex> =
Expand All @@ -16,6 +19,7 @@ fn use_platform_if_enabled(
enabled_platforms: &[PlatformType],
) -> PlatformType {
match platform {
PlatformType::Bun if enabled_platforms.contains(&PlatformType::Bun) => return platform,
PlatformType::Deno if enabled_platforms.contains(&PlatformType::Deno) => return platform,
PlatformType::Node if enabled_platforms.contains(&PlatformType::Node) => return platform,
PlatformType::Rust if enabled_platforms.contains(&PlatformType::Rust) => return platform,
Expand All @@ -30,6 +34,10 @@ pub fn detect_task_platform(
// language: &LanguageType,
enabled_platforms: &[PlatformType],
) -> PlatformType {
if BUN_COMMANDS.is_match(command) {
return use_platform_if_enabled(PlatformType::Bun, enabled_platforms);
}

if DENO_COMMANDS.is_match(command) {
return use_platform_if_enabled(PlatformType::Deno, enabled_platforms);
}
Expand Down
1 change: 1 addition & 0 deletions crates/node/lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"
publish = false

[dependencies]
moon_bun_lang = { path = "../../bun/lang" }
moon_lang = { path = "../../core/lang" }
moon_logger = { path = "../../core/logger" }
moon_utils = { path = "../../core/utils" }
Expand Down
Loading

0 comments on commit dd7e02a

Please sign in to comment.