Add Phase 1 frxd implementation with conformance test suite
This commit is contained in:
+141
@@ -0,0 +1,141 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use frxd::config::Config;
|
||||
use frxd::crypto::Keypair;
|
||||
use frxd::message::{EXPOSURE_FULL, EXPOSURE_METADATA};
|
||||
use frxd::{commands, node, relay};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
name = "frxd",
|
||||
version,
|
||||
about = "FRX member node — querier, responder, and local index (Draft 0.3)"
|
||||
)]
|
||||
struct Cli {
|
||||
#[arg(long, global = true, default_value = "frxd.toml")]
|
||||
config: PathBuf,
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Command {
|
||||
Init {
|
||||
#[arg(long, default_value = "member")]
|
||||
name: String,
|
||||
#[arg(long, default_value = "127.0.0.1:7701")]
|
||||
listen: String,
|
||||
#[arg(long, default_value = "http://127.0.0.1:7700")]
|
||||
relay: String,
|
||||
#[arg(long, default_value = "./frx-data")]
|
||||
data_dir: String,
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
},
|
||||
Add {
|
||||
path: PathBuf,
|
||||
#[arg(long)]
|
||||
name: Option<String>,
|
||||
#[arg(long)]
|
||||
shared: bool,
|
||||
#[arg(long, value_enum, default_value_t = Exposure::Full)]
|
||||
exposure: Exposure,
|
||||
},
|
||||
Reindex,
|
||||
Search {
|
||||
text: String,
|
||||
#[arg(long, default_value_t = 10)]
|
||||
limit: usize,
|
||||
},
|
||||
Query {
|
||||
text: String,
|
||||
#[arg(long)]
|
||||
max_results: Option<usize>,
|
||||
#[arg(long)]
|
||||
timeout_ms: Option<u64>,
|
||||
#[arg(long)]
|
||||
local_only: bool,
|
||||
},
|
||||
Serve,
|
||||
Relay {
|
||||
#[arg(long, default_value = "127.0.0.1:7700")]
|
||||
listen: String,
|
||||
#[arg(long, default_value_t = relay::DEFAULT_CAPACITY)]
|
||||
capacity: usize,
|
||||
},
|
||||
Status,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, ValueEnum)]
|
||||
enum Exposure {
|
||||
Metadata,
|
||||
Full,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match cli.command {
|
||||
Command::Init {
|
||||
name,
|
||||
listen,
|
||||
relay,
|
||||
data_dir,
|
||||
force,
|
||||
} => {
|
||||
if cli.config.exists() && !force {
|
||||
bail!(
|
||||
"config {} already exists (use --force to overwrite)",
|
||||
cli.config.display()
|
||||
);
|
||||
}
|
||||
let config = Config::new(&name, &listen, &relay, &data_dir);
|
||||
let key = Keypair::generate();
|
||||
config.save_key(&key)?;
|
||||
config.save(&cli.config)?;
|
||||
println!("wrote config {}", cli.config.display());
|
||||
println!("wrote key {}", config.key_path().display());
|
||||
println!("pubkey {}", key.public_hex());
|
||||
println!("data dir {}", config.data_dir().display());
|
||||
}
|
||||
Command::Add {
|
||||
path,
|
||||
name,
|
||||
shared,
|
||||
exposure,
|
||||
} => {
|
||||
let exposure = match exposure {
|
||||
Exposure::Metadata => EXPOSURE_METADATA,
|
||||
Exposure::Full => EXPOSURE_FULL,
|
||||
};
|
||||
commands::add(&cli.config, &path, name, shared, exposure)?;
|
||||
}
|
||||
Command::Reindex => commands::reindex(&cli.config)?,
|
||||
Command::Search { text, limit } => commands::search(&cli.config, &text, limit).await?,
|
||||
Command::Query {
|
||||
text,
|
||||
max_results,
|
||||
timeout_ms,
|
||||
local_only,
|
||||
} => {
|
||||
commands::query(&cli.config, &text, max_results, timeout_ms, !local_only).await?;
|
||||
}
|
||||
Command::Serve => {
|
||||
let config = Config::load(&cli.config)?;
|
||||
let handle = node::Node::start(config).await?;
|
||||
println!("frxd listening on http://{}", handle.addr);
|
||||
println!("pubkey {}", handle.pubkey);
|
||||
println!("control API POST http://{}/v1/local/query", handle.addr);
|
||||
tokio::signal::ctrl_c().await?;
|
||||
}
|
||||
Command::Relay { listen, capacity } => {
|
||||
let (listener, addr) = relay::bind(&listen).await?;
|
||||
println!("relay listening on http://{addr} (capacity {capacity})");
|
||||
relay::run(listener, capacity).await?;
|
||||
}
|
||||
Command::Status => commands::status(&cli.config).await?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user