feat: add NoxaConfig and ResolvedConfig with load()

Introduces config.rs with NoxaConfig (serde Deserialize, all-optional fields,
unknown-field-tolerant), ResolvedConfig (concrete post-merge struct), and
NoxaConfig::load() (explicit path > NOXA_CONFIG env > ./config.json, missing
file returns default). Also adds Debug derives to OutputFormat, Browser, and
PdfModeArg required by NoxaConfig. 4 tests pass.
This commit is contained in:
Jacob Magar 2026-04-11 12:16:56 -04:00
parent cc1617a3a9
commit 3bc6a9920b
2 changed files with 191 additions and 3 deletions

View file

@ -2,6 +2,7 @@
/// CLI entry point -- wires noxa-core and noxa-fetch into a single command.
/// All extraction and fetching logic lives in sibling crates; this is pure plumbing.
mod cloud;
mod config;
use std::io::{self, Read as _};
use std::path::{Path, PathBuf};
@ -285,7 +286,7 @@ struct Cli {
output_dir: Option<PathBuf>,
}
#[derive(Clone, ValueEnum, Deserialize)]
#[derive(Clone, Debug, ValueEnum, Deserialize)]
#[serde(rename_all = "lowercase")]
enum OutputFormat {
Markdown,
@ -295,7 +296,7 @@ enum OutputFormat {
Html,
}
#[derive(Clone, ValueEnum, Deserialize)]
#[derive(Clone, Debug, ValueEnum, Deserialize)]
#[serde(rename_all = "lowercase")]
enum Browser {
Chrome,
@ -303,7 +304,7 @@ enum Browser {
Random,
}
#[derive(Clone, ValueEnum, Default, Deserialize)]
#[derive(Clone, Debug, ValueEnum, Default, Deserialize)]
#[serde(rename_all = "lowercase")]
enum PdfModeArg {
/// Error if PDF has no extractable text (catches scanned PDFs)