systemprompt_cli/commands/core/content/
mod.rs1pub mod analytics;
2pub mod delete;
3pub mod delete_source;
4mod edit;
5pub mod files;
6pub mod ingest;
7pub mod link;
8pub mod list;
9pub mod popular;
10pub mod publish;
11pub mod search;
12pub mod show;
13pub mod status;
14pub mod types;
15pub mod verify;
16
17use crate::cli_settings::{get_global_config, CliConfig};
18use crate::shared::render_result;
19use anyhow::{bail, Context, Result};
20use clap::Subcommand;
21use systemprompt_runtime::DatabaseContext;
22
23#[derive(Debug, Subcommand)]
24pub enum ContentCommands {
25 #[command(about = "List content with pagination")]
26 List(list::ListArgs),
27
28 #[command(about = "Show content details")]
29 Show(show::ShowArgs),
30
31 #[command(about = "Search content")]
32 Search(search::SearchArgs),
33
34 #[command(about = "Ingest markdown files from directory")]
35 Ingest(ingest::IngestArgs),
36
37 #[command(about = "Edit content fields")]
38 Edit(edit::EditArgs),
39
40 #[command(about = "Delete content by ID")]
41 Delete(delete::DeleteArgs),
42
43 #[command(name = "delete-source", about = "Delete all content from a source")]
44 DeleteSource(delete_source::DeleteSourceArgs),
45
46 #[command(about = "Get popular content")]
47 Popular(popular::PopularArgs),
48
49 #[command(about = "Verify content is published and accessible")]
50 Verify(verify::VerifyArgs),
51
52 #[command(about = "Show content health status for a source")]
53 Status(status::StatusArgs),
54
55 #[command(subcommand, about = "Link generation and management")]
56 Link(link::LinkCommands),
57
58 #[command(subcommand, about = "Content analytics")]
59 Analytics(analytics::AnalyticsCommands),
60
61 #[command(subcommand, about = "Content-file operations (link, unlink, featured)")]
62 Files(files::ContentFilesCommands),
63
64 #[command(about = "Publish static content (ingest, prerender, sitemap)")]
65 Publish(publish::PublishArgs),
66
67 #[command(about = "Alias for publish", hide = true)]
68 Generate(publish::PublishArgs),
69}
70
71pub async fn execute(command: ContentCommands) -> Result<()> {
72 let config = get_global_config();
73 execute_with_config(command, &config).await
74}
75
76pub async fn execute_with_config(command: ContentCommands, config: &CliConfig) -> Result<()> {
77 match command {
78 ContentCommands::List(args) => {
79 let result = list::execute(args, config)
80 .await
81 .context("Failed to list content")?;
82 render_result(&result);
83 },
84 ContentCommands::Show(args) => {
85 let result = show::execute(args, config)
86 .await
87 .context("Failed to show content")?;
88 render_result(&result);
89 },
90 ContentCommands::Search(args) => {
91 let result = search::execute(args, config)
92 .await
93 .context("Failed to search content")?;
94 render_result(&result);
95 },
96 ContentCommands::Ingest(args) => {
97 let result = ingest::execute(args, config)
98 .await
99 .context("Failed to ingest content")?;
100 match result {
101 ingest::IngestResult::Single(r) => render_result(&r),
102 ingest::IngestResult::All(r) => render_result(&r),
103 }
104 },
105 ContentCommands::Edit(args) => {
106 let result = edit::execute(args, config)
107 .await
108 .context("Failed to edit content")?;
109 render_result(&result);
110 },
111 ContentCommands::Delete(args) => {
112 let result = delete::execute(args, config)
113 .await
114 .context("Failed to delete content")?;
115 render_result(&result);
116 },
117 ContentCommands::DeleteSource(args) => {
118 let result = delete_source::execute(args, config)
119 .await
120 .context("Failed to delete source content")?;
121 render_result(&result);
122 },
123 ContentCommands::Popular(args) => {
124 let result = popular::execute(args, config)
125 .await
126 .context("Failed to get popular content")?;
127 render_result(&result);
128 },
129 ContentCommands::Verify(args) => {
130 let result = verify::execute(args, config)
131 .await
132 .context("Failed to verify content")?;
133 render_result(&result);
134 },
135 ContentCommands::Status(args) => {
136 let result = status::execute(args, config)
137 .await
138 .context("Failed to get content status")?;
139 render_result(&result);
140 },
141 ContentCommands::Link(cmd) => {
142 link::execute(cmd, config).await?;
143 },
144 ContentCommands::Analytics(cmd) => {
145 analytics::execute(cmd, config).await?;
146 },
147 ContentCommands::Files(cmd) => {
148 files::execute(cmd, config).await?;
149 },
150 ContentCommands::Publish(args) | ContentCommands::Generate(args) => {
151 let result = publish::execute(args, config)
152 .await
153 .context("Failed to publish content")?;
154 render_result(&result);
155 },
156 }
157 Ok(())
158}
159
160pub async fn execute_with_db(
161 command: ContentCommands,
162 db_ctx: &DatabaseContext,
163 config: &CliConfig,
164) -> Result<()> {
165 match command {
166 ContentCommands::List(args) => {
167 let result = list::execute_with_pool(args, db_ctx.db_pool(), config)
168 .await
169 .context("Failed to list content")?;
170 render_result(&result);
171 },
172 ContentCommands::Show(args) => {
173 let result = show::execute_with_pool(args, db_ctx.db_pool(), config)
174 .await
175 .context("Failed to show content")?;
176 render_result(&result);
177 },
178 ContentCommands::Search(args) => {
179 let result = search::execute_with_pool(args, db_ctx.db_pool(), config)
180 .await
181 .context("Failed to search content")?;
182 render_result(&result);
183 },
184 ContentCommands::Popular(args) => {
185 let result = popular::execute_with_pool(args, db_ctx.db_pool(), config)
186 .await
187 .context("Failed to get popular content")?;
188 render_result(&result);
189 },
190 ContentCommands::Status(args) => {
191 let result = status::execute_with_pool(args, db_ctx.db_pool(), config)
192 .await
193 .context("Failed to get content status")?;
194 render_result(&result);
195 },
196 ContentCommands::Analytics(cmd) => {
197 analytics::execute_with_pool(cmd, db_ctx.db_pool(), config).await?;
198 },
199 ContentCommands::Ingest(_)
200 | ContentCommands::Edit(_)
201 | ContentCommands::Delete(_)
202 | ContentCommands::DeleteSource(_)
203 | ContentCommands::Verify(_)
204 | ContentCommands::Link(_)
205 | ContentCommands::Files(_)
206 | ContentCommands::Publish(_)
207 | ContentCommands::Generate(_) => {
208 bail!("This content command requires full profile context")
209 },
210 }
211 Ok(())
212}