Add dev prompts for keyword, model, and service
This commit is contained in:
parent
44d4a7b392
commit
83d4a61fcd
4 changed files with 337 additions and 0 deletions
151
prompts/dev/add-keyword.md
Normal file
151
prompts/dev/add-keyword.md
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
Create a new Rhai custom keyword implementation with these specifications:
|
||||||
|
|
||||||
|
- When generating new Rhai keyword handlers in Rust, always design them to be thread-safe and fully compatible with async execution. Use Arc for shared state, perform heavy or async operations with tokio::task::block_in_place and Handle::current().block_on, and return results as rhai::Dynamic to maintain safe cross-thread communication between Rust and the Rhai engine.
|
||||||
|
|
||||||
|
1. DATABASE REQUIREMENTS:
|
||||||
|
- No enums in database schema (only in Rust code)
|
||||||
|
- Use direct integer values for enum variants in queries
|
||||||
|
- Follow existing connection pooling pattern with AppState
|
||||||
|
- Include proper error handling and logging
|
||||||
|
|
||||||
|
2. RUST IMPLEMENTATION:
|
||||||
|
- Enum definition (Rust-only, no DB enum):
|
||||||
|
```rust
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum KeywordAction {
|
||||||
|
Action1 = 0,
|
||||||
|
Action2 = 1,
|
||||||
|
Action3 = 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. KEYWORD TEMPLATE:
|
||||||
|
```rust
|
||||||
|
pub fn {keyword_name}_keyword(state: &AppState, engine: &mut Engine) {
|
||||||
|
let db = state.db_custom.clone();
|
||||||
|
|
||||||
|
engine.register_custom_syntax(
|
||||||
|
{syntax_pattern},
|
||||||
|
{is_raw},
|
||||||
|
{
|
||||||
|
let db = db.clone();
|
||||||
|
move |context, inputs| {
|
||||||
|
// Input processing
|
||||||
|
{input_processing}
|
||||||
|
|
||||||
|
let binding = db.as_ref().unwrap();
|
||||||
|
let fut = execute_{keyword_name}(binding, {params});
|
||||||
|
|
||||||
|
let result = tokio::task::block_in_place(||
|
||||||
|
tokio::runtime::Handle::current().block_on(fut))
|
||||||
|
.map_err(|e| format!("DB error: {}", e))?;
|
||||||
|
|
||||||
|
{result_handling}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn execute_{keyword_name}(
|
||||||
|
pool: &PgPool,
|
||||||
|
{params_with_types}
|
||||||
|
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||||
|
info!("Executing {keyword_name} with: {debug_params}");
|
||||||
|
|
||||||
|
let result = sqlx::query(
|
||||||
|
"{sql_query_with_i32_enum}"
|
||||||
|
)
|
||||||
|
.bind({enum_value} as i32)
|
||||||
|
{additional_binds}
|
||||||
|
.execute(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(json!({
|
||||||
|
"command": "{keyword_name}",
|
||||||
|
{result_fields}
|
||||||
|
"rows_affected": result.rows_affected()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. EXAMPLE IMPLEMENTATION (SET SCHEDULE):
|
||||||
|
```rust
|
||||||
|
// Enum (Rust-only)
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum TriggerKind {
|
||||||
|
Scheduled = 0,
|
||||||
|
TableUpdate = 1,
|
||||||
|
TableInsert = 2,
|
||||||
|
TableDelete = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyword implementation
|
||||||
|
pub fn set_schedule_keyword(state: &AppState, engine: &mut Engine) {
|
||||||
|
let db = state.db_custom.clone();
|
||||||
|
|
||||||
|
engine.register_custom_syntax(
|
||||||
|
["SET", "SCHEDULE", "$string$"],
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
let db = db.clone();
|
||||||
|
move |context, inputs| {
|
||||||
|
let cron = context.eval_expression_tree(&inputs[0])?.to_string();
|
||||||
|
let script_name = format!("cron_{}.rhai", cron.replace(' ', "_"));
|
||||||
|
|
||||||
|
let binding = db.as_ref().unwrap();
|
||||||
|
let fut = execute_set_schedule(binding, &cron, &script_name);
|
||||||
|
|
||||||
|
let result = tokio::task::block_in_place(||
|
||||||
|
tokio::runtime::Handle::current().block_on(fut))
|
||||||
|
.map_err(|e| format!("DB error: {}", e))?;
|
||||||
|
|
||||||
|
if let Some(rows_affected) = result.get("rows_affected") {
|
||||||
|
Ok(Dynamic::from(rows_affected.as_i64().unwrap_or(0)))
|
||||||
|
} else {
|
||||||
|
Err("No rows affected".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn execute_set_schedule(
|
||||||
|
pool: &PgPool,
|
||||||
|
cron: &str,
|
||||||
|
script_name: &str,
|
||||||
|
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||||
|
info!("Executing schedule: {}, {}", cron, script_name);
|
||||||
|
|
||||||
|
let result = sqlx::query(
|
||||||
|
"INSERT INTO system_automations
|
||||||
|
(kind, schedule, script_name)
|
||||||
|
VALUES ($1, $2, $3)"
|
||||||
|
)
|
||||||
|
.bind(TriggerKind::Scheduled as i32)
|
||||||
|
.bind(cron)
|
||||||
|
.bind(script_name)
|
||||||
|
.execute(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(json!({
|
||||||
|
"command": "set_schedule",
|
||||||
|
"schedule": cron,
|
||||||
|
"script_name": script_name,
|
||||||
|
"rows_affected": result.rows_affected()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
5. ADDITIONAL REQUIREMENTS:
|
||||||
|
- Maintain consistent tokio runtime handling
|
||||||
|
- Include parameter validation
|
||||||
|
- Follow existing JSON response format
|
||||||
|
- Ensure proper script name generation
|
||||||
|
- Include debug logging for all operations
|
||||||
|
|
||||||
|
6. OUTPUT FORMAT:
|
||||||
|
Provide complete implementation with:
|
||||||
|
1. Rust enum definition
|
||||||
|
2. Keyword registration function
|
||||||
|
3. Execution function
|
||||||
|
4. Example usage in Rhai
|
||||||
94
prompts/dev/add-model.md
Normal file
94
prompts/dev/add-model.md
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
Create a Rust data model for database storage with optimal size and performance characteristics. Follow these specifications:
|
||||||
|
|
||||||
|
**REQUIREMENTS:**
|
||||||
|
1. Use appropriate integer types (i32, i16, i8, etc.) based on expected value ranges
|
||||||
|
2. Use `Option<T>` for nullable fields to avoid memory overhead
|
||||||
|
3. Use `Vec<u8>` for binary data instead of strings when appropriate
|
||||||
|
4. Prefer enum representations as integers rather than strings
|
||||||
|
5. Use `chrono::DateTime<Utc>` for timestamps
|
||||||
|
6. Use `uuid::Uuid` for unique identifiers
|
||||||
|
7. Implement necessary traits: `Debug`, `Clone`, `Serialize`, `Deserialize`, `FromRow`
|
||||||
|
8. Include validation where appropriate
|
||||||
|
9. Consider database index strategy in field design
|
||||||
|
|
||||||
|
**CONTEXT:**
|
||||||
|
- Database: PostgreSQL/SQLx compatible
|
||||||
|
- Serialization: Serde for JSON
|
||||||
|
- ORM: SQLx for database operations
|
||||||
|
|
||||||
|
**OUTPUT FORMAT:**
|
||||||
|
Provide the complete Rust struct with:
|
||||||
|
- Struct definition with fields
|
||||||
|
- Enum definitions with integer representations
|
||||||
|
- Conversion implementations
|
||||||
|
- Basic validation if needed
|
||||||
|
|
||||||
|
**EXAMPLE REFERENCE:**
|
||||||
|
```rust
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sqlx::FromRow;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum Status {
|
||||||
|
Pending = 0,
|
||||||
|
Active = 1,
|
||||||
|
Inactive = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Status {
|
||||||
|
pub fn from_i16(value: i16) -> Option<Self> {
|
||||||
|
match value {
|
||||||
|
0 => Some(Self::Pending),
|
||||||
|
1 => Some(Self::Active),
|
||||||
|
2 => Some(Self::Inactive),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, FromRow, Serialize, Deserialize)]
|
||||||
|
pub struct User {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub status: i16, // Using i16 for enum storage
|
||||||
|
pub email: String,
|
||||||
|
pub age: Option<i16>, // Nullable small integer
|
||||||
|
pub metadata: Vec<u8>, // Binary data for flexibility
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate a similar model for: [YOUR DOMAIN HERE]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Specialized Variants
|
||||||
|
|
||||||
|
### For High-Performance Applications
|
||||||
|
```
|
||||||
|
Add these additional requirements:
|
||||||
|
- Use `#[repr(u8)]` for enums to ensure minimal size
|
||||||
|
- Consider `Box<str>` instead of `String` for reduced heap overhead
|
||||||
|
- Use `arrayvec::ArrayString` for fixed-size short strings
|
||||||
|
- Implement `PartialEq` and `Eq` for hash-based operations
|
||||||
|
- Include `#[derive(Default)]` where appropriate
|
||||||
|
```
|
||||||
|
|
||||||
|
### For Embedded/Memory-Constrained Systems
|
||||||
|
```
|
||||||
|
Add these constraints:
|
||||||
|
- Prefer `i16` over `i32` where possible
|
||||||
|
- Use `u32` instead of `Uuid` if sequential IDs are acceptable
|
||||||
|
- Consider `bitflags` for multiple boolean flags in single byte
|
||||||
|
- Use `smol_str::SmolStr` for string optimization
|
||||||
|
- Avoid `Vec` in favor of arrays with capacity limits
|
||||||
|
```
|
||||||
|
|
||||||
|
### For Time-Series Data
|
||||||
|
```
|
||||||
|
Add time-series specific optimizations:
|
||||||
|
- Use `i64` for timestamps as nanoseconds since epoch
|
||||||
|
- Use `f32` instead of `f64` for measurements where precision allows
|
||||||
|
- Consider `ordered_float::OrderedFloat` for floating-point comparisons
|
||||||
|
- Use `#[serde(with = "chrono::serde::ts_seconds")]` for compact serialization
|
||||||
57
prompts/dev/add-service.md
Normal file
57
prompts/dev/add-service.md
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
Generate a Rust service module following these patterns:
|
||||||
|
|
||||||
|
Core Structure:
|
||||||
|
|
||||||
|
Use actix-web for HTTP endpoints (get, post, etc.)
|
||||||
|
|
||||||
|
Isolate shared resources (DB, clients, config) in AppState
|
||||||
|
|
||||||
|
Split logic into reusable helper functions
|
||||||
|
|
||||||
|
do not create main logic
|
||||||
|
|
||||||
|
Endpoints:
|
||||||
|
|
||||||
|
Follow REST conventions (e.g., POST /{resource}/create) use anotations in methods.
|
||||||
|
|
||||||
|
Use web::Path for route parameters, web::Json for payloads
|
||||||
|
|
||||||
|
Return consistent responses (e.g., HttpResponse::Ok().json(data))
|
||||||
|
|
||||||
|
Error Handling:
|
||||||
|
|
||||||
|
Wrap fallible operations in Result
|
||||||
|
|
||||||
|
Use map_err to convert errors to actix_web::Error
|
||||||
|
|
||||||
|
Provide clear error messages (e.g., ErrorInternalServerError)
|
||||||
|
|
||||||
|
Async Patterns:
|
||||||
|
|
||||||
|
Use async/await for I/O (DB, external APIs)
|
||||||
|
|
||||||
|
Leverage streams for pagination/large datasets
|
||||||
|
|
||||||
|
Isolate blocking ops in spawn_blocking if needed
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
|
||||||
|
Load settings (e.g., URLs, credentials) from AppConfig
|
||||||
|
|
||||||
|
Initialize clients (DB, SDKs) at startup (e.g., init_*() helpers)
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
|
||||||
|
Add brief doc comments for public functions
|
||||||
|
|
||||||
|
Note safety assumptions (e.g., #[post] invariants)
|
||||||
|
postgres sqlx
|
||||||
|
Omit domain-specific logic (e.g., file/email details), focusing on the scaffolding."
|
||||||
|
|
||||||
|
Key Features:
|
||||||
|
|
||||||
|
Generic (applies to any service: auth, payments, etc.)
|
||||||
|
|
||||||
|
KISS (avoids over-engineering)
|
||||||
|
|
||||||
|
Copy-paste friendly (clear patterns without verbosity)
|
||||||
35
prompts/dev/fix-errors.md
Normal file
35
prompts/dev/fix-errors.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
You are fixing Rust code in a Cargo project. The user is providing problematic code that needs to be corrected.
|
||||||
|
|
||||||
|
## Your Task
|
||||||
|
Fix ALL compiler errors and logical issues while maintaining the original intent.
|
||||||
|
Use Cargo.toml as reference, do not change it.
|
||||||
|
Only return input files, all other files already exists.
|
||||||
|
If something, need to be added to a external file, inform it separated.
|
||||||
|
|
||||||
|
## Critical Requirements
|
||||||
|
3. **Respect Cargo.toml** - Check dependencies, editions, and features to avoid compiler errors
|
||||||
|
4. **Type safety** - Ensure all types match and trait bounds are satisfied
|
||||||
|
5. **Ownership rules** - Fix borrowing, ownership, and lifetime issues
|
||||||
|
|
||||||
|
|
||||||
|
MORE RULES:
|
||||||
|
- Return only the modified files as a single `.sh` script using `cat`, so the - code can be restored directly.
|
||||||
|
- You MUST return exactly this example format:
|
||||||
|
```sh
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Restore fixed Rust project
|
||||||
|
|
||||||
|
cat > src/<filenamehere>.rs << 'EOF'
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
// test
|
||||||
|
|
||||||
|
cat > src/<anotherfile>.rs << 'EOF'
|
||||||
|
// Fixed library code
|
||||||
|
pub fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
----
|
||||||
Loading…
Add table
Reference in a new issue