Skip to content

Conversation

@Tuntii
Copy link
Owner

@Tuntii Tuntii commented Feb 2, 2026

Description

This pull request introduces several improvements and new features to the RustAPI CLI and templates, with a focus on enhancing development workflows and expanding functionality. The most notable changes include a major overhaul of the hot-reload/watch command, the addition of a database migration command to the CLI, and updates to the application templates for consistency and better usability.

CLI and Command Enhancements

  • Added a new migrate subcommand to the CLI, enabling database migration operations directly from the command line. This includes wiring up the argument parser and command dispatch logic for migrations. [1] [2] [3] [4] [5]

Hot-reload and Watch Improvements

  • Completely refactored the watch command for development:
    • Added support for configurable file extensions, watch/ignore paths, delay, quiet mode, polling, and restart behavior.
    • Improved output with progress spinners, emojis, and banners for better UX.
    • Automatically installs cargo-watch if missing.
    • Added tests for argument parsing and defaults.
  • Improved the run command's hot-reload mode:
    • Enhanced output messages for clarity.
    • Refined how the cargo watch command is constructed and executed. [1] [2] [3] [4] [5]

Template and API Consistency

  • Updated application templates to consistently use rustapi_rs instead of rustapi, fixed mount points to use route functions, and made API handler annotations uniform. Also improved JWT error handling and user claims schema. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

Dependency and Argument Improvements

  • Added the predicates crate to dev-dependencies for improved testing capabilities.
  • Improved argument parsing for the new command by adding short/long flags for project name.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Documentation update
  • Refactoring (no functional changes)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Related Issues

Fixes #82

Testing

Please describe the tests that you ran to verify your changes:

  • Unit tests
  • Integration tests
  • Manual testing

Introduces a new `migrate` command to the CLI, providing database migration management (run, revert, status, create, reset) via a wrapper around sqlx-cli. Enhances the watch command with more options and improved output. Updates project templates to use `rustapi_rs` attribute macros. Adds comprehensive integration tests for CLI commands, and updates dependencies to include `predicates` for testing.
Refactored the Schema derive macro in rustapi-macros to dynamically resolve crate paths for rustapi_openapi and serde_json, improving compatibility for both internal and external users. Updated dependencies to include proc-macro-crate. Adjusted API and full template handlers to use new mount_route and simplified create handler return types. Updated quickstart documentation to clarify CLI installation and usage. Re-exported rustapi_openapi and serde_json in rustapi-rs prelude for macro support.
Enhances the run command with improved hot-reload messaging and aliasing, updates project templates to use correct crate paths and API usage, and refines macro crate path resolution for better compatibility with hyphenated and underscored crate names. Also adds missing attribute to new command argument and fixes usage of authentication claims in templates.
Copilot AI review requested due to automatic review settings February 2, 2026 02:18
Improves code readability and consistency by refactoring multi-line formatting, argument passing, and function signatures in migrate.rs, run.rs, watch.rs, and derive_schema.rs. Also updates test formatting in cli_tests.rs for better clarity.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses Issue #82 by fixing the quickstart documentation and resolving Schema compilation issues. The changes include improvements to the derive macro system, template updates for API consistency, and new CLI features.

