Files
HEL/helcli/src/lib.rs
T
Oleksandr Kozachuk 74d3296882 feat: Notion backend for the catalog + set command + ls/source/save UX
Persist the entry catalog to a Notion page instead of an external script.

- `hel store notion:<ref>` reads the dump from stdin and writes it into a
  single code block on the page; `hel load notion:<ref>` prints it back.
  `<ref>` is a page id (UUID) or a page title (case-insensitive search).
  Token from HEL_NOTION_TOKEN. Networking lives in helcli (ureq + serde_json);
  the core lib and the wasm build are untouched. argv is dispatched before the
  REPL starts, so the subcommands never read ~/.helrc or prompt for a master.

- `set <key> <value>`: runtime config (e.g. hel_dump, hel_notion_token) from
  ~/.helrc instead of env vars. The map is exported (uppercased) into spawned
  pipe/source children, so `set hel_notion_token ...` reaches `hel store`.
  Values are redacted in history.

- `ls` now matches case-insensitively.
- `source` echoes `source <target>`.
- `save` prints a `< removed` / `> added` diff against the last load/save
  snapshot so removals are noticed before they persist.
2026-06-08 16:53:23 +02:00

89 lines
2.5 KiB
Rust

//! `helcli` library: the non-interactive `hel store` / `hel load` subcommands
//! that back the `hel` REPL's persistence onto a Notion page.
//!
//! Contract (matches the old Evernote pipe scripts):
//! - `hel store notion:<ref>` reads the dump script from **stdin** and writes it
//! to the Notion page. Status/errors go to **stderr**; stdout is kept empty so
//! the parent `hel` prints its own "Passwords saved to command hel".
//! - `hel load notion:<ref>` fetches the page and writes the script to **stdout**
//! verbatim, for the parent's `source … |` to eval.
pub mod notion;
use std::io::Read;
/// `hel store notion:<ref>` — stdin (dump) → Notion. Returns a process exit code.
pub fn run_store(target: &str) -> i32 {
let reference = match notion::parse_target(target) {
Ok(r) => r,
Err(e) => {
eprintln!("hel store: {}", e);
return 2;
}
};
let mut input = String::new();
if let Err(e) = std::io::stdin().read_to_string(&mut input) {
eprintln!("hel store: failed to read stdin: {}", e);
return 1;
}
let client = match notion::Notion::from_env() {
Ok(n) => n,
Err(e) => {
eprintln!("hel store: {}", e);
return 1;
}
};
let page = match client.resolve_page(reference) {
Ok(p) => p,
Err(e) => {
eprintln!("hel store: {}", e);
return 1;
}
};
match client.write_dump(&page, &input) {
Ok(()) => {
eprintln!("hel store: saved to Notion page {}", page);
0
}
Err(e) => {
eprintln!("hel store: {}", e);
1
}
}
}
/// `hel load notion:<ref>` — Notion → stdout (dump). Returns a process exit code.
pub fn run_load(target: &str) -> i32 {
let reference = match notion::parse_target(target) {
Ok(r) => r,
Err(e) => {
eprintln!("hel load: {}", e);
return 2;
}
};
let client = match notion::Notion::from_env() {
Ok(n) => n,
Err(e) => {
eprintln!("hel load: {}", e);
return 1;
}
};
let page = match client.resolve_page(reference) {
Ok(p) => p,
Err(e) => {
eprintln!("hel load: {}", e);
return 1;
}
};
match client.read_dump(&page) {
Ok(text) => {
print!("{}", text);
0
}
Err(e) => {
eprintln!("hel load: {}", e);
1
}
}
}