use std::path::Path;
use std::sync::Arc;
use deno_runtime::deno_core::{ModuleSpecifier, error::AnyError};
use crate::state::{NoopHost, RuntimeContext, RuntimeHost, RuntimeState};
use crate::version::TANXIUM_VERSION;
use crate::worker::start_worker;
pub struct TanxiumBuilder {
context: RuntimeContext,
host: Arc<dyn RuntimeHost>,
main_worker_all_permissions: bool,
}
impl TanxiumBuilder {
pub fn workspace_dir(mut self, path: impl Into<std::path::PathBuf>) -> Self {
self.context.workspace_dir = Some(path.into());
self
}
pub fn resource_dir(mut self, path: impl Into<std::path::PathBuf>) -> Self {
self.context.resource_dir = Some(path.into());
self
}
pub fn ready(mut self, ready: bool) -> Self {
self.context.ready = ready;
self
}
pub fn host(mut self, host: Arc<dyn RuntimeHost>) -> Self {
self.host = host;
self
}
pub fn allow_main_worker_all_permissions(mut self, allow: bool) -> Self {
self.main_worker_all_permissions = allow;
self
}
pub fn allow_http_imports(mut self, allow: bool) -> Self {
self.context.allow_http_imports = allow;
self
}
pub fn build(self) -> Result<Tanxium, AnyError> {
Ok(Tanxium {
state: Arc::new(RuntimeState::new(self.context)),
host: self.host,
main_worker_all_permissions: self.main_worker_all_permissions,
})
}
}
#[derive(Clone)]
pub struct Tanxium {
state: Arc<RuntimeState>,
host: Arc<dyn RuntimeHost>,
main_worker_all_permissions: bool,
}
impl Tanxium {
pub fn builder() -> TanxiumBuilder {
TanxiumBuilder {
context: RuntimeContext {
app_version: TANXIUM_VERSION.into(),
..Default::default()
},
host: Arc::new(NoopHost),
main_worker_all_permissions: true,
}
}
pub fn run_file(&self, file: impl AsRef<Path>) -> Result<(), AnyError> {
let module = module_specifier_from_file(file)?;
start_worker(
module,
self.state.clone(),
self.host.clone(),
self.main_worker_all_permissions,
)
.map(|_| ())
}
pub fn run_file_blocking(&self, file: impl AsRef<Path>) -> Result<(), AnyError> {
let module = module_specifier_from_file(file)?;
start_worker(
module,
self.state.clone(),
self.host.clone(),
self.main_worker_all_permissions,
)?
.join()
.map_err(|_| AnyError::msg("runtime thread panicked"))
}
pub fn send_event(&self, event: impl Into<String>) {
if let Some(sender) = self
.state
.event_sender
.lock()
.expect("event sender lock poisoned")
.as_ref()
{
let _ = sender.send(event.into());
}
}
pub fn state(&self) -> Arc<RuntimeState> {
self.state.clone()
}
}
fn module_specifier_from_file(file: impl AsRef<Path>) -> Result<ModuleSpecifier, AnyError> {
let file = std::fs::canonicalize(file)?;
ModuleSpecifier::from_file_path(file).map_err(|_| AnyError::msg("invalid entrypoint path"))
}