Skip to main content

pebble_cms/cli/
mod.rs

1pub mod backup;
2pub mod build;
3pub mod config;
4pub mod deploy;
5pub mod doctor;
6pub mod export;
7pub mod import;
8pub mod import_ghost;
9pub mod import_wordpress;
10pub mod init;
11pub mod migrate;
12pub mod registry;
13pub mod rerender;
14pub mod serve;
15pub mod user;
16
17use clap::{Parser, Subcommand};
18use std::path::PathBuf;
19
20#[derive(Parser)]
21#[command(name = "pebble")]
22#[command(version)]
23#[command(about = "A lightweight personal CMS", long_about = None)]
24pub struct Cli {
25    #[arg(short, long, default_value = "pebble.toml")]
26    pub config: PathBuf,
27
28    #[command(subcommand)]
29    pub command: Option<Commands>,
30}
31
32#[derive(Subcommand)]
33pub enum Commands {
34    /// Initialize a new Pebble site
35    Init {
36        /// Directory to create the site in
37        #[arg(default_value = ".")]
38        path: PathBuf,
39        /// Name of the site
40        #[arg(long)]
41        name: Option<String>,
42    },
43    /// Start the development server
44    Serve {
45        /// Host address to bind to
46        #[arg(short = 'H', long, default_value = "127.0.0.1")]
47        host: String,
48        /// Port to listen on
49        #[arg(short, long, default_value = "3000")]
50        port: u16,
51    },
52    /// Start the production server
53    Deploy {
54        /// Host address to bind to
55        #[arg(short = 'H', long, default_value = "0.0.0.0")]
56        host: String,
57        /// Port to listen on
58        #[arg(short, long, default_value = "8080")]
59        port: u16,
60    },
61    /// Generate a static site
62    Build {
63        /// Output directory for the static files
64        #[arg(short, long, default_value = "./dist")]
65        output: PathBuf,
66        /// Base URL for the generated site
67        #[arg(long)]
68        base_url: Option<String>,
69    },
70    /// Export site content to portable format
71    Export {
72        /// Output directory for exported content
73        #[arg(short, long, default_value = "./export")]
74        output: PathBuf,
75        /// Include draft posts and pages
76        #[arg(long)]
77        include_drafts: bool,
78        /// Include media files
79        #[arg(long)]
80        include_media: bool,
81        /// Export format: pebble, hugo, or zola
82        #[arg(long, default_value = "pebble")]
83        format: String,
84    },
85    /// Import content from an export directory
86    Import {
87        /// Path to the export directory
88        #[arg(default_value = "./export")]
89        path: PathBuf,
90        /// Overwrite existing content with the same slug
91        #[arg(long)]
92        overwrite: bool,
93    },
94    /// Import from a WordPress WXR export file
95    ImportWp {
96        /// Path to the WordPress WXR XML file
97        file: PathBuf,
98        /// Overwrite existing content with the same slug
99        #[arg(long)]
100        overwrite: bool,
101    },
102    /// Import from a Ghost JSON export file
103    ImportGhost {
104        /// Path to the Ghost JSON export file
105        file: PathBuf,
106        /// Overwrite existing content with the same slug
107        #[arg(long)]
108        overwrite: bool,
109    },
110    /// Backup and restore site data
111    Backup {
112        #[command(subcommand)]
113        command: BackupCommand,
114    },
115    /// Run database migrations
116    Migrate {
117        #[command(subcommand)]
118        command: Option<MigrateCommand>,
119    },
120    /// Check system health and configuration
121    Doctor,
122    /// Re-render all content HTML from markdown
123    Rerender,
124    /// Manage users
125    User {
126        #[command(subcommand)]
127        command: UserCommand,
128    },
129    /// Manage global configuration
130    Config {
131        #[command(subcommand)]
132        command: ConfigCommand,
133    },
134    /// Manage multiple Pebble sites
135    Registry {
136        #[command(subcommand)]
137        command: RegistryCommand,
138    },
139}
140
141#[derive(Subcommand)]
142pub enum UserCommand {
143    Add {
144        #[arg(long)]
145        username: String,
146        #[arg(long)]
147        email: String,
148        #[arg(long, default_value = "author")]
149        role: String,
150        #[arg(long)]
151        password: Option<String>,
152    },
153    List,
154    Remove {
155        username: String,
156    },
157    Passwd {
158        username: String,
159    },
160}
161
162#[derive(Subcommand)]
163pub enum BackupCommand {
164    Create {
165        #[arg(short, long, default_value = "./backups")]
166        output: PathBuf,
167    },
168    Restore {
169        file: PathBuf,
170    },
171    List {
172        #[arg(short, long, default_value = "./backups")]
173        dir: PathBuf,
174    },
175}
176
177#[derive(Subcommand)]
178pub enum MigrateCommand {
179    /// Show applied and pending migrations
180    Status,
181    /// Roll back the most recent migration(s)
182    Rollback {
183        /// Number of migrations to roll back
184        #[arg(short, long, default_value = "1")]
185        steps: u32,
186        /// Force rollback without confirmation (required for migration 001)
187        #[arg(long)]
188        force: bool,
189    },
190}
191
192#[derive(Subcommand)]
193pub enum ConfigCommand {
194    Get { key: String },
195    Set { key: String, value: String },
196    List,
197    Remove { key: String },
198    Path,
199}
200
201#[derive(Subcommand)]
202pub enum RegistryCommand {
203    /// Create a new site in the registry
204    Init {
205        /// Unique name for the site
206        name: String,
207        /// Display title for the site
208        #[arg(long)]
209        title: Option<String>,
210    },
211    /// List all registered sites
212    List,
213    /// Start a site's development server
214    Serve {
215        /// Name of the site to serve
216        name: String,
217        /// Port to listen on
218        #[arg(short, long)]
219        port: Option<u16>,
220    },
221    /// Start a site's production server
222    Deploy {
223        /// Name of the site to deploy
224        name: String,
225        /// Port to listen on
226        #[arg(short, long)]
227        port: Option<u16>,
228    },
229    /// Stop a running site
230    Stop {
231        /// Name of the site to stop
232        name: String,
233    },
234    /// Stop all running sites
235    StopAll,
236    /// Remove a site from the registry
237    Remove {
238        /// Name of the site to remove
239        name: String,
240        /// Skip confirmation prompt
241        #[arg(long)]
242        force: bool,
243    },
244    /// Show the status of a site
245    Status {
246        /// Name of the site
247        name: String,
248    },
249    /// Show the path to a site or the registry directory
250    Path {
251        /// Name of the site (omit to show registry directory)
252        name: Option<String>,
253    },
254    /// Re-render all content HTML from markdown for a site
255    Rerender {
256        /// Name of the site to re-render
257        name: String,
258    },
259    /// View or edit a site's configuration
260    Config {
261        /// Site name
262        name: String,
263        #[command(subcommand)]
264        command: Option<SiteConfigCommand>,
265    },
266}
267
268#[derive(Subcommand)]
269pub enum SiteConfigCommand {
270    /// Get a config value (e.g., theme.name, site.title)
271    Get {
272        /// Config key in dot notation (e.g., theme.name)
273        key: String,
274    },
275    /// Set a config value
276    Set {
277        /// Config key in dot notation (e.g., theme.name)
278        key: String,
279        /// New value
280        value: String,
281    },
282    /// Open config file in editor
283    Edit,
284}