use crate::{fs, logger::GRAY, Cli, Commands, Opts};
use anyhow_ext::{anyhow, bail, ensure, Context, Result};
use cargo_metadata::{MetadataCommand, Package as CargoPackage};
use regex::Regex;
use serde::Deserialize;
use std::path::Path;
#[derive(Debug, Clone)]
pub struct Config {
pub cli: Opts,
pub cargo: CargoPackage,
pub leptos: LeptosManifest,
pub watch: bool,
pub target_directory: String,
}
impl Config {
pub fn lib_crate_name(&self) -> String {
match self
.cargo
.targets
.iter()
.find(|t| t.kind.iter().any(|k| k == "cdylib"))
{
Some(lib) => lib.name.replace("-", "_"),
None => self.cargo.name.replace("-", "_"),
}
}
}
pub fn read(cli: &Cli, opts: Opts) -> Result<Config> {
let leptos = read_config("Cargo.toml")
.context(format!("read config: Cargo.toml"))?
.package
.metadata
.leptos;
let style = Path::new(&leptos.style.file);
ensure!(style.exists(), "no css/sass/scss file found at: {style:?}",);
ensure!(style.is_file(), "expected a file, not a dir: {style:?}",);
let watch = match cli.command {
Commands::Watch(_) => true,
_ => false,
};
let workspace = MetadataCommand::new().manifest_path("Cargo.toml").exec()?;
let target_directory = workspace.target_directory.to_string();
let cargo = workspace
.root_package()
.ok_or_else(|| anyhow!("Could not find root package in Cargo.toml"))?
.clone();
Ok(Config {
cli: opts,
cargo,
leptos,
watch,
target_directory,
})
}
fn read_config(file: &str) -> Result<ConfigFile> {
let text = fs::read_to_string(file)?;
let re: Regex = Regex::new(r#"(?m)^\[package.metadata.leptos\]"#).unwrap();
let start = match re.find(&text) {
Some(found) => found.start(),
None => {
bail!(
"Missing Cargo.toml configuration section {}.\n\
Append the output of {} to your Cargo.toml",
GRAY.paint("[package.metadata.leptos]"),
GRAY.paint("cargo leptos config")
)
}
};
log::trace!("Config file content:\n{text}");
let newlines = text[..start].matches('\n').count();
let toml = "\n".repeat(newlines) + &text[start..];
Ok(toml::from_str(&toml)?)
}
#[derive(Deserialize, Debug)]
struct ConfigFile {
pub package: Package,
}
#[derive(Deserialize, Debug)]
struct Package {
metadata: Metadata,
}
#[derive(Deserialize, Debug)]
struct Metadata {
leptos: LeptosManifest,
}
#[derive(Deserialize, Debug, Clone)]
pub struct LeptosManifest {
pub index_file: String,
pub gen_file: String,
pub assets_dir: Option<String>,
pub csr_port: u16,
pub reload_port: u16,
pub style: Style,
}
#[derive(Clone, Deserialize, Debug)]
pub struct Style {
pub file: String,
pub browserquery: String,
}