wasm-rquickjs 0.1.1

Tool for wrapping JavaScript modules as WebAssembly components using the QuickJS engine
Documentation
use anyhow::Context;
use camino::Utf8Path;
use wit_encoder::StandaloneFunc;
use wit_parser::Resolve;

pub fn add_get_script_import(wit_root: &Utf8Path, world: Option<&str>) -> anyhow::Result<()> {
    let mut resolve = Resolve::new();
    let (root_package_id, source_map) = resolve
        .push_path(wit_root)
        .context("Failed to resolve WIT package")?;
    let world_id = resolve
        .select_world(root_package_id, world)
        .context("Failed to select WIT world")?;

    let root_package_name = resolve.packages[root_package_id].name.clone();
    let world_name = resolve.worlds[world_id].name.clone();

    let root_package_path = source_map
        .package_paths(root_package_id)
        .ok_or_else(|| anyhow::anyhow!("Failed to get package paths for root package"))?
        .collect::<Vec<_>>();

    if root_package_path.len() != 1 {
        return Err(anyhow::anyhow!(
            "Expected exactly one path for root package, found {root_package_path:?}",
        ));
    }

    let packages = wit_encoder::packages_from_parsed(&resolve);
    let mut root_package = packages
        .into_iter()
        .find(|pkg| pkg.name().to_string() == root_package_name.to_string())
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Failed to find root package '{}' in the resolved packages",
                root_package_name
            )
        })?;

    let world = root_package
        .items_mut()
        .iter_mut()
        .find_map(|item| match item {
            wit_encoder::PackageItem::World(w) if w.name().raw_name() == world_name => Some(w),
            _ => None,
        })
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Failed to find world '{}' in the root package '{}'",
                world_name,
                root_package_name
            )
        })?;

    let mut get_source_func = StandaloneFunc::new("get-script", false);
    get_source_func.set_result(Some(wit_encoder::Type::String));

    world.function_import(get_source_func);

    crate::write_if_changed(root_package_path[0], root_package.to_string()).context(format!(
        "Overwriting root WIT package at {:?}",
        root_package_path[0]
    ))?;

    Ok(())
}

pub fn add_wizer_init_export(wit_root: &Utf8Path, world: Option<&str>) -> anyhow::Result<()> {
    let mut resolve = Resolve::new();
    let (root_package_id, source_map) = resolve
        .push_path(wit_root)
        .context("Failed to resolve WIT package")?;
    let world_id = resolve
        .select_world(root_package_id, world)
        .context("Failed to select WIT world")?;

    let root_package_name = resolve.packages[root_package_id].name.clone();
    let world_name = resolve.worlds[world_id].name.clone();

    let root_package_path = source_map
        .package_paths(root_package_id)
        .ok_or_else(|| anyhow::anyhow!("Failed to get package paths for root package"))?
        .collect::<Vec<_>>();

    if root_package_path.len() != 1 {
        return Err(anyhow::anyhow!(
            "Expected exactly one path for root package, found {root_package_path:?}",
        ));
    }

    let packages = wit_encoder::packages_from_parsed(&resolve);
    let mut root_package = packages
        .into_iter()
        .find(|pkg| pkg.name().to_string() == root_package_name.to_string())
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Failed to find root package '{}' in the resolved packages",
                root_package_name
            )
        })?;

    let world = root_package
        .items_mut()
        .iter_mut()
        .find_map(|item| match item {
            wit_encoder::PackageItem::World(w) if w.name().raw_name() == world_name => Some(w),
            _ => None,
        })
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Failed to find world '{}' in the root package '{}'",
                world_name,
                root_package_name
            )
        })?;

    let wizer_init_func = StandaloneFunc::new("wizer-initialize", false);
    world.function_export(wizer_init_func);

    crate::write_if_changed(root_package_path[0], root_package.to_string()).context(format!(
        "Overwriting root WIT package at {:?}",
        root_package_path[0]
    ))?;

    Ok(())
}