use serde_json::{Value, json};
use crate::validation;
use crate::engine;
use uuid::Uuid;
fn resolve_extends(doc: Value, db: &engine::Db) -> Value {
let obj = match doc.as_object() {
Some(o) => o,
None => return doc,
};
let extends_map = match obj.get("extends").and_then(|v| v.as_object()) {
Some(m) => m.clone(),
None => return doc,
};
let mut result = obj.clone();
result.remove("extends");
for (alias, ref_val) in &extends_map {
if let Some(ref_str) = ref_val.as_str() {
if let Some(dot_pos) = ref_str.find('.') {
let ref_collection = &ref_str[..dot_pos]; let ref_key = &ref_str[dot_pos + 1..];
if let Some(referenced_doc) = db.get(ref_collection, ref_key) {
result.insert(alias.clone(), referenced_doc);
}
}
}
}
Value::Object(result)
}
pub fn process_set(db: &engine::Db, payload: &Value, max_body_size: usize) -> (u16, Value) {
const SET_ALLOWED: &[&str] = &["collection", "data"];
if let Err(e) = validation::validate_allowed_properties(payload, SET_ALLOWED) {
return (400, json!({ "error": e.to_string(), "statusCode": 400 }));
}
if let Err(e) = validation::validate_request(payload, max_body_size) {
return (400, json!({ "error": e.to_string(), "statusCode": 400 }));
}
let col = payload["collection"].as_str().unwrap_or("default");
match payload.get("data") {
Some(Value::Object(data_map)) => {
let mut items = Vec::new();
for (k, v) in data_map {
let resolved = resolve_extends(v.clone(), db);
items.push((k.clone(), resolved));
}
match db.insert_batch(col, items) {
Ok(_) => (200, json!({ "status": "ok", "count": data_map.len() })),
Err(e) => (500, json!({ "error": "Database write failed", "details": e.to_string(), "statusCode": 500 }))
}
},
Some(Value::Array(data_arr)) => {
let mut items = Vec::new();
let mut generated_ids = Vec::new();
for item in data_arr {
let id = Uuid::now_v7().to_string();
generated_ids.push(id.clone());
let resolved = resolve_extends(item.clone(), db);
items.push((id, resolved));
}
match db.insert_batch(col, items) {
Ok(_) => (200, json!({
"status": "ok",
"count": data_arr.len(),
"ids": generated_ids
})),
Err(e) => (500, json!({ "error": "Database write failed", "details": e.to_string(), "statusCode": 500 }))
}
},
_ => (400, json!({ "error": "Missing 'data' (object or array)", "statusCode": 400 }))
}
}