//! The bindgen API for PublicFile. use chrono::{DateTime, Utc}; use js_sys::{Error, Promise, Uint8Array}; use std::rc::Rc; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen_futures::future_to_promise; use wnfs::{ipld::Cid, BlockStore as WnfsBlockStore, Id, PublicFile as WnfsPublicFile}; use crate::{ fs::{metadata::JsMetadata, utils::error, BlockStore, ForeignBlockStore, JsResult}, value, }; //-------------------------------------------------------------------------------------------------- // Type Definitions //-------------------------------------------------------------------------------------------------- /// A file in a WNFS public file system. #[wasm_bindgen] pub struct PublicFile(pub(crate) Rc); //-------------------------------------------------------------------------------------------------- // Implementations //-------------------------------------------------------------------------------------------------- #[wasm_bindgen] impl PublicFile { /// Creates a new file in a WNFS public file system. #[wasm_bindgen(constructor)] pub fn new(time: &js_sys::Date, cid: Vec) -> JsResult { let time = DateTime::::from(time); let cid = Cid::try_from(&cid[..]).map_err(error("Invalid CID"))?; Ok(PublicFile(Rc::new(WnfsPublicFile::new(time, cid)))) } /// Gets a unique id for node. #[wasm_bindgen(js_name = "getId")] pub fn get_id(&self) -> String { self.0.get_id() } /// Stores a file in provided block store. pub fn store(&self, store: BlockStore) -> JsResult { let file = Rc::clone(&self.0); let mut store = ForeignBlockStore(store); Ok(future_to_promise(async move { let cid = file .store(&mut store) .await .map_err(|e| Error::new(&format!("Cannot add to store: {e}")))?; let cid_u8array = Uint8Array::from(&cid.to_bytes()[..]); Ok(value!(cid_u8array)) })) } /// Loads a file given its CID from the block store. pub fn load(cid: Vec, store: BlockStore) -> JsResult { let store = ForeignBlockStore(store); let cid = Cid::try_from(cid).map_err(|e| Error::new(&format!("Cannot parse cid: {e}")))?; Ok(future_to_promise(async move { let file: WnfsPublicFile = store .get_deserializable(&cid) .await .map_err(|e| Error::new(&format!("Couldn't deserialize directory: {e}")))?; Ok(value!(PublicFile(Rc::new(file)))) })) } /// Gets the previous CID(s) of the file. /// This will usually be an array of a single CID, but may be /// - an empty array, if this is the first revision of a file /// - an array with multiple elements if this is the merge node of /// multiple concurrent changes to the file. #[wasm_bindgen(js_name = "previousCids")] pub fn previous_cids(&self) -> Vec { let cids = self.0.get_previous(); let arr: Vec = cids .iter() .map(|cid| Uint8Array::from(&cid.to_bytes()[..])) .collect(); arr } /// Gets the metadata of this file. pub fn metadata(&self) -> JsResult { JsMetadata(self.0.get_metadata()).try_into() } /// Gets the content cid of the file. #[wasm_bindgen(js_name = "contentCid")] pub fn content_cid(&self) -> Vec { self.0.get_content_cid().to_bytes() } }