diff --git a/backend/tests/bun_jobs.rs b/backend/tests/bun_jobs.rs index cf3ce4d350d56..b0faa5a529bba 100644 --- a/backend/tests/bun_jobs.rs +++ b/backend/tests/bun_jobs.rs @@ -1191,6 +1191,49 @@ export function main(name: string) { Ok(()) } +// ============================================================================ +// NPM Dependency Tests +// ============================================================================ + +#[sqlx::test(fixtures("base"))] +async fn test_bun_job_with_cowsay_dep(db: Pool) -> anyhow::Result<()> { + initialize_tracing().await; + let server = ApiServer::start(db.clone()).await?; + let port = server.addr.port(); + + let content = r#" +import * as cowsay from "cowsay"; + +export function main() { + return cowsay.say({ text: "hoisted" }); +} +"# + .to_owned(); + + let job = JobPayload::Code(RawCode { + hash: None, + content, + path: None, + language: ScriptLang::Bun, + lock: None, + concurrency_settings: + windmill_common::runnable_settings::ConcurrencySettings::default().into(), + debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), + cache_ttl: None, + cache_ignore_s3_path: None, + dedicated_worker: None, + }); + + let result = run_job_in_new_worker_until_complete(&db, false, job, port) + .await + .json_result() + .unwrap(); + + let result_str = result.as_str().unwrap(); + assert!(result_str.contains("hoisted"), "cowsay output should contain 'hoisted'"); + Ok(()) +} + /// Tests for RELATIVE_BUN_BUILDER (loader_builder.bun.js) /// These tests verify Bun's behavior for import scanning and package.json generation. /// Purpose: Catch regressions when upgrading Bun versions. diff --git a/backend/windmill-worker/src/bun_executor.rs b/backend/windmill-worker/src/bun_executor.rs index e15aa09b46ddc..702f5a8e4bb08 100644 --- a/backend/windmill-worker/src/bun_executor.rs +++ b/backend/windmill-worker/src/bun_executor.rs @@ -342,7 +342,7 @@ pub async fn install_bun_lockfile( ) -> Result<()> { let mut child_cmd = Command::new(if npm_mode { &*NPM_PATH } else { &*BUN_PATH }); - let mut args = vec!["install", "--save-text-lockfile"]; + let mut args = vec!["install", "--save-text-lockfile", "--linker", "hoisted"]; let no_cache = !npm_mode && *BUN_NO_CACHE; diff --git a/backend/windmill-worker/src/prepare_deps.rs b/backend/windmill-worker/src/prepare_deps.rs index 70b5718cf771e..aa6948628c5fa 100644 --- a/backend/windmill-worker/src/prepare_deps.rs +++ b/backend/windmill-worker/src/prepare_deps.rs @@ -462,7 +462,7 @@ pub async fn prepare_deps_standalone(code: &str, language: &str) -> PrepareRespo .current_dir(&job_dir) .env_clear() .envs(common_bun_proc_envs) - .args(vec!["install"]) + .args(vec!["install", "--linker", "hoisted"]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .output()