ordinary 0.11.1

Ordinary CLI
Documentation
// Copyright (C) 2026 The Ordinary Authors.
//
// SPDX-License-Identifier: BSD-3-Clause

use crate::HostCallFlags;
use crate::cmds::accounts::get_current_account;
use clap::Subcommand;
use serde_json::Value;
use tracing::instrument;

#[derive(Clone, Debug)]
pub enum UuidVersion {
    /// random
    V4,
    /// unix timestamp
    V7,
}

impl UuidVersion {
    fn as_str(&self) -> &'static str {
        match self {
            Self::V4 => "v4",
            Self::V7 => "v7",
        }
    }
}

impl clap::ValueEnum for UuidVersion {
    fn value_variants<'a>() -> &'a [Self] {
        &[Self::V4, Self::V7]
    }

    fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
        match self {
            Self::V4 => Some(clap::builder::PossibleValue::new("v4")),
            Self::V7 => Some(clap::builder::PossibleValue::new("v7")),
        }
    }
}

#[derive(Subcommand, Debug)]
pub enum Database {
    /// seed the database if the `seed_path` is set
    Seed {
        #[command(flatten)]
        host: HostCallFlags,
    },

    Models {
        #[command(subcommand)]
        models: Models,
    },

    /// manage model items for the application running on an `ordinaryd` instance
    Items {
        #[command(subcommand)]
        items: Items,
    },
}

#[derive(Subcommand, Debug)]
pub enum Models {
    /// add a new model to your Ordinary project
    Add {
        /// name of the model
        name: String,

        /// UUID version
        uuid_version: Option<UuidVersion>,
    },
}

#[derive(Subcommand, Debug)]
pub enum Items {
    /// list model items for the application running on an `ordinaryd` instance
    #[clap(visible_aliases(["ls"]))]
    List {
        #[command(flatten)]
        host: HostCallFlags,

        /// name of the model
        name: String,

        /// for applications that need to consume stdio or pipe to `jq`
        #[arg(long, default_value_t = false)]
        json: bool,
    },
}

impl Database {
    #[instrument(skip_all, name = "database")]
    pub async fn handle(&self, project: &str) -> anyhow::Result<()> {
        match self {
            Self::Seed { host } => {
                let account = get_current_account(host.insecure)?;
                let client = host.client(&account)?;

                client.database_items_seed(project).await?;
            }
            Self::Models { models } => match models {
                Models::Add { name, uuid_version } => {
                    ordinary_modify::add_model(
                        project,
                        name,
                        uuid_version.to_owned().map(|uv| uv.as_str()),
                    )?;
                }
            },
            Self::Items { items: item } => match item {
                Items::List { name, json, host } => {
                    let account = get_current_account(host.insecure)?;
                    let client = host.client(&account)?;

                    let res = client.database_items_list(project, name).await?;

                    if json == &true {
                        print!("{res}");
                    } else {
                        let items: Vec<Value> = serde_json::from_str(&res)?;

                        for item in items {
                            tracing::info!(%item);
                        }
                    }
                }
            },
        }

        Ok(())
    }
}