systemprompt-generator 0.1.18

Static site generation for systemprompt.io
Documentation
use anyhow::{Context, Result};
use std::path::Path;
use systemprompt_extension::{AssetDefinition, ExtensionRegistry};
use systemprompt_models::AppPaths;
use systemprompt_traits::JobResult;

pub async fn execute_copy_extension_assets() -> Result<JobResult> {
    let start_time = std::time::Instant::now();

    tracing::info!("Copy extension assets job started");

    let paths = AppPaths::get().map_err(|e| anyhow::anyhow!("AppPaths not initialized: {}", e))?;

    let registry = ExtensionRegistry::discover();
    let assets = registry.all_required_assets(paths);

    if assets.is_empty() {
        let duration_ms = start_time.elapsed().as_millis() as u64;
        tracing::info!(duration_ms, "No extension assets to copy");
        return Ok(JobResult::success()
            .with_stats(0, 0)
            .with_duration(duration_ms));
    }

    let dist_dir = paths.web().dist();

    let mut copied = 0u64;
    let mut failed = 0u64;

    for (ext_id, asset) in assets {
        match copy_asset(dist_dir, ext_id, &asset).await {
            Ok(()) => copied += 1,
            Err(e) => {
                if asset.is_required() {
                    return Err(e);
                }
                tracing::warn!(
                    extension = %ext_id,
                    asset = %asset.source().display(),
                    error = %e,
                    "Optional asset copy failed"
                );
                failed += 1;
            },
        }
    }

    let duration_ms = start_time.elapsed().as_millis() as u64;

    tracing::info!(
        copied,
        failed,
        duration_ms,
        "Copy extension assets job completed"
    );

    Ok(JobResult::success()
        .with_stats(copied, failed)
        .with_duration(duration_ms))
}

async fn copy_asset(dist_dir: &Path, ext_id: &str, asset: &AssetDefinition) -> Result<()> {
    let dest_path = dist_dir.join(asset.destination());

    if let Some(parent) = dest_path.parent() {
        tokio::fs::create_dir_all(parent)
            .await
            .with_context(|| format!("Failed to create directory: {}", parent.display()))?;
    }

    tokio::fs::copy(asset.source(), &dest_path)
        .await
        .with_context(|| {
            format!(
                "Failed to copy asset from {} to {}",
                asset.source().display(),
                dest_path.display()
            )
        })?;

    tracing::debug!(
        extension = %ext_id,
        source = %asset.source().display(),
        destination = %dest_path.display(),
        "Copied extension asset"
    );

    Ok(())
}