ppc cli runs

This commit is contained in:
Sebastian Moser
2026-02-18 16:08:39 +01:00
parent 0b7e54dc1d
commit 56f658da1e
15 changed files with 292 additions and 292 deletions

10
crates/marts/Cargo.toml Normal file
View File

@@ -0,0 +1,10 @@
[package]
name = "marts"
description = "marts = mize_parts - parts collection of the Mize framework"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = "4.5.59"
deno_core = "0.385.0"
mize = { path = "../mize/" }

View File

@@ -0,0 +1,60 @@
use clap::{ArgMatches, Command};
use std::collections::HashMap;
use mize::{mize_part, Mize, MizePart, MizeResult};
#[mize_part("cli")]
#[derive(Default)]
pub struct CliPart {
mize: Mize,
cmd: Option<Command>,
actions: HashMap<String, fn(&ArgMatches) -> MizeResult<()>>,
}
pub fn cli(mize: &mut Mize) -> MizeResult<()> {
let cli_part = CliPart {
mize: mize.clone(),
cmd: Some(Command::new("marts-cli")),
actions: HashMap::new(),
};
mize.register_part(Box::new(cli_part))
}
impl MizePart for CliPart {
fn init(&mut self, _mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
fn run(&mut self, _mize: &mut Mize) -> MizeResult<()> {
let matches = self.cmd.take().unwrap().get_matches();
let sub_cmd = matches.subcommand_name().unwrap();
let action = self.actions.get(sub_cmd).unwrap();
action(matches.subcommand_matches(sub_cmd).unwrap())?;
Ok(())
}
fn opts(&self, mize: &mut Mize) {
mize.new_opt("cli.name");
}
}
impl CliPart {
pub fn subcommand(
&mut self,
subcmd: Command,
action: fn(sub_matches: &ArgMatches) -> MizeResult<()>,
) -> &mut Command {
let name = subcmd.get_name().to_string();
let cmd = self.cmd.take().unwrap().subcommand(subcmd);
self.actions.insert(name, action);
self.cmd = Some(cmd);
self.cmd.as_mut().unwrap()
}
pub fn with_cmd(
&mut self,
func: fn(mize: Mize, cmd: Command) -> MizeResult<Command>,
) -> MizeResult<()> {
let cmd = func(self.mize.clone(), self.cmd.take().unwrap())?;
self.cmd = Some(cmd);
Ok(())
}
}

155
crates/marts/src/js/mod.rs Normal file
View File

@@ -0,0 +1,155 @@
use deno_core::error::AnyError;
use deno_core::FsModuleLoader;
use deno_core::{extension, op2, JsRuntime, ModuleSpecifier, PollEventLoopOptions, RuntimeOptions};
use mize::async_trait;
use mize::instance::MizePartCreate;
use mize::{mize_part, Mize, MizePart, MizeResult};
use std::path::Path;
use std::rc::Rc;
#[mize_part("js")]
pub struct JsPart {
mize: Mize,
js_runtime: JsRuntime,
}
// Define your custom ops for the "mize" object inside deno
#[op2(fast)]
fn op_mize_get_part(#[string] name: &str) {
println!("js wants the part {}", name);
}
#[op2]
#[string]
fn op_mize_get_config(#[string] key: &str) -> String {
format!("config_value_for_{}", key)
}
// Create an extension with your custom ops
extension!(mize_ext, ops = [op_mize_get_part, op_mize_get_config]);
impl MizePart for JsPart {
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
println!("js part init");
Ok(())
}
}
fn js(mize: &mut Mize) -> Box<dyn MizePart> {
let mut js_runtime = JsRuntime::new(RuntimeOptions {
module_loader: Some(Rc::new(FsModuleLoader)),
extensions: vec![mize_ext::init_ops()],
..Default::default()
});
let bootstrap_code = r#"
globalThis.mize = {
get_part: (name) => Deno.core.ops.op_mize_get_part(name),
get_config: (key) => Deno.core.ops.op_mize_get_config(key),
version: "1.0.0",
// Add more methods as needed
};
"#;
js_runtime.execute_script("[bootstrap]", bootstrap_code)?;
JsPart { mize, js_runtime }
}
impl JsPart {
pub fn part_from_js_file(
&mut self,
name: &'static str,
path: &'static str,
) -> Box<dyn MizePart + Send + Sync> {
Box::new(PartFromJsFileAdapter {
mize: self.mize.clone(),
name,
js_file: path,
})
}
pub fn runtime(&mut self) -> &mut JsRuntime {
&mut self.js_runtime
}
}
#[mize_part]
struct PartFromJsFileAdapter {
mize: Mize,
name: &'static str,
js_file: &'static str,
}
#[async_trait]
impl MizePart for PartFromJsFileAdapter {
fn deps(&self) -> &'static [&'static str] {
&["js"]
}
fn name(&self) -> &'static str {
self.name
}
async fn async_init(&mut self, mize: &mut Mize) -> MizeResult<()> {
let js = mize.get_part_native::<JsPart>("js")?;
let path = self.js_file;
let js_code = format!(
r#"
import {{ opts, deps, create }} from "{path}";
const isPromise = (value) => {
return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
};
// Call the async function
let create_result = create(mize);
if (isPromise(create_result)) {
create_result = await create_result;
}
const result = {
opts: opts(mize),
deps: deps(mize),
create: create_result,
};
result;
"#
);
// Execute the script
let result = js.runtime().execute_script("[main]", js_code)?;
// Resolve the promise and run event loop
let resolved_value = js.runtime().resolve_value(result).await?;
// Run the event loop to completion
js.runtime()
.run_event_loop(PollEventLoopOptions::default())
.await?;
println!("Execution of part {} completed successfully", self.name());
Ok(())
}
async fn async_run(&mut self, mize: &mut Mize) -> MizeResult<()> {
let js = mize.get_part_native::<JsPart>("js")?;
let path = self.js_file;
let js_code = format!(
r#"
import {{ run }} from "{path}";
const result = run()
result;
"#
);
// Execute the script
let result = js.runtime().execute_script("[main]", js_code)?;
// Resolve the promise and run event loop
let resolved_value = js.runtime.resolve_value(result).await?;
// Run the event loop to completion
js.runtime()
.run_event_loop(PollEventLoopOptions::default())
.await?;
println!("Running of part {} completed successfully", self.name());
Ok(())
}
}

4
crates/marts/src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
mod cli;
pub use cli::*;
//mod js;