Skip to main content

systemprompt_cli/commands/core/content/
list.rs

1use super::types::{ContentListOutput, ContentSummary};
2use crate::cli_settings::CliConfig;
3use crate::shared::CommandOutput;
4use anyhow::Result;
5use clap::Args;
6use systemprompt_content::ContentRepository;
7use systemprompt_database::DbPool;
8use systemprompt_identifiers::{LocaleCode, SourceId};
9use systemprompt_runtime::AppContext;
10
11#[derive(Debug, Args)]
12pub struct ListArgs {
13    #[arg(long, help = "Filter by source ID")]
14    pub source: Option<String>,
15
16    #[arg(long, help = "Filter by category ID")]
17    pub category: Option<String>,
18
19    #[arg(long, default_value = "20")]
20    pub limit: i64,
21
22    #[arg(long, default_value = "0")]
23    pub offset: i64,
24}
25
26pub async fn execute(args: ListArgs, config: &CliConfig) -> Result<CommandOutput> {
27    let ctx = AppContext::new().await?;
28    execute_with_pool(args, ctx.db_pool(), config).await
29}
30
31pub async fn execute_with_pool(
32    args: ListArgs,
33    pool: &DbPool,
34    _config: &CliConfig,
35) -> Result<CommandOutput> {
36    let repo = ContentRepository::new(pool)?;
37
38    let items = match &args.source {
39        Some(source_id) => {
40            let source = SourceId::new(source_id.clone());
41            repo.list_by_source(&source, &LocaleCode::new("en")).await?
42        },
43        None => repo.list(args.limit, args.offset).await?,
44    };
45
46    let summaries: Vec<ContentSummary> = items
47        .into_iter()
48        .filter(|c| {
49            args.category.as_ref().is_none_or(|cat| {
50                c.category_id
51                    .as_ref()
52                    .is_some_and(|cid| cid.as_str() == cat)
53            })
54        })
55        .map(|c| ContentSummary {
56            id: c.id,
57            slug: c.slug,
58            title: c.title,
59            kind: c.kind,
60            source_id: c.source_id,
61            category_id: c.category_id,
62            published_at: Some(c.published_at),
63        })
64        .collect();
65
66    let total = summaries.len() as i64;
67
68    let output = ContentListOutput {
69        items: summaries,
70        total,
71        limit: args.limit,
72        offset: args.offset,
73    };
74
75    Ok(CommandOutput::table_of(
76        vec!["id", "title", "kind", "source_id", "published_at"],
77        &output.items,
78    )
79    .with_title("Content"))
80}