Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some WASM APIs #39

Merged
merged 9 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions crates/fs/common/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ pub enum UnixFsMode {
/// See <https://docs.ipfs.io/concepts/file-systems/#unix-file-system-unixfs>
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UnixFsMetadata {
pub(crate) created: i64,
pub(crate) modified: i64,
pub(crate) mode: UnixFsMode,
pub(crate) kind: UnixFsNodeKind,
pub created: i64,
pub modified: i64,
pub mode: UnixFsMode,
pub kind: UnixFsNodeKind,
}

/// The metadata of a node on the WNFS file system.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Metadata {
pub(crate) unix_fs: UnixFsMetadata,
pub(crate) version: Version,
pub unix_fs: UnixFsMetadata,
pub version: Version,
}

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -208,6 +208,19 @@ impl TryFrom<&str> for UnixFsNodeKind {
}
}

impl From<&UnixFsNodeKind> for String {
fn from(kind: &UnixFsNodeKind) -> Self {
match kind {
UnixFsNodeKind::Raw => "raw".into(),
UnixFsNodeKind::File => "file".into(),
UnixFsNodeKind::Dir => "dir".into(),
UnixFsNodeKind::Metadata => "metadata".into(),
UnixFsNodeKind::SymLink => "symlink".into(),
UnixFsNodeKind::HAMTShard => "hamt-shard".into(),
}
}
}

//--------------------------------------------------------------------------------------------------
// Tests
//--------------------------------------------------------------------------------------------------
Expand Down
34 changes: 34 additions & 0 deletions crates/wasm/fs/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::fs::JsResult;
use crate::value;
use js_sys::{Object, Reflect};
use wasm_bindgen::JsValue;
use wnfs::{Metadata, UnixFsMetadata};

pub(crate) struct JsMetadata<'a>(pub(crate) &'a Metadata);

impl TryInto<JsValue> for JsMetadata<'_> {
type Error = js_sys::Error;

fn try_into(self) -> JsResult<JsValue> {
let metadata = Object::new();
let unix_meta = unix_fs_to_js_value(&self.0.unix_fs)?;
let version = value!(self.0.version.to_string());

Reflect::set(&metadata, &value!("unixMeta"), &unix_meta)?;
Reflect::set(&metadata, &value!("version"), &version)?;

Ok(value!(metadata))
}
}

fn unix_fs_to_js_value(unix_fs: &UnixFsMetadata) -> JsResult<JsValue> {
let obj = Object::new();
let kind = value!(String::from(&unix_fs.kind));

Reflect::set(&obj, &value!("created"), &value!(unix_fs.created))?;
Reflect::set(&obj, &value!("modified"), &value!(unix_fs.modified))?;
Reflect::set(&obj, &value!("mode"), &value!(unix_fs.mode.clone() as u32))?;
Reflect::set(&obj, &value!("kind"), &kind)?;
matheus23 marked this conversation as resolved.
Show resolved Hide resolved

Ok(value!(obj))
}
1 change: 1 addition & 0 deletions crates/wasm/fs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod blockstore;
mod metadata;
mod public;
mod types;

Expand Down
59 changes: 54 additions & 5 deletions crates/wasm/fs/public/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use wnfs::{
OpResult as WnfsOpResult, PublicDirectory as WnfsPublicDirectory,
PublicNode as WnfsPublicNode,
},
Id,
BlockStore as WnfsBlockStore, Id,
};

use crate::fs::{BlockStore, ForeignBlockStore, JsResult, PublicNode};
Expand Down Expand Up @@ -86,6 +86,21 @@ impl PublicDirectory {
}))
}

/// Loads a directory given its CID from the block store.
pub fn load(cid: Uint8Array, store: BlockStore) -> JsResult<Promise> {
let store = ForeignBlockStore(store);
let cid = Cid::read_bytes(cid.to_vec().as_slice())
.map_err(|e| Error::new(&format!("Cannot parse cid: {e}")))?;
Ok(future_to_promise(async move {
let directory: WnfsPublicDirectory = store
.get_deserializable(&cid)
.await
.map_err(|e| Error::new(&format!("Couldn't deserialize directory: {e}")))?;

Ok(value!(PublicDirectory(Rc::new(directory))))
}))
}

