//! What the cocore modules share: the console's XRPC service, form fields, and one-call actions. use abi::{Call, Event, Handle}; use serde_json::{Map, Value}; /// The console: API keys (did:web:cocore.dev, served at https://cocore.dev). pub const CONSOLE: &str = "did:web:cocore.dev#cocore_console"; /// An action's input: its form fields plus `did` and `now`. pub type Args = Map; /// A field as a trimmed, non-empty string (numbers too, since forms send strings and JSON sends numbers). pub fn field(args: &Args, key: &str) -> Option { match args.get(key)? { Value::String(s) => Some(s.trim().to_string()).filter(|s| !s.is_empty()), Value::Number(n) => Some(n.to_string()), Value::Bool(b) => Some(b.to_string()), _ => None, } } pub fn required(args: &Args, key: &str) -> Result { field(args, key).ok_or_else(|| format!("{key} is required")) } /// One call; its output is the run's result and a failed call the run's error. pub fn once(event: Event, call: impl FnOnce() -> Result) -> Result { Ok(match event { Event::Start => Handle::new().call(call()?.id("call")), Event::Result { result, .. } => Handle::new().result(result.into_result()?).done(), _ => Handle::new(), }) }