Patterns · 1 of 4
Input validation
Procedures run server-side, so they're the last gate before data hits storage. Validate everything at the top — fail fast, fail clearly.
Guard-clause style
proc create_user(email, name, age) {
if email == null || email == "" { abort "email required" }
if name == null || name == "" { abort "name required" }
if age < 13 { abort "must be 13 or older" }
insert("users", {email: email, name: name, age: age})
return {ok: true}
}
Range checks
proc set_price(sku, price) {
if price < 0 { abort "price cannot be negative" }
if price > 10000 { abort "price too high — needs approval" }
update("products", {sku: sku}, {$set: {price: price}})
return {ok: true}
}
Existence checks
proc add_to_team(user_id, team_id) {
let user = find_one("users", {_id: user_id})
let team = find_one("teams", {_id: team_id})
if user == null { abort "user not found" }
if team == null { abort "team not found" }
insert("members", {user_id: user_id, team_id: team_id})
return {ok: true}
}
Permission checks
proc delete_post(post_id, actor_id) {
let post = find_one("posts", {_id: post_id})
if post == null { abort "post not found" }
let actor = find_one("users", {_id: actor_id})
if actor == null { abort "actor not found" }
if post.author_id != actor_id && actor.role != "admin" {
abort "forbidden"
}
delete_one("posts", {_id: post_id})
return {ok: true}
}
Uniqueness checks
proc claim_username(user_id, username) {
if count("users", {username: username}) > 0 {
abort "username taken"
}
update("users", {_id: user_id}, {$set: {username: username}})
return {ok: true}
}
Quota checks
proc upload(user_id, file_size) {
let user = find_one("users", {_id: user_id})
if user.storage_used + file_size > user.storage_quota {
abort "storage quota exceeded"
}
update("users", {_id: user_id}, {$inc: {storage_used: file_size}})
insert("files", {owner: user_id, size: file_size})
return {ok: true, used: user.storage_used + file_size}
}
Compose validation into its own proc
proc validate_email(email) {
if email == null || email == "" { abort "email required" }
return {ok: true}
}
proc signup(email, name) {
validate_email({email: email})
if count("users", {email: email}) > 0 { abort "email taken" }
insert("users", {email: email, name: name})
return {ok: true}
}
Error message style: short, lowercase, machine-grep-friendly. Wire response is
{"ok": false, "error": "msg"}; clients can switch on the message text.