mod discovery;
mod js;
mod parse;
mod pkl;
#[cfg(test)]
mod tests;
use std::path::{Path, PathBuf};
use discovery::{resolve_dir_path, resolve_file_path};
use parse::{parse_raw_config_file, try_parse_raw_candidate};
use super::model::{ConfigFeatureFlags, LinterConfig, RawVizeConfig, VizeConfig};
const CONFIG_FILE_NAMES: [&str; 5] = [
"vize.config.pkl",
"vize.config.ts",
"vize.config.js",
"vize.config.mjs",
"vize.config.json",
];
#[derive(Debug, Clone)]
pub struct LoadedConfig {
pub config: VizeConfig,
pub source_path: Option<PathBuf>,
}
#[derive(Debug, Clone)]
pub struct LoadedConfigWithFeatures {
pub config: VizeConfig,
pub source_path: Option<PathBuf>,
pub features: ConfigFeatureFlags,
}
struct LoadedRawConfig {
config: RawVizeConfig,
source_path: Option<PathBuf>,
}
pub fn validate_explicit_config_path(path: &Path) -> Result<(), std::string::String> {
let display = path.display();
if !path.exists() {
return Err(crate::cstr!("config file not found: {display}").into());
}
if path.is_file() {
return parse_raw_config_file(path)
.map(|_| ())
.map_err(|error| crate::cstr!("failed to parse {display}: {error}").into());
}
if path.is_dir() {
for file_name in CONFIG_FILE_NAMES {
let candidate = path.join(file_name);
if candidate.exists() {
let candidate_display = candidate.display();
return parse_raw_config_file(&candidate)
.map(|_| ())
.map_err(|error| {
crate::cstr!("failed to parse {candidate_display}: {error}").into()
});
}
}
return Err(crate::cstr!("no vize config file found under {display}").into());
}
Err(crate::cstr!("config path is neither a file nor a directory: {display}").into())
}
pub fn load_config(path: Option<&Path>) -> VizeConfig {
load_config_with_source(path).config
}
pub fn load_config_with_source(path: Option<&Path>) -> LoadedConfig {
let loaded = load_raw_config_with_source(path);
let (config, _) = loaded.config.into_config_and_features();
LoadedConfig {
config,
source_path: loaded.source_path,
}
}
pub fn load_config_with_features_and_source(path: Option<&Path>) -> LoadedConfigWithFeatures {
let loaded = load_raw_config_with_source(path);
let (config, features) = loaded.config.into_config_and_features();
LoadedConfigWithFeatures {
config,
source_path: loaded.source_path,
features,
}
}
pub fn load_compiler_template_syntax(path: Option<&Path>) -> Option<&'static str> {
load_raw_config_with_source(path)
.config
.compiler
.template_syntax
.map(|template_syntax| template_syntax.as_str())
}
pub fn load_compiler_vue_version(path: Option<&Path>) -> Option<crate::config::VueVersion> {
let loaded = load_raw_config_with_source(path);
let (_, features) = loaded.config.into_config_and_features();
features.vue_version
}
pub fn load_compiler_jsx_mode(path: Option<&Path>) -> Option<crate::config::JsxMode> {
let loaded = load_raw_config_with_source(path);
let (_, features) = loaded.config.into_config_and_features();
features.jsx_mode
}
pub fn load_config_and_linter_with_source(path: Option<&Path>) -> (LoadedConfig, LinterConfig) {
let loaded = load_raw_config_with_source(path);
let linter = LinterConfig::from(loaded.config.linter.clone());
let (config, _) = loaded.config.into_config_and_features();
(
LoadedConfig {
config,
source_path: loaded.source_path,
},
linter,
)
}
pub fn load_config_and_linter_with_features_and_source(
path: Option<&Path>,
) -> (LoadedConfigWithFeatures, LinterConfig) {
let loaded = load_raw_config_with_source(path);
let linter = LinterConfig::from(loaded.config.linter.clone());
let (config, features) = loaded.config.into_config_and_features();
(
LoadedConfigWithFeatures {
config,
source_path: loaded.source_path,
features,
},
linter,
)
}
pub fn load_linter_config(path: Option<&Path>) -> LinterConfig {
LinterConfig::from(load_raw_config_with_source(path).config.linter)
}
fn load_raw_config_with_source(path: Option<&Path>) -> LoadedRawConfig {
let base = path
.map(Path::to_path_buf)
.unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
if let Some(file_path) = resolve_file_path(&base) {
return LoadedRawConfig {
config: parse_raw_config_file(&file_path).unwrap_or_default(),
source_path: Some(file_path),
};
}
let Some(dir_path) = resolve_dir_path(&base) else {
return LoadedRawConfig {
config: RawVizeConfig::default(),
source_path: None,
};
};
for file_name in CONFIG_FILE_NAMES {
let candidate = dir_path.join(file_name);
if !candidate.exists() {
continue;
}
if let Some(config) = try_parse_raw_candidate(&candidate) {
return LoadedRawConfig {
config,
source_path: Some(candidate),
};
}
}
LoadedRawConfig {
config: RawVizeConfig::default(),
source_path: None,
}
}