mod loader;
#[cfg(feature = "swc")]
mod namespaces;
#[cfg(feature = "swc")]
mod parser;
#[cfg(test)]
mod tests;
pub use loader::MacroforgeConfigLoader;
#[cfg(feature = "swc")]
pub use namespaces::extract_expression_namespaces;
use dashmap::DashMap;
use serde::{Deserialize, Serialize};
use std::sync::LazyLock;
pub use macroforge_ts_syn::config::{
ForeignTypeAlias, ForeignTypeConfig, ImportInfo, MacroforgeConfig,
};
pub static CONFIG_CACHE: LazyLock<DashMap<String, MacroforgeConfig>> = LazyLock::new(DashMap::new);
pub fn clear_config_cache() {
CONFIG_CACHE.clear();
}
const CONFIG_FILES: &[&str] = &[
"macroforge.config.ts",
"macroforge.config.mts",
"macroforge.config.js",
"macroforge.config.mjs",
"macroforge.config.cjs",
];
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroConfig {
#[serde(default)]
pub macro_packages: Vec<String>,
#[serde(default)]
pub allow_native_macros: bool,
#[serde(default)]
pub macro_runtime_overrides: std::collections::HashMap<String, RuntimeMode>,
#[serde(default)]
pub limits: ResourceLimits,
#[serde(default)]
pub keep_decorators: bool,
#[serde(default = "macroforge_ts_syn::config::default_generate_convenience_const")]
pub generate_convenience_const: bool,
}
impl Default for MacroConfig {
fn default() -> Self {
Self {
macro_packages: Vec::new(),
allow_native_macros: false,
macro_runtime_overrides: Default::default(),
limits: Default::default(),
keep_decorators: false,
generate_convenience_const: true,
}
}
}
impl From<MacroforgeConfig> for MacroConfig {
fn from(cfg: MacroforgeConfig) -> Self {
MacroConfig {
keep_decorators: cfg.keep_decorators,
generate_convenience_const: cfg.generate_convenience_const,
..Default::default()
}
}
}
impl MacroConfig {
pub fn find_with_root() -> super::error::Result<Option<(Self, std::path::PathBuf)>> {
match MacroforgeConfigLoader::find_with_root()? {
Some((cfg, path)) => Ok(Some((cfg.into(), path))),
None => Ok(None),
}
}
pub fn find_and_load() -> super::error::Result<Option<Self>> {
Ok(Self::find_with_root()?.map(|(cfg, _)| cfg))
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RuntimeMode {
Wasm,
Native,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResourceLimits {
#[serde(default = "default_max_execution_time")]
pub max_execution_time_ms: u64,
#[serde(default = "default_max_memory")]
pub max_memory_bytes: usize,
#[serde(default = "default_max_output_size")]
pub max_output_size: usize,
#[serde(default = "default_max_diagnostics")]
pub max_diagnostics: usize,
}
impl Default for ResourceLimits {
fn default() -> Self {
Self {
max_execution_time_ms: default_max_execution_time(),
max_memory_bytes: default_max_memory(),
max_output_size: default_max_output_size(),
max_diagnostics: default_max_diagnostics(),
}
}
}
fn default_max_execution_time() -> u64 {
5000
}
fn default_max_memory() -> usize {
100 * 1024 * 1024
}
fn default_max_output_size() -> usize {
10 * 1024 * 1024
}
fn default_max_diagnostics() -> usize {
100
}