implement basic KV binding
parent
0547cdd0c3
commit
243a64b7b9
@ -0,0 +1,45 @@
|
||||
// Utility functions and structs for the blogging system
|
||||
// Due to limitations of the Cloudflare Workers KV, we do not
|
||||
// store the entire state in one record; instead, different
|
||||
// parts are stroed in different records. This also increases
|
||||
// efficiency, since the program won't need to load anything
|
||||
// unnecessary from KV.
|
||||
use crate::store;
|
||||
use crate::utils::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::vec::Vec;
|
||||
|
||||
// A list of the UUIDs of all published blog posts
|
||||
// This should be SORTED with the newest posts at lower indices (closer to 0)
|
||||
// The user may edit this via KV UI to change ordering and such
|
||||
// by default new posts are always added to the top
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PostsList(pub Vec<String>);
|
||||
|
||||
impl PostsList {
|
||||
pub async fn load() -> PostsList {
|
||||
match store::get_obj("posts_list").await {
|
||||
Ok(v) => PostsList(v),
|
||||
// Don't panic on empty
|
||||
// TODO: What if the user messed up when editing?
|
||||
// That would cause a decode failure and all data will be gone
|
||||
// if a new post is added or updated (overwriting the KV value)
|
||||
// under this logic
|
||||
// (if no new post is added then nothing bad would happen;
|
||||
// the user would probably notice when trying to visit the blog home page)
|
||||
Err(_) => PostsList(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_post(&self, uuid: &str) -> bool {
|
||||
self.0.contains(&uuid.into())
|
||||
}
|
||||
|
||||
// Add a post to the list and then update the record in KV
|
||||
// Also consumes self, as this should normally be the last action
|
||||
// in an API call
|
||||
pub async fn add_post(mut self, uuid: &str) -> MyResult<()> {
|
||||
self.0.insert(0, uuid.into());
|
||||
store::put_obj_pretty("posts_list", self.0).await
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// Bindings to Cloudflare Workers KV
|
||||
use crate::utils::*;
|
||||
use js_sys::Promise;
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = PAPRIKA, js_name = "get")]
|
||||
fn kv_get(key: &str) -> Promise;
|
||||
#[wasm_bindgen(js_namespace = PAPRIKA, js_name = "put")]
|
||||
fn kv_put_str(key: &str, value: &str) -> Promise;
|
||||
}
|
||||
|
||||
pub async fn get_str(key: &str) -> MyResult<String> {
|
||||
Ok(JsFuture::from(kv_get(key)).await.internal_err()?.as_string().unwrap())
|
||||
}
|
||||
|
||||
pub async fn get_obj<T: DeserializeOwned>(key: &str) -> MyResult<T> {
|
||||
let res = get_str(key).await?;
|
||||
Ok(serde_json::from_str(&res).internal_err()?)
|
||||
}
|
||||
|
||||
pub async fn put_str(key: &str, value: &str) -> MyResult<()> {
|
||||
JsFuture::from(kv_put_str(key, value)).await.internal_err()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn put_obj<T: Serialize>(key: &str, value: T) -> MyResult<()> {
|
||||
put_str(key, &serde_json::to_string(&value).internal_err()?).await
|
||||
}
|
||||
|
||||
// Some objects may be available for manual editing; thus making it pretty may be helpful
|
||||
// For example, the user may want to manually edit the order in which posts appear
|
||||
pub async fn put_obj_pretty<T: Serialize>(key: &str, value: T) -> MyResult<()> {
|
||||
put_str(key, &serde_json::to_string_pretty(&value).internal_err()?).await
|
||||
}
|
Loading…
Reference in New Issue