Skip to main content

harmont_cli/cli/
render.rs

1use std::path::PathBuf;
2
3use anyhow::{Context, Result};
4use clap::Parser;
5use hm_dsl_engine::{detect, engine_for};
6
7#[derive(Debug, Clone, Parser)]
8pub struct RenderArgs {
9    /// Pipeline slug to render.
10    #[arg()]
11    pub slug: String,
12
13    /// Source root containing `.hm/` (defaults to cwd).
14    #[arg(short, long)]
15    pub dir: Option<PathBuf>,
16}
17
18/// Render one pipeline's v0 IR JSON to stdout without executing it.
19///
20/// When both Python and TypeScript are present, Python wins (the supported
21/// backend path), matching `hm pipelines`.
22///
23/// # Errors
24///
25/// Returns an error if the language can't be detected, the engine can't start,
26/// or the slug is unknown / fails to render (the available slugs are written to
27/// stderr by the DSL runtime).
28pub async fn run(args: RenderArgs) -> Result<()> {
29    let repo_root = match args.dir {
30        Some(d) => d,
31        None => std::env::current_dir().context("cannot determine current directory")?,
32    };
33
34    let lang =
35        detect::detect_language_python_first(&repo_root).context("detecting pipeline language")?;
36    let engine = engine_for(lang).context("initializing DSL engine")?;
37    let json = engine
38        .render_pipeline_json(&repo_root, &args.slug)
39        .await
40        .with_context(|| format!("rendering pipeline {:?}", args.slug))?;
41
42    // Machine-facing: raw v0 IR JSON on stdout, nothing else.
43    print!("{json}");
44    Ok(())
45}