mod new;
mod prompt;
mod templates;
mod upgrade;
use std::process::ExitCode;
const VERSION: &str = env!("CARGO_PKG_VERSION");
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
let args: Vec<&str> = args
.iter()
.map(String::as_str)
.skip_while(|a| *a == "rahti")
.collect();
let result = match args.first().copied() {
Some("new") => new::run(&args[1..]),
Some("upgrade") => upgrade::run(&args[1..]),
_ => return other(&args),
};
match result {
Ok(()) => ExitCode::SUCCESS,
Err(message) => {
eprintln!("error: {message}");
ExitCode::FAILURE
}
}
}
fn other(args: &[&str]) -> ExitCode {
match args.first().copied() {
Some("--version" | "-V") => {
println!("cargo-rahti {VERSION}");
ExitCode::SUCCESS
}
Some("help" | "--help" | "-h") | None => {
print!("{}", usage());
ExitCode::SUCCESS
}
Some(other) => {
eprintln!("error: `{other}` is not a cargo-rahti command.\n");
eprint!("{}", usage());
ExitCode::FAILURE
}
}
}
fn usage() -> String {
format!(
"cargo-rahti {VERSION}
Create and maintain Rahti projects.
USAGE:
cargo rahti new <name> [options]
cargo rahti upgrade [--dry-run] [--db [backend]] [--ws]
NEW:
A flag adds a feature. Leaving it out is how you say no.
--tailwind Add Tailwind CSS. Without it, plain CSS.
--db [backend] Add a database — sqlite, postgres or mysql. Bare
`--db` is sqlite, the one that needs no server.
Writes src/models/ and src/migrations/, and adds
SeaORM to Cargo.toml.
--ws Add WebSockets: the `ws` feature on the rahti
dependency, which compiles `rahti::ws` and the
`#[socket]` attribute.
--local <path> Depend on a Rahti checkout by path rather than by
version. For working on the framework itself.
UPGRADE:
-n, --dry-run Print what would change, and change nothing.
--db [backend] Add a database to a project that has none — the same
flag `new` takes. Writes the files, records the
backend in rahti.config.json, and prints what to add
to Cargo.toml and .env, which stay yours.
--ws Add WebSockets to a project without them.
Rewrites the scaffolded files you have not edited, and leaves the ones
you have. Which is which is decided by the hashes in rahti.config.json,
not by guessing. A dry run never asks a question — name the feature to
preview adding it.
-h, --help Print this message.
-V, --version Print the version.
An interactive run asks about any feature you did not name. A run with
nowhere to ask — a pipe, a CI job — takes the flags at their word and adds
only what they list.
"
)
}