use crate::agent::api::ApiError;
use crate::runtime::core::native_executor::execute_wasm_bytes_with_env;
use crate::runtime::runtime_cache::{wasmhub_language, RuntimeCache};
use crate::runtime::wasi::WasiEnv;
use std::path::Path;
use std::sync::{Arc, Mutex};
const JS_SCRIPT_NAME: &str = "_run_.js";
pub fn resolve_runtime(language: &str) -> std::result::Result<&'static str, ApiError> {
match wasmhub_language(language) {
"nodejs" => Ok("nodejs"),
_ => Err(ApiError::BadRequest(format!(
"Unsupported language: '{language}'. Supported languages: javascript, js, nodejs",
))),
}
}
pub fn execute_source(
source: &str,
language: &str,
wasi_env: Arc<Mutex<WasiEnv>>,
work_dir: &Path,
max_memory_pages: Option<u32>,
) -> std::result::Result<i32, ApiError> {
let runtime_name = resolve_runtime(language)?;
std::fs::write(work_dir.join(JS_SCRIPT_NAME), source)
.map_err(|e| ApiError::Internal(format!("Failed to write script: {e}")))?;
let cache = RuntimeCache::new()
.map_err(|e| ApiError::Internal(format!("Runtime cache unavailable: {e}")))?;
let wasm_bytes = cache
.get_runtime(runtime_name)
.map_err(|e| ApiError::Internal(format!("Failed to fetch {runtime_name} runtime: {e}")))?;
let args = vec![
"nodejs-runtime".to_string(),
"run".to_string(),
JS_SCRIPT_NAME.to_string(),
];
execute_wasm_bytes_with_env(&wasm_bytes, wasi_env, None, args, max_memory_pages)
.map_err(|e| ApiError::Internal(e.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resolve_runtime_js_aliases() {
assert_eq!(resolve_runtime("javascript").unwrap(), "nodejs");
assert_eq!(resolve_runtime("js").unwrap(), "nodejs");
assert_eq!(resolve_runtime("nodejs").unwrap(), "nodejs");
}
#[test]
fn test_resolve_runtime_python_unsupported() {
let err = resolve_runtime("python").unwrap_err();
assert_eq!(err.status_code(), 400);
let msg = err.to_string();
assert!(msg.contains("python"), "expected 'python' in: {msg}");
assert!(
msg.contains("javascript"),
"expected 'javascript' in: {msg}"
);
}
#[test]
fn test_resolve_runtime_unknown_unsupported() {
let err = resolve_runtime("ruby").unwrap_err();
assert_eq!(err.status_code(), 400);
assert!(err.to_string().contains("ruby"));
}
#[test]
fn test_resolve_runtime_case_sensitive() {
assert!(resolve_runtime("JavaScript").is_err());
assert!(resolve_runtime("JS").is_err());
assert!(resolve_runtime("NodeJS").is_err());
}
}