harn-cli 0.7.26

CLI for the Harn programming language — run, test, REPL, format, and lint
use axum::http::{header, HeaderMap};
use axum::response::{Html, IntoResponse, Response};
use include_dir::{include_dir, Dir};

use super::errors::{internal_error, not_found_error};

pub(super) static PORTAL_DIST: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/portal-dist");

pub(super) async fn index() -> Response {
    match PORTAL_DIST.get_file("index.html") {
        Some(file) => Html(String::from_utf8_lossy(file.contents()).into_owned()).into_response(),
        None => internal_error("portal frontend is not built; run ./scripts/dev_setup.sh or npm --prefix crates/harn-cli/portal run build")
            .into_response(),
    }
}

pub(super) async fn asset(axum::extract::Path(path): axum::extract::Path<String>) -> Response {
    let asset_path = format!("assets/{path}");
    match PORTAL_DIST.get_file(&asset_path) {
        Some(file) => asset_response(file.contents(), content_type_for_path(&asset_path)),
        None => not_found_error(format!("asset not found: {path}")).into_response(),
    }
}

pub(super) fn asset_response(body: &'static [u8], content_type: &'static str) -> Response {
    let mut headers = HeaderMap::new();
    headers.insert(
        header::CONTENT_TYPE,
        content_type.parse().expect("content type"),
    );
    (headers, body).into_response()
}

pub(super) fn content_type_for_path(path: &str) -> &'static str {
    if path.ends_with(".css") {
        "text/css; charset=utf-8"
    } else if path.ends_with(".js") {
        "application/javascript; charset=utf-8"
    } else if path.ends_with(".html") {
        "text/html; charset=utf-8"
    } else if path.ends_with(".svg") {
        "image/svg+xml"
    } else if path.ends_with(".json") {
        "application/json; charset=utf-8"
    } else {
        "application/octet-stream"
    }
}