~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-cocore

0
0
main
32 lines · 1.3 KB Raw History
//! 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<String, Value>;

/// 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<String> {
    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<String, String> {
    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<Call, String>) -> Result<Handle, String> {
    Ok(match event {
        Event::Start => Handle::new().call(call()?.id("call")),
        Event::Result { result, .. } => Handle::new().result(result.into_result()?).done(),
        _ => Handle::new(),
    })
}