|
| 1 | +{{ talk_to_me_lang }} |
| 2 | +Here is the refined, concise English version of your guidelines for AI: |
| 3 | +Salvo Framework Overview |
| 4 | +Salvo is a Rust-based web framework focused on simplicity, efficiency, and usability. Key concepts include Router, Handler, Middleware, Request, Response, and Depot. |
| 5 | +Key Concepts: |
| 6 | + 1. Router: |
| 7 | + • Create with Router::new(). |
| 8 | + • Define paths with path() or with_path(). |
| 9 | + • Use HTTP methods like get(), post(), patch(), delete(). |
| 10 | + • Support for path parameters (e.g., {id}, <id:num>). |
| 11 | + • Filters like filters::path(), filters::get() can be added. |
| 12 | + • Add middleware with hoop(). |
| 13 | + 2. Handler: |
| 14 | + • Use #[handler] macro for easy definition. |
| 15 | + • Optional parameters include Request, Depot, FlowCtrl. |
| 16 | + • Return types must implement Writer Trait (e.g., &str, String, Result<T, E>). |
| 17 | + 3. Middleware: |
| 18 | + • Implement Handler Trait. |
| 19 | + • Use hoop() to add middleware to Router or Service. |
| 20 | + • Control execution flow with FlowCtrl, e.g., ctrl.skip_rest(). |
| 21 | + 4. Request: |
| 22 | + • Get path parameters with req.param::<T>("param_name"). |
| 23 | + • Use req.query::<T>("query_name") for query parameters. |
| 24 | + • Parse form or JSON with req.form::<T>("name").await or req.parse_json::<T>().await. |
| 25 | + • Extract data into structures with req.extract(). |
| 26 | + 5. Response: |
| 27 | + • Render responses with res.render(). |
| 28 | + • Return types like Text::Plain(), Text::Html(), Json(). |
| 29 | + • Set status with res.status_code() or StatusError. |
| 30 | + • Use Redirect::found() for redirection. |
| 31 | + 6. Depot: |
| 32 | + • Store temporary data between middleware and handlers with methods like depot.insert() and depot.obtain::<T>(). |
| 33 | + 7. Extractors: |
| 34 | + • Use #[salvo(extract(...))] annotations to map request data to structures. |
| 35 | + |
| 36 | +Core Features: |
| 37 | + • Static File Serving: Use StaticDir or StaticEmbed. |
| 38 | + • OpenAPI Support: Auto-generate docs with #[endpoint] macro. |
| 39 | + |
| 40 | +Routing: |
| 41 | + • Flat or tree-like route structure supported. |
| 42 | + |
| 43 | +Middleware: |
| 44 | + • Middleware is a Handler added to Router, Service, or Catcher. |
| 45 | + • FlowCtrl allows skipping handlers or middleware. |
| 46 | + |
| 47 | +Error Handling: |
| 48 | + • Handlers return Result<T, E> where T and E implement Writer Trait. |
| 49 | + • Custom errors are handled via the Writer Trait, with anyhow::Error as the default. |
| 50 | + |
| 51 | +Deployment: |
| 52 | + • Compile Salvo apps into a single executable for easy deployment. |
| 53 | + |
| 54 | +Project Structure: |
| 55 | + |
| 56 | +project/ |
| 57 | +├── src/ |
| 58 | +│ ├── routers/ |
| 59 | +│ ├── models/ |
| 60 | +│ ├── db/ |
| 61 | +│ ├── error.rs |
| 62 | +│ └── utils.rs |
| 63 | +├── views/ |
| 64 | +│ └── *.html |
| 65 | +├── migrations/ |
| 66 | +└── assets/ |
| 67 | + ├── js/ |
| 68 | + └── css/ |
| 69 | + |
| 70 | +JSON Response Format: |
| 71 | + |
| 72 | +#[derive(Serialize)] |
| 73 | +pub struct JsonResponse<T> { |
| 74 | + pub code: i32, |
| 75 | + pub message: String, |
| 76 | + pub data: T, |
| 77 | +} |
| 78 | + |
| 79 | +Frontend Guidelines: |
| 80 | + 1. Tailwind CSS: |
| 81 | + • Use flex, grid, space-x, space-y, bg-{color}, text-{color}, rounded-{size}, shadow-{size}. |
| 82 | + 2. Alpine.js: |
| 83 | + • Use x-data, x-model, @click, x-show, x-if. |
| 84 | + 3. Fragment Architecture: |
| 85 | + • Use X-Fragment-Header for partial page updates via x-html. |
| 86 | + |
| 87 | +Error Handling: |
| 88 | + • AppError handles various error types: Public, Internal, HttpStatus, SqlxError, Validation. |
| 89 | + • Log errors with tracing and return appropriate HTTP status codes. |
| 90 | + |
| 91 | +Database Operations: |
| 92 | + • Use SQLx for async DB operations (e.g., query!, query_as!). |
| 93 | + • Paginate with LIMIT and OFFSET. |
| 94 | + |
| 95 | +Password Handling: |
| 96 | + • Use bcrypt/Argon2 for password hashing. |
| 97 | + |
| 98 | +Input Validation: |
| 99 | + • Use validator for validating and sanitizing inputs. |
| 100 | + |
| 101 | +Diesel ORM Guidelines: |
| 102 | +1. Database Connection Setup: |
| 103 | + {%- if db_type == "postgres" %} |
| 104 | + • PostgreSQL: |
| 105 | + - URL format: postgres://user:password@host:port/dbname |
| 106 | + - Enable features: diesel/postgres |
| 107 | + - Types: Timestamp, Uuid, Json/Jsonb support |
| 108 | + {%- endif %} |
| 109 | + |
| 110 | + {%- if db_type == "mysql" %} |
| 111 | + • MySQL: |
| 112 | + - URL format: mysql://user:password@host/dbname |
| 113 | + - Enable features: diesel/mysql |
| 114 | + - Types: DateTime for timestamps |
| 115 | + {%- endif %} |
| 116 | + |
| 117 | + {%- if db_type == "sqlite" %} |
| 118 | + • SQLite: |
| 119 | + - URL format: file:path/to/db.sqlite |
| 120 | + - Enable features: diesel/sqlite |
| 121 | + - Types: INTEGER for auto-increment |
| 122 | + {%- endif %} |
| 123 | + |
| 124 | +2. Schema Definition: |
| 125 | + ```rust |
| 126 | + diesel::table! { |
| 127 | + users (id) { |
| 128 | + id -> Text, |
| 129 | + username -> Text, |
| 130 | + password -> Text, |
| 131 | + } |
| 132 | + } |
| 133 | + ``` |
| 134 | + |
| 135 | +3. Model Definition: |
| 136 | + ```rust |
| 137 | + #[derive(Queryable, Selectable, Insertable)] |
| 138 | + #[diesel(table_name = users)] |
| 139 | + pub struct User { |
| 140 | + pub id: String, |
| 141 | + pub username: String, |
| 142 | + pub password: String, |
| 143 | + } |
| 144 | + ``` |
| 145 | + |
| 146 | +4. Common Operations: |
| 147 | + • Select: |
| 148 | + ```rust |
| 149 | + users::table.filter(users::id.eq(user_id)).first::<User>(conn)? |
| 150 | + ``` |
| 151 | + • Insert: |
| 152 | + ```rust |
| 153 | + diesel::insert_into(users::table).values(&user).execute(conn)? |
| 154 | + ``` |
| 155 | + • Update: |
| 156 | + ```rust |
| 157 | + diesel::update(users::table) |
| 158 | + .filter(users::id.eq(user_id)) |
| 159 | + .set(users::username.eq(new_username)) |
| 160 | + .execute(conn)? |
| 161 | + ``` |
| 162 | + • Delete: |
| 163 | + ```rust |
| 164 | + diesel::delete(users::table).filter(users::id.eq(user_id)).execute(conn)? |
| 165 | + ``` |
| 166 | + |
| 167 | +5. Relationships: |
| 168 | + • belongs_to: |
| 169 | + ```rust |
| 170 | + #[derive(Associations)] |
| 171 | + #[belongs_to(User)] |
| 172 | + pub struct Post { ... } |
| 173 | + ``` |
| 174 | + • has_many: Use inner joins |
| 175 | + ```rust |
| 176 | + users::table.inner_join(posts::table) |
| 177 | + ``` |
| 178 | + |
| 179 | +6. Migrations: |
| 180 | + • Create: diesel migration generate create_users |
| 181 | + • Run: diesel migration run |
| 182 | + • Revert: diesel migration revert |
| 183 | + |
| 184 | +7. Database-Specific Features: |
| 185 | + {%- if db_type == "postgres" %} |
| 186 | + • PostgreSQL: |
| 187 | + - JSONB operations |
| 188 | + - Full-text search |
| 189 | + - Array types |
| 190 | + {%- endif %} |
| 191 | + {%- if db_type == "mysql" %} |
| 192 | + • MySQL: |
| 193 | + - ON DUPLICATE KEY |
| 194 | + - REPLACE INTO |
| 195 | + {%- endif %} |
| 196 | + {%- if db_type == "sqlite" %} |
| 197 | + • SQLite: |
| 198 | + - Simple file-based |
| 199 | + - WAL mode for concurrency |
| 200 | + {%- endif %} |
| 201 | + |
| 202 | +8. Best Practices: |
| 203 | + • Use connection pools (r2d2) |
| 204 | + • Implement From/Into for models |
| 205 | + • Use transactions for atomic operations |
| 206 | + • Use derive macros for boilerplate |
0 commit comments