Changes:

  • Fixed quickstart documentation to show correct CLI command (cargo rustapi new with installation instructions)
  • Enhanced Schema derive macro to properly resolve crate paths using proc-macro-crate, fixing compilation issues when Schema is used in different contexts
  • Added new migrate command for database migrations with comprehensive subcommands (run, revert, status, create, reset)
  • Updated all project templates to use consistent rustapi_rs:: prefixes and current API patterns
  • Enhanced watch command with additional configuration options (extensions, paths, delays, polling)
  • Added comprehensive CLI integration tests

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
docs/cookbook/src/getting_started/quickstart.md Added CLI installation section and fixed command examples
crates/rustapi-rs/src/lib.rs Added re-exports of rustapi_openapi and serde_json for Schema macro
crates/rustapi-macros/src/derive_schema.rs Implemented dynamic crate path resolution for Schema derive macro
crates/rustapi-macros/Cargo.toml Added proc-macro-crate dependency for path resolution
crates/cargo-rustapi/tests/cli_tests.rs Added comprehensive integration tests for CLI commands
crates/cargo-rustapi/src/templates/*.rs Updated templates to use rustapi_rs:: prefix and current APIs
crates/cargo-rustapi/src/commands/watch.rs Enhanced with more options and better UX
crates/cargo-rustapi/src/commands/run.rs Minor improvements to watch mode integration
crates/cargo-rustapi/src/commands/new.rs Changed name parameter from positional to named argument
crates/cargo-rustapi/src/commands/migrate.rs New comprehensive database migration command
crates/cargo-rustapi/src/commands/mod.rs Added migrate command export
crates/cargo-rustapi/src/cli.rs Integrated migrate command into CLI
crates/cargo-rustapi/Cargo.toml Added predicates test dependency
Cargo.lock Updated dependencies for new features

Comment on lines +35 to +132
.args(["new", project_name, "--template", "minimal", "--yes"])
.assert()
.success();

// Verify project structure
assert!(project_path.exists(), "Project directory should exist");
assert!(
project_path.join("Cargo.toml").exists(),
"Cargo.toml should exist"
);
assert!(
project_path.join("src/main.rs").exists(),
"src/main.rs should exist"
);

// Verify Cargo.toml content
let cargo_content =
fs::read_to_string(project_path.join("Cargo.toml")).expect("Failed to read Cargo.toml");
assert!(
cargo_content.contains("rustapi-rs"),
"Cargo.toml should depend on rustapi-rs"
);
}

#[test]
fn test_new_api_template() {
let dir = tempdir().expect("Failed to create temp dir");
let project_name = "test-api-project";
let project_path = dir.path().join(project_name);

cargo_rustapi()
.current_dir(dir.path())
.args(["new", project_name, "--template", "api", "--yes"])
.assert()
.success();

// Verify API project structure
assert!(project_path.join("src/handlers").is_dir());
assert!(project_path.join("src/models").is_dir());
assert!(project_path.join("src/handlers/mod.rs").exists());
assert!(project_path.join("src/handlers/items.rs").exists());
assert!(project_path.join("src/models/mod.rs").exists());
}

#[test]
fn test_new_with_features() {
let dir = tempdir().expect("Failed to create temp dir");
let project_name = "test-features-project";
let project_path = dir.path().join(project_name);

cargo_rustapi()
.current_dir(dir.path())
.args([
"new",
project_name,
"--template",
"minimal",
"--features",
"jwt,cors",
"--yes",
])
.assert()
.success();

let cargo_content =
fs::read_to_string(project_path.join("Cargo.toml")).expect("Failed to read Cargo.toml");
assert!(
cargo_content.contains("jwt") && cargo_content.contains("cors"),
"Cargo.toml should include jwt and cors features"
);
}

#[test]
fn test_new_existing_directory_fails() {
let dir = tempdir().expect("Failed to create temp dir");
let project_name = "existing-dir";

// Create the directory first
fs::create_dir(dir.path().join(project_name)).expect("Failed to create dir");

cargo_rustapi()
.current_dir(dir.path())
.args(["new", project_name, "--template", "minimal", "--yes"])
.assert()
.failure()
.stderr(predicate::str::contains("already exists"));
}

#[test]
fn test_new_invalid_name_fails() {
let dir = tempdir().expect("Failed to create temp dir");

cargo_rustapi()
.current_dir(dir.path())
.args(["new", "invalid/name", "--template", "minimal", "--yes"])
.assert()
.failure();
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test cases are passing the project name as a positional argument (e.g., ["new", project_name, ...]), but the code change in new.rs made the name field require --name or -n flags. These tests will fail and need to be updated to use ["new", "--name", project_name, ...] or the name field in NewArgs should be changed back to a positional argument.

Copilot uses AI. Check for mistakes.
Comment on lines +97 to +100

/// Create migration with timestamp prefix instead of sequential
#[arg(long)]
pub timestamp: bool,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timestamp field in MigrateCreateArgs is defined but never used in the create_migration function. The function always generates a timestamp using chrono_timestamp() regardless of this flag's value. Either remove this unused field or implement the intended behavior (e.g., using sequential numbering when timestamp is false).

Suggested change
/// Create migration with timestamp prefix instead of sequential
#[arg(long)]
pub timestamp: bool,

Copilot uses AI. Check for mistakes.
Comment on lines +167 to +173
) -> Json<Item> {
let item = Item::new(body.name, body.description);

let mut store = state.write().await;
store.items.insert(item.id.clone(), item.clone());

Ok(Created(Json(item)))
Json(item)
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type changed from Result<Created<Json<Item>>> to Json<Item>, which means POST requests will return HTTP 200 instead of HTTP 201 Created. While this works, it deviates from REST best practices where POST requests that create resources should return 201. The Created type is still available in rustapi-core, so this appears to be an intentional simplification rather than a required change. Consider whether this trade-off is acceptable for your template examples.

Copilot uses AI. Check for mistakes.
#[derive(Args, Debug)]
pub struct NewArgs {
/// Project name
#[arg(short, long)]
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name field has been changed from a positional argument to a named argument requiring --name or -n flags. This is a breaking change that will affect users who currently use cargo rustapi new my-project. The command would now need to be cargo rustapi new --name my-project or cargo rustapi new -n my-project. Consider keeping this as a positional argument for better UX, matching the pattern of similar CLI tools like cargo new.

Suggested change
#[arg(short, long)]
#[arg(value_name = "NAME")]

Copilot uses AI. Check for mistakes.
@Tuntii Tuntii merged commit 89281a5 into main Feb 2, 2026
7 checks passed
github-actions bot pushed a commit that referenced this pull request Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Quickstart update / no Schema in the root

1 participant