8个版本

0.1.9 2022年10月21日
0.1.8 2022年10月21日
0.1.7 2022年8月25日
0.1.6 2022年5月23日
0.1.0 2022年4月14日

#350 in WebAssembly

Apache-2.0

4MB
8K SLoC

Wasm WNFS

该项目实现了在浏览器中使用WebNative 文件系统 (WNFS) Rust实现所需的必要JavaScript绑定。

WNFS是一个具有版本控制的、内容寻址的分布式文件系统,包含私有和公共子系统。私有文件系统被加密,只有拥有正确密钥的用户才能访问其内容。它旨在防止推断元数据,如文件树的结构。WNFS文件系统的另一部分是一个更简单的公共文件系统,未加密,任何拥有正确地址的人都可以访问。

WNFS还支持文件树的协作编辑,多个用户可以同时编辑同一棵树。

WNFS文件树可以从IPLD图进行序列化和反序列化,并具有可扩展的元数据部分。这允许WNFS被其他基于IPLD的工具和系统理解。

概述

设置项目

  • 安装 wasm-pack

    cargo install wasm-pack
    
  • 安装依赖项

    yarn
    
  • 安装 playwright 二进制文件

    npx playwright install
    
  • 构建项目

    wasm-pack build
    

用法

WNFS对您希望持久化内容或文件树的位置没有意见。相反,API期望任何实现了异步 BlockStore 接口的对象。此实现还将系统级操作推迟到用户;要求将时间、随机数生成等操作从接口传递进来。这使得具有通用wasm界面的操作变得干净利落。

让我们看看如何与公共目录一起工作的示例。在这里,我们将使用自定义编写的基于内存的块存储。

import { MemoryBlockStore } from "<custom>";
import { PublicDirectory } from "wnfs";

const dir = new PublicDirectory(new Date());
const store = new MemoryBlockStore();

var { rootDir } = await dir.mkdir(["pictures", "cats"], new Date(), store);

// Create a sample CIDv1.
const cid = Uint8Array.from([
  1, 112, 18, 32, 195, 196, 115, 62, 200, 175, 253, 6, 207, 158, 159, 245, 15,
  252, 107, 205, 46, 200, 90, 97, 112, 0, 75, 183, 9, 102, 156, 49, 222, 148,
  57, 26,
]);

// Add a file to /pictures/cats.
var { rootDir } = await rootDir.write(
  ["pictures", "cats", "tabby.png"],
  cid,
  time,
  store
);

// Create and add a file to /pictures/dogs directory.
var { rootDir } = await rootDir.write(
  ["pictures", "dogs", "billie.jpeg"],
  cid,
  time,
  store
);

// Delete /pictures/cats directory.
var { rootDir } = await rootDir.rm(["pictures", "cats"], store);

// List all files in /pictures directory.
var { result } = await rootDir.ls(["pictures"], store);

console.log("Files in /pictures directory:", result);

您可能会注意到我们在后续操作中使用每个操作返回的 rootDir。这是因为WNFS内部状态是不变的,每个操作都可能返回一个新的根目录。这允许我们在需要时跟踪和回滚更改。它还使协作编辑更容易实现和推理。有关文件系统不可变性的基本演示,请参阅此处

另一方面,私有文件系统要复杂一些。在将其持久化到块存储之前,我们使用哈希数组映射树(HAMT)作为私有文件树的中间格式。HAMT帮助我们隐藏文件树的层次结构。

import { MemoryBlockStore, Rng } from "<custom>";
import { PrivateDirectory, PrivateForest, Namefilter } from "wnfs";

const initialHamt = new PrivateForest();
const rng = new Rng();
const store = new MemoryBlockStore();
const dir = new PrivateDirectory(new Namefilter(), new Date(), rng);

var { rootDir, hamt } = await root.mkdir(
  ["pictures", "cats"],
  true,
  new Date(),
  initialHamt,
  store,
  rng
);

// Add a file to /pictures/cats.
var { rootDir, hamt } = await rootDir.write(
  ["pictures", "cats", "tabby.png"],
  cid,
  time,
  store
);

// Create and add a file to /pictures/dogs directory.
var { rootDir, hamt } = await rootDir.write(
  ["pictures", "cats", "billie.png"],
  true,
  new Uint8Array([1, 2, 3, 4, 5]),
  new Date(),
  hamt,
  store,
  rng
);

// Delete /pictures/cats directory.
var { rootDir, hamt } = await rootDir.rm(
  ["pictures", "cats"],
  true,
  hamt,
  store,
  rng
);

// List all files in /pictures directory.
var { result } = await rootDir.ls(["pictures"], true, hamt, store);

console.log("Files in /pictures directory:", result);

测试项目

  • 运行测试

    yarn playwright test
    

发布包

  • 构建项目

    rs-wnfs build --wasm
    
  • pkg 目录发布

    cd pkg
    
    npm publish
    

依赖项

~14–25MB
~359K SLoC