Skip to main content

systemprompt_cli/commands/core/content/
list.rs

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