refactor: extract Store methods, clean up shell-outs

- Add Store::upsert() — generic create-or-update, used by cmd_write
- Add Store::insert_node() — for pre-constructed nodes (journal entries)
- Add Store::delete_node() — soft-delete with version bump
- Simplify cmd_write (20 → 8 lines), cmd_node_delete (16 → 7 lines),
  cmd_journal_write (removes manual append/insert/save boilerplate)
- Replace generate_cookie shell-out to head/urandom with direct
  /dev/urandom read + const alphabet table

main.rs: 1137 → 1109 lines.
This commit is contained in:
ProofOfConcept 2026-02-28 23:49:43 -05:00
parent 29d5ed47a1
commit 0ea86b8d54
3 changed files with 62 additions and 55 deletions

View file

@ -491,6 +491,48 @@ impl Store {
Ok(())
}
/// Upsert a node: update if exists (and content changed), create if not.
/// Returns: "created", "updated", or "unchanged".
pub fn upsert(&mut self, key: &str, content: &str) -> Result<&'static str, String> {
if let Some(existing) = self.nodes.get(key) {
if existing.content == content {
return Ok("unchanged");
}
let mut node = existing.clone();
node.content = content.to_string();
node.version += 1;
self.append_nodes(std::slice::from_ref(&node))?;
self.nodes.insert(key.to_string(), node);
Ok("updated")
} else {
let node = Store::new_node(key, content);
self.append_nodes(std::slice::from_ref(&node))?;
self.uuid_to_key.insert(node.uuid, node.key.clone());
self.nodes.insert(key.to_string(), node);
Ok("created")
}
}
/// Soft-delete a node (appends deleted version, removes from cache).
pub fn delete_node(&mut self, key: &str) -> Result<(), String> {
let node = self.nodes.get(key)
.ok_or_else(|| format!("No node '{}'", key))?;
let mut deleted = node.clone();
deleted.deleted = true;
deleted.version += 1;
self.append_nodes(std::slice::from_ref(&deleted))?;
self.nodes.remove(key);
Ok(())
}
/// Insert a fully constructed node (for journal entries, imports, etc.)
pub fn insert_node(&mut self, node: Node) -> Result<(), String> {
self.append_nodes(std::slice::from_ref(&node))?;
self.uuid_to_key.insert(node.uuid, node.key.clone());
self.nodes.insert(node.key.clone(), node);
Ok(())
}
/// Create a new node with defaults
pub fn new_node(key: &str, content: &str) -> Node {
Node {