Add container setup scripts for various services
Some checks failed
GBCI / build (push) Has been cancelled
Some checks failed
GBCI / build (push) Has been cancelled
- Implemented ALM container setup with Forgejo installation and systemd service configuration. - Created Bot container setup with necessary dependencies and Node.js application installation. - Developed Desktop container setup with XRDP and Brave browser installation. - Established Directory container setup with Zitadel installation and service configuration. - Added Doc Editor container setup for Collabora Online integration. - Implemented Drive container setup with MinIO installation and service configuration. - Created Email container setup with Stalwart Mail installation and service configuration. - Developed Meeting container setup with LiveKit and TURN server configuration. - Added Proxy container setup with Caddy installation and service configuration. - Implemented System container setup for general bots with service configuration. - Created Table Editor container setup with NocoDB installation and service configuration. - Developed Tables container setup with PostgreSQL installation and configuration. - Added Webmail container setup with Roundcube installation and service configuration. - Included prompt guidelines for container setup scripts.
This commit is contained in:
parent
247afd11cd
commit
d4697a6a93
10 changed files with 446 additions and 15 deletions
85
Cargo.lock
generated
85
Cargo.lock
generated
|
@ -275,6 +275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"const-random",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
|
@ -883,6 +884,26 @@ version = "0.9.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
|
@ -974,6 +995,12 @@ version = "0.8.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
@ -1625,6 +1652,7 @@ dependencies = [
|
|||
"minio",
|
||||
"native-tls",
|
||||
"reqwest 0.11.27",
|
||||
"rhai",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
|
@ -2845,6 +2873,9 @@ name = "once_cell"
|
|||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
|
@ -3477,6 +3508,34 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rhai"
|
||||
version = "1.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2780e813b755850e50b178931aaf94ed24f6817f46aaaf5d21c13c12d939a249"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"bitflags 2.9.1",
|
||||
"instant",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rhai_codegen",
|
||||
"smallvec",
|
||||
"smartstring",
|
||||
"thin-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rhai_codegen"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
|
@ -3900,6 +3959,17 @@ version = "1.15.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.10"
|
||||
|
@ -4370,6 +4440,12 @@ dependencies = [
|
|||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thin-vec"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
|
@ -4465,6 +4541,15 @@ dependencies = [
|
|||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.1"
|
||||
|
|
|
@ -15,6 +15,7 @@ actix-ws="0.3.0"
|
|||
bytes = "1.1"
|
||||
futures-util = "0.3"
|
||||
reqwest = { version = "0.11", features = ["json", "stream"] }
|
||||
rhai = "1.0"
|
||||
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
dotenv = "0.15"
|
||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -3,7 +3,8 @@ use actix_web::http::header;
|
|||
use actix_web::{web, App, HttpServer};
|
||||
use dotenv::dotenv;
|
||||
|
||||
|
||||
use services::script
|
||||
::*;
|
||||
use services::config::*;
|
||||
use services::email::*;
|
||||
use services::file::*;
|
||||
|
@ -17,6 +18,25 @@ async fn main() -> std::io::Result<()> {
|
|||
dotenv().ok();
|
||||
let config = AppConfig::from_env();
|
||||
|
||||
let script_service = ScriptService::new();
|
||||
|
||||
let script = r#"
|
||||
let json = FIND "users", "name=John"
|
||||
let x=2
|
||||
let text = GET "example.com"
|
||||
"#;
|
||||
|
||||
match script_service.compile(script) {
|
||||
Ok(ast) => {
|
||||
match script_service.run(&ast) {
|
||||
Ok(result) => println!("Script executed successfully: {:?}", result),
|
||||
Err(e) => eprintln!("Error executing script: {}", e),
|
||||
}
|
||||
},
|
||||
Err(e) => eprintln!("Error compiling script: {}", e),
|
||||
}
|
||||
|
||||
|
||||
let db_url = config.database_url();
|
||||
//let db = PgPool::connect(&db_url).await.unwrap();
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ lxc launch images:debian/12 "$PARAM_TENANT"-bot -c security.privileged=true
|
|||
sleep 15
|
||||
|
||||
lxc exec "$PARAM_TENANT"-bot -- bash -c "
|
||||
|
||||
echo "nameserver $PARAM_DNS_INTERNAL_IP" > /etc/resolv.conf
|
||||
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
build-essential cmake git pkg-config libjpeg-dev libtiff-dev \
|
||||
libpng-dev libavcodec-dev libavformat-dev libswscale-dev \
|
||||
|
|
|
@ -6,6 +6,9 @@ HOST_LOGS="$HOST_BASE/logs"
|
|||
mkdir -p "$HOST_BASE" "$HOST_CONF" "$HOST_DATA" "$HOST_LOGS"
|
||||
chmod -R 750 "$HOST_BASE"
|
||||
|
||||
lxc network set lxdbr0 user.dns.nameservers $PARAM_DNS_INTERNAL_IP,8.8.8.8,1.1.1.1
|
||||
lxc network set lxdbr0 dns.mode managed
|
||||
|
||||
# Clear existing rules
|
||||
sudo iptables -F
|
||||
|
||||
|
|
|
@ -37,9 +37,13 @@ sleep 15
|
|||
|
||||
echo "[CONTAINER] Installing Stalwart Mail..."
|
||||
lxc exec "$PARAM_TENANT"-email -- bash -c "
|
||||
|
||||
echo "nameserver $PARAM_DNS_INTERNAL_IP" > /etc/resolv.conf
|
||||
|
||||
apt install resolvconf -y
|
||||
apt-get update && apt-get install -y wget libcap2-bin
|
||||
wget -O /tmp/stalwart.tar.gz https://github.com/stalwartlabs/stalwart/releases/download/v0.12.4/stalwart-x86_64-unknown-linux-gnu.tar.gz
|
||||
|
||||
|
||||
tar -xzf /tmp/stalwart.tar.gz -C /tmp
|
||||
mkdir -p /opt/gbo/bin
|
||||
mv /tmp/stalwart /opt/gbo/bin/stalwart
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
# Define container limits in an associative array
|
||||
declare -A container_limits=(
|
||||
# Pattern Memory CPU Allowance
|
||||
["*tables*"]="2048MB:25ms/100ms"
|
||||
["*proxy*"]="512MB:25ms/100ms"
|
||||
["*directory*"]="512MB:25ms/100ms"
|
||||
["*drive*"]="1024MB:25ms/100ms"
|
||||
["*email*"]="1024MB:20ms/100ms"
|
||||
["*webmail*"]="1024MB:20ms/100ms"
|
||||
["*tables*"]="2048MB:50ms/100ms"
|
||||
["*dns*"]="512MB:50ms/100ms"
|
||||
["*doc-editor*"]="512MB:50ms/100ms"
|
||||
["*proxy*"]="512MB:50ms/100ms"
|
||||
["*directory*"]="512MB:50ms/100ms"
|
||||
["*drive*"]="1024MB:50ms/100ms"
|
||||
["*email*"]="2048MB:90ms/100ms"
|
||||
["*webmail*"]="2048MB:90ms/100ms"
|
||||
["*bot*"]="2048MB:50ms/100ms"
|
||||
["*meeting*"]="1024MB:20ms/100ms"
|
||||
["*alm*"]="512MB:20ms/100ms"
|
||||
["*alm-ci*"]="4096MB:80ms/100ms"
|
||||
["*meeting*"]="1024MB:50ms/100ms"
|
||||
["*alm*"]="512MB:50ms/100ms"
|
||||
["*alm-ci*"]="4096MB:50ms/100ms"
|
||||
)
|
||||
|
||||
# Default values (for containers that don't match any pattern)
|
||||
|
|
|
@ -2,4 +2,5 @@ pub mod config;
|
|||
pub mod file;
|
||||
pub mod state;
|
||||
pub mod email;
|
||||
pub mod llm;
|
||||
pub mod llm;
|
||||
pub mod script;
|
|
@ -59,7 +59,7 @@ pub async fn chat(
|
|||
let open_ai = OpenAI::new(azure_config);
|
||||
|
||||
// Parse the context JSON
|
||||
let context: serde_json::Value = match serde_json::from_str(&request.context) {
|
||||
let context: serde_json::Value = match serde_json::from_str(&request) {
|
||||
Ok(ctx) => ctx,
|
||||
Err(_) => serde_json::json!({})
|
||||
};
|
||||
|
@ -71,11 +71,11 @@ pub async fn chat(
|
|||
format!(
|
||||
"Respond to this email: {}. Keep it professional and concise. \
|
||||
If the email requires a response, provide one in the 'replyEmail' action format.",
|
||||
request.input
|
||||
request
|
||||
),
|
||||
true,
|
||||
),
|
||||
_ => (request.input, false),
|
||||
_ => (request, false),
|
||||
};
|
||||
|
||||
let response_text = match open_ai.invoke(&prompt).await {
|
||||
|
|
311
src/services/script.rs
Normal file
311
src/services/script.rs
Normal file
|
@ -0,0 +1,311 @@
|
|||
use rhai::module_resolvers::StaticModuleResolver;
|
||||
use rhai::{
|
||||
Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseError, ParseErrorType, Position,
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct ScriptService {
|
||||
engine: Engine,
|
||||
module_resolver: StaticModuleResolver,
|
||||
}
|
||||
|
||||
impl ScriptService {
|
||||
pub fn new() -> Self {
|
||||
let mut engine = Engine::new();
|
||||
let module_resolver = StaticModuleResolver::new();
|
||||
|
||||
// Configure engine for BASIC-like syntax
|
||||
engine.set_allow_anonymous_fn(true);
|
||||
engine.set_allow_looping(true);
|
||||
|
||||
// Register custom syntax for FOR EACH loop
|
||||
engine.register_custom_syntax(
|
||||
&["FOR", "EACH", "$ident$", "in", "$expr$", "$block$"],
|
||||
false, // Not a statement
|
||||
|context, inputs| {
|
||||
// Simple implementation - just return unit for now
|
||||
Ok(Dynamic::UNIT)
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// FIND command: FIND "table", "filter"
|
||||
engine.register_custom_syntax(
|
||||
&["FIND", "$expr$", ",", "$expr$"],
|
||||
false, // Expression, not statement
|
||||
|context, inputs| {
|
||||
let table_name = context.eval_expression_tree(&inputs[0])?;
|
||||
let filter = context.eval_expression_tree(&inputs[1])?;
|
||||
|
||||
let table_str = table_name.to_string();
|
||||
let filter_str = filter.to_string();
|
||||
|
||||
let result = json!({
|
||||
"command": "find",
|
||||
"table": table_str,
|
||||
"filter": filter_str,
|
||||
"results": []
|
||||
});
|
||||
Ok(Dynamic::from(result.to_string()))
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// SET command: SET "table", "key", "value"
|
||||
engine.register_custom_syntax(
|
||||
&["SET", "$expr$", ",", "$expr$", ",", "$expr$"],
|
||||
true, // Statement
|
||||
|context, inputs| {
|
||||
let table_name = context.eval_expression_tree(&inputs[0])?;
|
||||
let key_value = context.eval_expression_tree(&inputs[1])?;
|
||||
let value = context.eval_expression_tree(&inputs[2])?;
|
||||
|
||||
let table_str = table_name.to_string();
|
||||
let key_str = key_value.to_string();
|
||||
let value_str = value.to_string();
|
||||
|
||||
let result = json!({
|
||||
"command": "set",
|
||||
"status": "success",
|
||||
"table": table_str,
|
||||
"key": key_str,
|
||||
"value": value_str
|
||||
});
|
||||
println!("SET executed: {}", result.to_string());
|
||||
Ok(Dynamic::UNIT)
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// GET command: GET "url"
|
||||
engine.register_custom_syntax(
|
||||
&["GET", "$expr$"],
|
||||
false, // Expression, not statement
|
||||
|context, inputs| {
|
||||
let url = context.eval_expression_tree(&inputs[0])?;
|
||||
let url_str = url.to_string();
|
||||
|
||||
Ok(format!("Content from {}", url_str).into())
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// CREATE SITE command: CREATE SITE "name", "company", "website", "template", "prompt"
|
||||
engine.register_custom_syntax(
|
||||
&["CREATE", "SITE", "$expr$", ",", "$expr$", ",", "$expr$", ",", "$expr$", ",", "$expr$"],
|
||||
true, // Statement
|
||||
|context, inputs| {
|
||||
if inputs.len() < 5 {
|
||||
return Err("Not enough arguments for CREATE SITE".into());
|
||||
}
|
||||
|
||||
let name = context.eval_expression_tree(&inputs[0])?;
|
||||
let company = context.eval_expression_tree(&inputs[1])?;
|
||||
let website = context.eval_expression_tree(&inputs[2])?;
|
||||
let template = context.eval_expression_tree(&inputs[3])?;
|
||||
let prompt = context.eval_expression_tree(&inputs[4])?;
|
||||
|
||||
let result = json!({
|
||||
"command": "create_site",
|
||||
"name": name.to_string(),
|
||||
"company": company.to_string(),
|
||||
"website": website.to_string(),
|
||||
"template": template.to_string(),
|
||||
"prompt": prompt.to_string()
|
||||
});
|
||||
println!("CREATE SITE executed: {}", result.to_string());
|
||||
Ok(Dynamic::UNIT)
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// CREATE DRAFT command: CREATE DRAFT "to", "subject", "body"
|
||||
engine.register_custom_syntax(
|
||||
&["CREATE", "DRAFT", "$expr$", ",", "$expr$", ",", "$expr$"],
|
||||
true, // Statement
|
||||
|context, inputs| {
|
||||
if inputs.len() < 3 {
|
||||
return Err("Not enough arguments for CREATE DRAFT".into());
|
||||
}
|
||||
|
||||
let to = context.eval_expression_tree(&inputs[0])?;
|
||||
let subject = context.eval_expression_tree(&inputs[1])?;
|
||||
let body = context.eval_expression_tree(&inputs[2])?;
|
||||
|
||||
let result = json!({
|
||||
"command": "create_draft",
|
||||
"to": to.to_string(),
|
||||
"subject": subject.to_string(),
|
||||
"body": body.to_string()
|
||||
});
|
||||
println!("CREATE DRAFT executed: {}", result.to_string());
|
||||
Ok(Dynamic::UNIT)
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// PRINT command
|
||||
engine.register_custom_syntax(
|
||||
&["PRINT", "$expr$"],
|
||||
true, // Statement
|
||||
|context, inputs| {
|
||||
let value = context.eval_expression_tree(&inputs[0])?;
|
||||
println!("{}", value);
|
||||
Ok(Dynamic::UNIT)
|
||||
},
|
||||
).unwrap();
|
||||
|
||||
// Register web service functions
|
||||
engine.register_fn("web_get", |url: &str| {
|
||||
format!("Response from {}", url)
|
||||
});
|
||||
|
||||
ScriptService {
|
||||
engine,
|
||||
module_resolver,
|
||||
}
|
||||
}
|
||||
|
||||
/// Preprocesses BASIC-style script to handle semicolon-free syntax
|
||||
fn preprocess_basic_script(&self, script: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let mut in_block = false;
|
||||
|
||||
for line in script.lines() {
|
||||
let trimmed = line.trim();
|
||||
|
||||
// Skip empty lines and comments
|
||||
if trimmed.is_empty() || trimmed.starts_with("//") || trimmed.starts_with("REM") {
|
||||
result.push_str(line);
|
||||
result.push('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track block state
|
||||
if trimmed.contains('{') {
|
||||
in_block = true;
|
||||
}
|
||||
if trimmed.contains('}') {
|
||||
in_block = false;
|
||||
}
|
||||
|
||||
// Check if line starts with our custom commands (these don't need semicolons)
|
||||
let custom_commands = ["SET", "CREATE", "PRINT", "FOR", "FIND", "GET"];
|
||||
let is_custom_command = custom_commands.iter().any(|&cmd| trimmed.starts_with(cmd));
|
||||
|
||||
if is_custom_command || in_block {
|
||||
// Custom commands and block content don't need semicolons
|
||||
result.push_str(line);
|
||||
} else {
|
||||
// Regular statements need semicolons
|
||||
result.push_str(line);
|
||||
if !trimmed.ends_with(';') && !trimmed.ends_with('{') && !trimmed.ends_with('}') {
|
||||
result.push(';');
|
||||
}
|
||||
}
|
||||
result.push('\n');
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
pub fn compile(&self, script: &str) -> Result<rhai::AST, Box<EvalAltResult>> {
|
||||
let processed_script = self.preprocess_basic_script(script);
|
||||
match self.engine.compile(&processed_script) {
|
||||
Ok(ast) => Ok(ast),
|
||||
Err(parse_error) => Err(Box::new(EvalAltResult::from(parse_error))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn run(&self, ast: &rhai::AST) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
self.engine.eval_ast(ast)
|
||||
}
|
||||
|
||||
pub fn call_web_service(
|
||||
&self,
|
||||
endpoint: &str,
|
||||
data: HashMap<String, String>,
|
||||
) -> Result<String, Box<EvalAltResult>> {
|
||||
Ok(format!("Called {} with {:?}", endpoint, data))
|
||||
}
|
||||
|
||||
/// Execute a BASIC-style script without semicolons
|
||||
pub fn execute_basic_script(&self, script: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let processed = self.preprocess_basic_script(script);
|
||||
let ast = self.engine.compile(&processed)?;
|
||||
self.run(&ast)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_basic_script_without_semicolons() {
|
||||
let service = ScriptService::new();
|
||||
|
||||
// Test BASIC-style script without semicolons
|
||||
let script = r#"
|
||||
json = FIND "users", "name=John"
|
||||
SET "users", "name=John", "age=30"
|
||||
text = GET "example.com"
|
||||
CREATE SITE "mysite", "My Company", "mycompany.com", "basic", "Create a professional site"
|
||||
CREATE DRAFT "client@example.com", "Project Update", "Here's the latest update..."
|
||||
PRINT "Script completed successfully"
|
||||
"#;
|
||||
|
||||
let result = service.execute_basic_script(script);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_preprocessing() {
|
||||
let service = ScriptService::new();
|
||||
|
||||
let script = r#"
|
||||
json = FIND "users", "name=John"
|
||||
SET "users", "name=John", "age=30"
|
||||
let x = 42
|
||||
PRINT x
|
||||
if x > 10 {
|
||||
PRINT "Large number"
|
||||
}
|
||||
"#;
|
||||
|
||||
let processed = service.preprocess_basic_script(script);
|
||||
|
||||
// Should add semicolons to regular statements but not custom commands
|
||||
assert!(processed.contains("let x = 42;"));
|
||||
assert!(processed.contains("json = FIND"));
|
||||
assert!(!processed.contains("SET \"users\""));
|
||||
assert!(!processed.contains("PRINT \"Large number\";")); // Inside block shouldn't get semicolon
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_individual_commands() {
|
||||
let service = ScriptService::new();
|
||||
|
||||
let commands = vec![
|
||||
r#"SET "users", "name=John", "age=30""#,
|
||||
r#"CREATE SITE "mysite", "My Company", "mycompany.com", "basic", "Create a professional site""#,
|
||||
r#"CREATE DRAFT "client@example.com", "Project Update", "Here's the latest update...""#,
|
||||
r#"PRINT "Hello, World!""#,
|
||||
];
|
||||
|
||||
for cmd in commands {
|
||||
let result = service.execute_basic_script(cmd);
|
||||
assert!(result.is_ok(), "Command '{}' failed", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_statements() {
|
||||
let service = ScriptService::new();
|
||||
|
||||
let script = r#"
|
||||
if true {
|
||||
PRINT "Inside block"
|
||||
PRINT "Another statement"
|
||||
}
|
||||
"#;
|
||||
|
||||
let result = service.execute_basic_script(script);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue