salvo-rs salvo-cli .cursorrules file for Rust (stars: 46)

{{ talk_to_me_lang }}
Here is the refined, concise English version of your guidelines for AI:
Salvo Framework Overview
Salvo is a Rust-based web framework focused on simplicity, efficiency, and usability. Key concepts include Router, Handler, Middleware, Request, Response, and Depot.
Key Concepts:
	1.	Router:
	•	Create with Router::new().
	•	Define paths with path() or with_path().
	•	Use HTTP methods like get(), post(), patch(), delete().
	•	Support for path parameters (e.g., {id}, <id:num>).
	•	Filters like filters::path(), filters::get() can be added.
	•	Add middleware with hoop().
	2.	Handler:
	•	Use #[handler] macro for easy definition.
	•	Optional parameters include Request, Depot, FlowCtrl.
	•	Return types must implement Writer Trait (e.g., &str, String, Result<T, E>).
	3.	Middleware:
	•	Implement Handler Trait.
	•	Use hoop() to add middleware to Router or Service.
	•	Control execution flow with FlowCtrl, e.g., ctrl.skip_rest().
	4.	Request:
	•	Get path parameters with req.param::<T>("param_name").
	•	Use req.query::<T>("query_name") for query parameters.
	•	Parse form or JSON with req.form::<T>("name").await or req.parse_json::<T>().await.
	•	Extract data into structures with req.extract().
	5.	Response:
	•	Render responses with res.render().
	•	Return types like Text::Plain(), Text::Html(), Json().
	•	Set status with res.status_code() or StatusError.
	•	Use Redirect::found() for redirection.
	6.	Depot:
	•	Store temporary data between middleware and handlers with methods like depot.insert() and depot.obtain::<T>().
	7.	Extractors:
	•	Use #[salvo(extract(...))] annotations to map request data to structures.

Core Features:
	•	Static File Serving: Use StaticDir or StaticEmbed.
	•	OpenAPI Support: Auto-generate docs with #[endpoint] macro.

Routing:
	•	Flat or tree-like route structure supported.

Middleware:
	•	Middleware is a Handler added to Router, Service, or Catcher.
	•	FlowCtrl allows skipping handlers or middleware.

Error Handling:
	•	Handlers return Result<T, E> where T and E implement Writer Trait.
	•	Custom errors are handled via the Writer Trait, with anyhow::Error as the default.

Deployment:
	•	Compile Salvo apps into a single executable for easy deployment.

Project Structure:

project/
├── src/
│   ├── routers/
│   ├── models/
│   ├── db/
│   ├── error.rs
│   └── utils.rs
├── views/
│   └── *.html
├── migrations/
└── assets/
    ├── js/
    └── css/

JSON Response Format:

#[derive(Serialize)]
pub struct JsonResponse<T> {
    pub code: i32,
    pub message: String,
    pub data: T,
}

Frontend Guidelines:
	1.	Tailwind CSS:
	•	Use flex, grid, space-x, space-y, bg-{color}, text-{color}, rounded-{size}, shadow-{size}.
	2.	Alpine.js:
	•	Use x-data, x-model, @click, x-show, x-if.
	3.	Fragment Architecture:
	•	Use X-Fragment-Header for partial page updates via x-html.

Error Handling:
	•	AppError handles various error types: Public, Internal, HttpStatus, SqlxError, Validation.
	•	Log errors with tracing and return appropriate HTTP status codes.

Database Operations:
	•	Use SQLx for async DB operations (e.g., query!, query_as!).
	•	Paginate with LIMIT and OFFSET.

Password Handling:
	•	Use bcrypt/Argon2 for password hashing.

Input Validation:
	•	Use validator for validating and sanitizing inputs.
1. Entity Definition:
```rust
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
  #[sea_orm(primary_key)]
  pub id: i32,
  pub name: String,
  pub created_at: DateTime,
}
```

2. Common Operations:
• Select:
```rust
// Find by id
let user: Option<user::Model> = User::find_by_id(1).one(db).await?;

// Find all
let users: Vec<user::Model> = User::find().all(db).await?;

// Find with condition
let users = User::find()
    .filter(user::Column::Name.contains("John"))
    .all(db).await?;
```

• Insert:
```rust
let user = user::ActiveModel {
    name: Set("New User".to_owned()),
    ..Default::default()
};
let res = user.insert(db).await?;
```

• Update:
```rust
let mut user: user::ActiveModel = User::find_by_id(1)
    .one(db)
    .await?
    .unwrap()
    .into();
user.name = Set("New Name".to_owned());
let user: user::Model = user.update(db).await?;
```

• Delete:
```rust
let user: user::Model = User::find_by_id(1).one(db).await?.unwrap();
user.delete(db).await?;
```

3. Relationships:
• One-to-One:
```rust
let (post, user) = Post::find_by_id(1)
    .find_also_related(User)
    .one(db)
    .await?;
```

• One-to-Many:
```rust
let (user, posts) = User::find_by_id(1)
    .find_with_related(Post)
    .all(db)
    .await?;
```

• Many-to-Many:
```rust
let (post, categories) = Post::find_by_id(1)
    .find_with_related(Category)
    .all(db)
    .await?;
```

4. Pagination:
```rust
let paginator = User::find()
  .paginate(db, 10);
let num_pages = paginator.num_pages().await?;
let users = paginator.fetch_page(0).await?;
```

5. SeaORM CLI Usage:
• Installation:
```bash
cargo install sea-orm-cli
```

• Generate Entities:
```bash
sea-orm-cli generate entity \
    -u postgres://user:pass@localhost/db \
    -o src/entities
```

• Migration Commands:
```bash
# Initialize
sea-orm-cli migrate init

# Generate new
sea-orm-cli migrate generate create_users_table

# Run migrations
sea-orm-cli migrate up

# Rollback
sea-orm-cli migrate down

# Status check
sea-orm-cli migrate status
```

6. Best Practices:
• Use connection pools (e.g., sqlx::Pool)
• Implement ActiveModelBehavior for custom logic
• Use transactions for atomic operations
• Leverage async/await for all database operations
• Use Column enums for type-safe queries
• Implement proper error handling with DbErr

7. Query Building:
```rust
User::find()
  .select_only()
  .column(user::Column::Name)
  .column_as(post::Column::Id.count(), "post_count")
  .join(JoinType::LeftJoin, user::Relation::Posts.def())
  .group_by(user::Column::Id)
  .having(post::Column::Id.count().gt(5))
  .order_by_asc(user::Column::Name)
  .into_model::<UserWithPostCount>()
  .all(db)
  .await?
```

8. JSON Operations:
```rust
// Convert to JSON
let json = user.into_json();

// Query as JSON
let users_json = User::find()
  .into_json()
  .all(db)
  .await?;
```

9. Streaming:
```rust
let mut stream = User::find()
  .stream(db)
  .await?;

while let Some(user) = stream.try_next().await? {
  println!("User: {:?}", user);
}
```
golang
liquid
postgresql
rest-api
rust
tailwindcss

First Time Repository

Rust

Languages:

Liquid: 75.1KB
Rust: 88.3KB
Created: 9/20/2023
Updated: 1/23/2025

All Repositories (1)