fob_cli/cli/
commands.rs

1use clap::{Args, Subcommand};
2use std::path::PathBuf;
3
4use crate::cli::enums::*;
5use crate::cli::validation::parse_global;
6
7/// Available Fob subcommands
8#[derive(Subcommand, Debug)]
9pub enum Command {
10    /// Build a library or application
11    ///
12    /// Bundles entry points into optimized output with support for multiple
13    /// formats, TypeScript declarations, source maps, and tree shaking.
14    Build(BuildArgs),
15
16    /// Start development server with watch mode
17    ///
18    /// Runs a development server with hot module replacement and automatic
19    /// rebuilding when source files change.
20    Dev(DevArgs),
21
22    /// Initialize a new Fob project
23    ///
24    /// Creates a new project with sensible defaults and optional templates
25    /// for common project types (library, application, monorepo).
26    Init(InitArgs),
27
28    /// Validate configuration and dependencies
29    ///
30    /// Checks fob.config.json for errors and validates that all dependencies
31    /// are correctly installed and compatible.
32    Check(CheckArgs),
33}
34
35/// Arguments for the build command
36#[derive(Args, Debug)]
37pub struct BuildArgs {
38    /// Entry points to bundle
39    ///
40    /// Specify one or more entry points. Each entry point will be bundled
41    /// into a separate output file. If not specified, reads from fob.config.json.
42    ///
43    /// Examples:
44    ///   fob build src/index.ts
45    ///   fob build src/main.ts src/worker.ts
46    #[arg(value_name = "ENTRY")]
47    pub entry: Option<Vec<String>>,
48
49    /// Output format for the bundle
50    ///
51    /// - esm: ECMAScript modules (modern, tree-shakeable)
52    /// - cjs: CommonJS (Node.js compatible)
53    /// - iife: Immediately Invoked Function Expression (browser script tag)
54    #[arg(short = 'f', long, value_enum, default_value = "esm")]
55    pub format: Format,
56
57    /// Output directory for bundled files
58    ///
59    /// All generated files (bundles, source maps, declarations) will be
60    /// written to this directory. Created if it doesn't exist.
61    #[arg(short = 'd', long, default_value = "dist", value_name = "DIR")]
62    pub out_dir: PathBuf,
63
64    /// Generate TypeScript declaration files (.d.ts)
65    ///
66    /// Extracts type definitions from TypeScript source files. Useful for
67    /// library authors who want to provide type safety to consumers.
68    #[arg(long)]
69    pub dts: bool,
70
71    /// Bundle declaration files into a single .d.ts file
72    ///
73    /// Combines all declaration files into one output file, making it easier
74    /// for consumers to import types. Requires --dts to be enabled.
75    #[arg(long, requires = "dts")]
76    pub dts_bundle: bool,
77
78    /// Generate API documentation from JSDoc / TSDoc comments
79    ///
80    /// Emits Markdown or JSON files describing exported symbols.
81    #[arg(long)]
82    pub docs: bool,
83
84    /// Format for generated documentation (md, json, both)
85    #[arg(long, value_enum, value_name = "FORMAT", requires = "docs")]
86    pub docs_format: Option<DocsFormat>,
87
88    /// Output directory for generated documentation files
89    #[arg(long, value_name = "DIR", requires = "docs")]
90    pub docs_dir: Option<PathBuf>,
91
92    /// Include symbols annotated with @internal
93    #[arg(long, requires = "docs")]
94    pub docs_include_internal: bool,
95
96    /// Enable LLM-powered documentation enhancement
97    ///
98    /// Uses Ollama to automatically generate comprehensive documentation
99    /// for symbols with missing or incomplete JSDoc comments.
100    /// Requires Ollama to be installed and running (ollama serve).
101    #[arg(long, requires = "docs")]
102    pub docs_enhance: bool,
103
104    /// LLM enhancement mode (missing, incomplete, all)
105    ///
106    /// - missing: Only enhance symbols with no JSDoc at all (fastest)
107    /// - incomplete: Enhance symbols missing params, returns, or examples
108    /// - all: Enhance all symbols, merging with existing docs (most thorough)
109    #[arg(long, value_enum, value_name = "MODE", requires = "docs_enhance")]
110    pub docs_enhance_mode: Option<DocsEnhanceMode>,
111
112    /// LLM model to use for enhancement
113    ///
114    /// Specifies which Ollama model to use for generating documentation.
115    /// Examples: llama3.2:3b (default, fast), codellama:7b (better quality),
116    /// deepseek-coder:6.7b (code-focused), qwen2.5-coder:7b (latest)
117    #[arg(long, value_name = "MODEL", requires = "docs_enhance")]
118    pub docs_llm_model: Option<String>,
119
120    /// Disable LLM response caching
121    ///
122    /// By default, LLM responses are cached using BLAKE3-based smart invalidation
123    /// that auto-invalidates when code changes. Use this flag to disable caching
124    /// and always query the LLM (useful for testing different prompts).
125    #[arg(long, requires = "docs_enhance")]
126    pub docs_no_cache: bool,
127
128    /// Custom Ollama server URL
129    ///
130    /// Specify a custom Ollama server endpoint. Useful for remote Ollama instances
131    /// or non-standard ports. Defaults to http://localhost:11434
132    #[arg(long, value_name = "URL", requires = "docs_enhance")]
133    pub docs_llm_url: Option<String>,
134
135    /// Write enhanced documentation back to source files
136    ///
137    /// Instead of generating external docs, this modifies the original
138    /// source files by adding or updating JSDoc comments with LLM-enhanced
139    /// documentation. Creates .bak backup files by default.
140    #[arg(long, requires = "docs_enhance")]
141    pub docs_write_back: bool,
142
143    /// JSDoc merge strategy when writing back
144    ///
145    /// Controls how to handle existing JSDoc comments:
146    /// - merge: Merge LLM output with existing JSDoc (default, preserves custom tags)
147    /// - replace: Replace existing JSDoc entirely with LLM output
148    /// - skip: Skip symbols that already have JSDoc
149    #[arg(
150        long,
151        value_enum,
152        value_name = "STRATEGY",
153        requires = "docs_write_back"
154    )]
155    pub docs_merge_strategy: Option<DocsMergeStrategy>,
156
157    /// Skip creating backup files when writing back
158    ///
159    /// By default, original files are backed up with .bak extension before modification.
160    /// Use this flag to skip backup creation (useful for version-controlled code).
161    #[arg(long, requires = "docs_write_back")]
162    pub docs_no_backup: bool,
163
164    /// External packages to exclude from bundle
165    ///
166    /// Dependencies listed here will not be included in the output bundle.
167    /// They must be provided by the consuming environment.
168    ///
169    /// Examples:
170    ///   --external react --external react-dom
171    ///   --external react,react-dom
172    #[arg(short, long, value_name = "PACKAGE")]
173    pub external: Vec<String>,
174
175    /// Target platform environment
176    ///
177    /// - browser: Optimizes for browser environments (no Node.js APIs)
178    /// - node: Optimizes for Node.js (enables require, process, etc.)
179    #[arg(long, value_enum, default_value = "browser")]
180    pub platform: Platform,
181
182    /// Source map generation mode
183    ///
184    /// - inline: Embeds source maps in the bundle (larger file, single file)
185    /// - external: Generates separate .map files (smaller bundle, two files)
186    /// - hidden: Generates maps but doesn't reference them (debugging builds)
187    #[arg(long, value_enum, value_name = "MODE")]
188    pub sourcemap: Option<SourceMapMode>,
189
190    /// Enable minification of output
191    ///
192    /// Reduces bundle size by removing whitespace, shortening variable names,
193    /// and applying other optimizations. Recommended for production builds.
194    #[arg(short = 'm', long)]
195    pub minify: bool,
196
197    /// JavaScript language target version
198    ///
199    /// Determines which JavaScript features are available in the output.
200    /// Later targets produce smaller, faster code but require modern runtimes.
201    #[arg(long, value_enum, default_value = "es2020", value_name = "TARGET")]
202    pub target: EsTarget,
203
204    /// Global variable name for IIFE/UMD bundles
205    ///
206    /// When using IIFE format, this is the global variable name that will
207    /// contain the exported module. Must be a valid JavaScript identifier.
208    ///
209    /// Example: --global-name MyLibrary
210    #[arg(long, value_parser = parse_global, value_name = "NAME")]
211    pub global_name: Option<String>,
212
213    /// Bundle dependencies into output
214    ///
215    /// - true: Include all dependencies in the bundle (standalone app/library)
216    /// - false: Externalize dependencies (require them at runtime)
217    ///
218    /// Use false for npm packages, true for browser apps.
219    #[arg(long, default_value = "true")]
220    pub bundle: bool,
221
222    /// Enable code splitting
223    ///
224    /// Splits the bundle into multiple chunks for lazy loading. Useful for
225    /// large applications to reduce initial load time. Only works with ESM format.
226    /// Requires --bundle.
227    #[arg(long)]
228    pub splitting: bool,
229
230    /// Disable tree shaking optimizations
231    ///
232    /// By default, unused exports are removed. This flag preserves all code,
233    /// which may be useful for debugging or specific compatibility requirements.
234    #[arg(long)]
235    pub no_treeshake: bool,
236
237    /// Clean output directory before build
238    ///
239    /// Removes all files from the output directory before starting the build.
240    /// Ensures no stale artifacts remain from previous builds.
241    #[arg(long)]
242    pub clean: bool,
243
244    /// Working directory for the build
245    ///
246    /// All relative paths in the build process are resolved relative to this
247    /// directory. Defaults to the current working directory.
248    #[arg(long, value_name = "DIR")]
249    pub cwd: Option<PathBuf>,
250}
251
252/// Arguments for the dev command (development server)
253#[derive(Args, Debug)]
254pub struct DevArgs {
255    /// Entry point for development server
256    ///
257    /// The main file to serve. If not specified, reads from fob.config.json.
258    /// The dev server will rebuild this entry point and its dependencies
259    /// whenever files change.
260    #[arg(value_name = "ENTRY")]
261    pub entry: Option<PathBuf>,
262
263    /// Port for development server
264    ///
265    /// The HTTP port to listen on. The server will automatically find an
266    /// available port if this one is in use.
267    #[arg(short, long, default_value = "3000", value_name = "PORT")]
268    pub port: u16,
269
270    /// Enable HTTPS with automatic certificate generation
271    ///
272    /// Generates a self-signed certificate for local HTTPS development.
273    /// Useful for testing service workers or other HTTPS-only features.
274    #[arg(long)]
275    pub https: bool,
276
277    /// Open browser automatically on server start
278    ///
279    /// Launches the default web browser and navigates to the dev server URL.
280    #[arg(long)]
281    pub open: bool,
282
283    /// Working directory for the dev server (defaults to auto-detected project root)
284    ///
285    /// All relative paths are resolved relative to this directory. If not specified,
286    /// fob will automatically detect the project root by finding the nearest package.json.
287    #[arg(long, value_name = "DIR")]
288    pub cwd: Option<PathBuf>,
289}
290
291/// Arguments for the init command (project scaffolding)
292#[derive(Args, Debug)]
293pub struct InitArgs {
294    /// Project name
295    ///
296    /// Name of the project to create. If omitted, uses the current directory
297    /// name. Must be a valid npm package name.
298    #[arg(value_name = "NAME")]
299    pub name: Option<String>,
300
301    /// Template to use for project initialization
302    ///
303    /// Available templates:
304    /// - library: TypeScript library with type declarations
305    /// - app: Web application with dev server
306    /// - component-library: React component library (aliases: components)
307    /// - meta-framework: Educational framework example (aliases: framework)
308    ///
309    /// If not specified, an interactive prompt will ask for preferences.
310    #[arg(short, long, value_name = "TEMPLATE")]
311    pub template: Option<String>,
312
313    /// Skip interactive prompts and use defaults
314    ///
315    /// Creates a basic project without asking for customization options.
316    /// Useful for automated workflows or quick prototyping.
317    #[arg(short = 'y', long)]
318    pub yes: bool,
319
320    /// Use npm as package manager (default)
321    #[arg(long, conflicts_with_all = ["use_yarn", "use_pnpm"])]
322    pub use_npm: bool,
323
324    /// Use Yarn as package manager
325    #[arg(long, conflicts_with_all = ["use_npm", "use_pnpm"])]
326    pub use_yarn: bool,
327
328    /// Use pnpm as package manager
329    #[arg(long, conflicts_with_all = ["use_npm", "use_yarn"])]
330    pub use_pnpm: bool,
331}
332
333/// Arguments for the check command (configuration validation)
334#[derive(Args, Debug)]
335pub struct CheckArgs {
336    /// Path to fob.config.json
337    ///
338    /// Specify a custom configuration file location. If not provided,
339    /// searches for fob.config.json in the current directory.
340    #[arg(short, long, value_name = "FILE")]
341    pub config: Option<PathBuf>,
342
343    /// Also validate package.json dependencies
344    ///
345    /// Checks that all dependencies are installed and that their versions
346    /// are compatible with the project requirements.
347    #[arg(long)]
348    pub deps: bool,
349
350    /// Show warnings in addition to errors
351    ///
352    /// Displays potential issues that won't prevent building but might
353    /// indicate configuration problems or suboptimal settings.
354    #[arg(short, long)]
355    pub warnings: bool,
356}