Browse Source

WIP: basic API

develop
chodak166 4 months ago
parent
commit
ea48899627
  1. 5
      apps/app_cli/src/commands.rs
  2. 77
      apps/app_cli/src/commands/list_dicts.rs
  3. 3
      apps/app_cli/src/config.rs
  4. 3
      config.toml
  5. 4
      lib/src/dictionary.rs
  6. 30
      lib/src/dictionary/infrastructure/sqlite_dict_repository.rs

5
apps/app_cli/src/commands.rs

@ -1,6 +1,7 @@
pub mod decode;
pub mod encode;
pub mod import_dict;
pub mod list_dicts;
use crate::config::AppConfig;
use crate::container::Container;
@ -22,6 +23,9 @@ pub enum Command {
/// Import dictionary
ImportDict(import_dict::ImportDictCmd),
/// List all dictionaries
ListDicts(list_dicts::ListDictsCmd),
}
impl Command {
@ -30,6 +34,7 @@ impl Command {
Command::Decode(cmd) => Box::new(cmd),
Command::Encode(cmd) => Box::new(cmd),
Command::ImportDict(cmd) => Box::new(cmd),
Command::ListDicts(cmd) => Box::new(cmd),
}
}
}

77
apps/app_cli/src/commands/list_dicts.rs

@ -0,0 +1,77 @@
use crate::commands::{ClapArgs, Configurable, Executable};
use crate::config::AppConfig;
use crate::container::Container;
use anyhow::Result;
use async_trait::async_trait;
use config::ConfigBuilder;
use config::builder::DefaultState;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
pub show_counts: bool,
}
#[derive(ClapArgs, Debug, Clone)]
pub struct ListDictsCmd {
#[arg(short, long, help = defaults::HELP_LIST_DICTS_COUNTS)]
pub show_counts: bool,
}
impl Configurable for ListDictsCmd {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
) -> Result<ConfigBuilder<DefaultState>> {
builder
.set_default("list_dicts.show_counts", defaults::SHOW_COUNTS)
.map_err(Into::into)
}
fn apply_overrides(
&self,
builder: ConfigBuilder<DefaultState>,
) -> Result<ConfigBuilder<DefaultState>> {
builder
.set_override("list_dicts.show_counts", self.show_counts)
.map_err(Into::into)
}
}
#[async_trait]
impl Executable for ListDictsCmd {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()> {
let config = config
.list_dicts
.as_ref()
.expect("ListDicts config not set");
let repo = container.create_dict_repo("default").await?;
let dicts = repo.fetch_dicts().await?;
if dicts.is_empty() {
println!("No dictionaries found.");
return Ok(());
}
println!("Dictionaries:");
for dict_name in &dicts {
if config.show_counts {
let count_repo = container.create_dict_repo(dict_name).await?;
let count = count_repo.count_entries().await?;
println!(" - {} ({} entries)", dict_name, count);
} else {
println!(" - {}", dict_name);
}
}
Ok(())
}
}
mod defaults {
use const_format::formatcp;
pub const SHOW_COUNTS: bool = false;
pub const HELP_LIST_DICTS_COUNTS: &str = formatcp!("Show entry counts for each dictionary");
}

3
apps/app_cli/src/config.rs

@ -1,5 +1,4 @@
use crate::commands::*;
// use crate::commands::{Configurable, GlobalArgs};
use anyhow::{Context, Result};
use config::{Config, Environment, File};
use serde::Deserialize;
@ -12,6 +11,8 @@ pub struct AppConfig {
pub encode: Option<encode::Config>,
#[serde(default)]
pub import_dict: Option<import_dict::Config>,
#[serde(default)]
pub list_dicts: Option<list_dicts::Config>,
pub log_level: String,
}

3
config.toml

@ -1,4 +1 @@
log_level = "info"
[decode]
input = "CONFIGTEST"

4
lib/src/dictionary.rs

@ -54,6 +54,10 @@ pub trait DictRepository: Send + Sync {
fn use_dict(&mut self, name: &str);
async fn create_dict(&self) -> Result<(), RepositoryError>;
async fn fetch_dicts(&self) -> Result<Vec<String>, RepositoryError>;
async fn count_entries(&self) -> Result<u64, RepositoryError>;
/// "Upsert" logic:
/// - If entry exists (by text), update metadata.
/// - If not, insert new.

30
lib/src/dictionary/infrastructure/sqlite_dict_repository.rs

@ -93,6 +93,10 @@ impl SqliteDictRepository {
#[async_trait::async_trait]
impl DictRepository for SqliteDictRepository {
fn use_dict(&mut self, name: &str) {
self.dict_name = name.to_string();
}
async fn create_dict(&self) -> Result<(), RepositoryError> {
sqlx::query("INSERT OR IGNORE INTO dictionaries (name) VALUES (?)")
.bind(&self.dict_name)
@ -102,8 +106,30 @@ impl DictRepository for SqliteDictRepository {
Ok(())
}
fn use_dict(&mut self, name: &str) {
self.dict_name = name.to_string();
async fn fetch_dicts(&self) -> Result<Vec<String>, RepositoryError> {
let rows = sqlx::query("SELECT name FROM dictionaries ORDER BY name")
.fetch_all(&self.pool)
.await
.map_err(|e| RepositoryError::StorageError(e.to_string()))?;
let dicts = rows.iter().map(|row| row.get("name")).collect();
Ok(dicts)
}
async fn count_entries(&self) -> Result<u64, RepositoryError> {
let dict_id = self.get_dict_id().await?;
let row = sqlx::query("SELECT COUNT(*) as count FROM entries WHERE dictionary_id = ?")
.bind(dict_id)
.fetch_optional(&self.pool)
.await
.map_err(|e| RepositoryError::StorageError(e.to_string()))?;
match row {
Some(r) => Ok(r.get::<i64, _>("count") as u64),
None => Ok(0),
}
}
async fn save_entries(&self, entries: &[DictEntry]) -> Result<(), RepositoryError> {

Loading…
Cancel
Save