/// Reads specified file content from the directory.
pub fn read(&self, path_segments: &Array, store: BlockStore) -> JsResult<Promise> {
let directory = Rc::clone(&self.0);
Expand All @@ -98,7 +113,9 @@ impl PublicDirectory {
.await
.map_err(|e| Error::new(&format!("Cannot read from directory: {e}")))?;

Ok(utils::create_op_result(root_dir, result.to_string())?)
let cid_u8array = Uint8Array::from(&result.to_bytes()[..]);

Ok(utils::create_op_result(root_dir, cid_u8array)?)
}))
}

Expand All @@ -116,7 +133,7 @@ impl PublicDirectory {

let result = result
.iter()
.map(|(name, _)| value!(name))
.flat_map(|(name, metadata)| utils::create_ls_entry(name, metadata))
.collect::<Array>();

Ok(utils::create_op_result(root_dir, result)?)
Expand Down Expand Up @@ -169,6 +186,7 @@ impl PublicDirectory {
}

/// Moves a specified path to a new location.
#[wasm_bindgen(js_name = "basicMv")]
pub fn basic_mv(
&self,
path_segments_from: &Array,
Expand Down Expand Up @@ -216,6 +234,24 @@ impl PublicDirectory {
}))
}

#[wasm_bindgen(js_name = "baseHistoryOn")]
pub fn base_history_on(&self, base: &PublicDirectory, store: BlockStore) -> JsResult<Promise> {
let directory = self.0.clone();
let base = base.0.clone();
let mut store = ForeignBlockStore(store);

Ok(future_to_promise(async move {
let WnfsOpResult { root_dir, .. } = directory
.base_history_on(base, &mut store)
.await
.map_err(|e| {
Error::new(&format!("Cannot do history rebase (base_history_on): {e}"))
})?;

Ok(utils::create_op_result(root_dir, JsValue::NULL)?)
}))
}

/// Converts directory to a node.
#[wasm_bindgen(js_name = "asNode")]
pub fn as_node(&self) -> PublicNode {
Expand All @@ -236,10 +272,10 @@ impl PublicDirectory {
mod utils {
use std::rc::Rc;

use crate::{fs::JsResult, value};
use crate::{fs::metadata::JsMetadata, fs::JsResult, value};
use js_sys::{Array, Error, Object, Reflect};
use wasm_bindgen::JsValue;
use wnfs::public::PublicDirectory as WnfsPublicDirectory;
use wnfs::{public::PublicDirectory as WnfsPublicDirectory, Metadata};

use super::PublicDirectory;

Expand Down Expand Up @@ -273,4 +309,17 @@ mod utils {

Ok(value!(op_result))
}

pub(crate) fn create_ls_entry(name: &String, metadata: &Metadata) -> JsResult<JsValue> {
let entry = Object::new();

Reflect::set(&entry, &value!("name"), &value!(name))?;
Reflect::set(
&entry,
&value!("metadata"),
&JsMetadata(metadata).try_into()?,
)?;

Ok(value!(entry))
}
}
7 changes: 4 additions & 3 deletions crates/wasm/tests/fs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ test.describe("PublicDirectory", () => {
});

expect(result.length).toBe(2);
expect(result.includes("dogs")).toBe(true);
expect(result.includes("cats")).toBe(true);
expect(result[0].name).toBe("cats");
expect(result[1].name).toBe("dogs");
});

test("rm can remove children from directory", async ({ page }) => {
Expand Down Expand Up @@ -137,6 +137,7 @@ test.describe("PublicDirectory", () => {
return result;
});

expect(result).toEqual(["dogs"]);
expect(result.length).toEqual(1)
expect(result[0].name).toEqual("dogs");
});
});
7 changes: 5 additions & 2 deletions scripts/rs-wnfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,11 @@ build_wasm() {
display_header "💿 | BUILDING WASM-WNFS PROJECT | 💿"
echo "script_dir = $script_dir"
cd $script_dir/../crates/wasm
wasm-pack build --target nodejs
sed -i ".bak" -e 's/"name": "wasm-wnfs"/"name": "wnfs"/g' pkg/package.json
wasm-pack build --target web
sed -i ".bak" \
-e 's/"name": "wasm-wnfs"/"name": "wnfs",\n "type": "module"/g' \
-e 's/"module": "wasm_wnfs\.js"/"module": "wasm_wnfs\.js",\n "main": "wasm_wnfs\.js"/g' \
pkg/package.json
rm pkg/package.json.bak
}

Expand Down