Files
start-os/core/src/registry/info.rs
Aiden McClelland bcdeabfe85 fix: clap CLI definitions and manpage generation
- add #[group(skip)] to all Parser-derived structs
- fix conflicts_with and arg definitions for correct CLI behavior
- refactor bin entry points to support manpage generation
2026-03-18 23:48:13 -06:00

133 lines
3.6 KiB
Rust

use std::collections::BTreeMap;
use std::path::PathBuf;
use clap::Parser;
use imbl_value::InternedString;
use itertools::Itertools;
use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::context::CliContext;
use crate::prelude::*;
use crate::registry::context::RegistryContext;
use crate::registry::package::index::Category;
use crate::util::DataUrl;
use crate::util::serde::{HandlerExtSerde, WithIoFormat};
pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
ParentHandler::<C, WithIoFormat<Empty>>::new()
.root_handler(
from_fn_async(get_info)
.with_metadata("authenticated", Value::Bool(false))
.with_display_serializable()
.with_about("about.display-registry-info")
.with_call_remote::<CliContext>(),
)
.subcommand(
"set-name",
from_fn_async(set_name)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("about.set-registry-name")
.with_call_remote::<CliContext>(),
)
.subcommand(
"set-icon",
from_fn_async(set_icon)
.with_metadata("admin", Value::Bool(true))
.no_cli(),
)
.subcommand(
"set-icon",
from_fn_async(cli_set_icon)
.no_display()
.with_about("about.set-registry-icon"),
)
}
#[derive(Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryInfo {
pub name: Option<String>,
pub icon: Option<DataUrl<'static>>,
pub categories: BTreeMap<InternedString, Category>,
}
pub async fn get_info(ctx: RegistryContext) -> Result<RegistryInfo, Error> {
let peek = ctx.db.peek().await.into_index();
Ok(RegistryInfo {
name: peek.as_name().de()?,
icon: peek.as_icon().de()?,
categories: peek.as_package().as_categories().de()?,
})
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[group(skip)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetNameParams {
#[arg(help = "help.arg.registry-name")]
pub name: String,
}
pub async fn set_name(
ctx: RegistryContext,
SetNameParams { name }: SetNameParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| db.as_index_mut().as_name_mut().ser(&Some(name)))
.await
.result
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetIconParams {
pub icon: DataUrl<'static>,
}
pub async fn set_icon(
ctx: RegistryContext,
SetIconParams { icon }: SetIconParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| db.as_index_mut().as_icon_mut().ser(&Some(icon)))
.await
.result
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[group(skip)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CliSetIconParams {
#[arg(help = "help.arg.icon-path")]
pub icon: PathBuf,
}
pub async fn cli_set_icon(
HandlerArgs {
context: ctx,
parent_method,
method,
params: CliSetIconParams { icon },
..
}: HandlerArgs<CliContext, CliSetIconParams>,
) -> Result<(), Error> {
let data_url = DataUrl::from_path(icon).await?;
ctx.call_remote::<RegistryContext>(
&parent_method.into_iter().chain(method).join("."),
imbl_value::json!({
"icon": data_url,
}),
)
.await?;
Ok(())
}