File System (WNFS)
Working with the Webnative File System (WNFS)
The Web Native File System (WNFS) is a file system built on top of the InterPlanetary File System (IPFS). Each Fission user has their own WNFS, and apps store user files and data in it when granted permission.
Each file system has a public tree and a private tree, much like your macOS, Windows, or Linux desktop file system. The public tree is "live" and publicly accessible on the Internet. The private tree is encrypted so that only the owner can see the contents.
All information (links, data, metadata, etc.) in the private tree is encrypted. Decryption keys are stored so that access to a given directory grants access to all of its subdirectories.
WNFS is structured and functions similarly to a Unix-style file system, with one notable exception: it's a Directed Acyclic Graph (DAG), meaning that a given child can have more than one parent (think symlinks but without the "sym").

Permissions

Every file system action checks if an app has received sufficient permissions from the user. Apps request permissions when they initialize webnative. The Fission Auth Lobby grants authorization.
Apps request permission for app storage, additional private and public directories, and user apps published with the Platform APIs. For example, a notes app might request these permissions.
1
permissions: {
2
app: {
3
name: "Notes",
4
creator: "Fission"
5
},
6
fs: {
7
private: [ wn.path.directory("Notes") ],
8
public: [ wn.path.directory("Notes") ]
9
},
10
platform: {
11
apps: []
12
}
13
}
Copied!
The app would have access to its dedicated app storage and public and private Notes directories.
Apps request permissions.app to store user data in a default app storage directory and other public and private directories. Webnative creates these directories for your app if they do not already exist.
Platform permissions. The platform permissions could be left out of this example because this app will not need them. See the Platform API guide for more information on working with user apps.
The initialize function will return a NotAuthorised scenario if one of the UCAN will expire in one day to minimize the likelihood of receiving an expired permissions error. But to be safe, apps should also account for this error.

WNFS

WNFS exposes a POSIX-style interface:
    add: add a file
    cat: retrieve a file
    exists: check if a file or directory exists
    ls: list a directory
    mkdir: create a directory
    mv: move a file or directory
    read: alias for cat
    rm: remove a file or directory
    write: alias for add
1
// After initialising …
2
const fs = state.fs
3
​
4
// List the user's private files that belong to this app
5
await fs.ls(fs.appPath())
6
​
7
// Create a sub directory and add some content
8
await fs.write(
9
fs.appPath(wn.path.file("Sub Directory", "hello.txt")),
10
"πŸ‘‹"
11
)
12
​
13
// Announce the changes to the server
14
await fs.publish()
Copied!

Publish

The publish function synchronizes your file system with the Fission API and IPFS. WNFS does not publish changes automatically because it is more practical to batch changes in some cases. For example, a large data set is better published once than over multiple calls to publish.
Returns: CID the updated root CID for the file system.
Remember to publish! If you do not call publish after making changes, user data will not be persisted to WNFS.

API Summary

Methods

Methods for interacting with the filesystem all use absolute paths.
Paths created by path functions have a FilePath or DirectoryPath type. Methods with a DistinctivePath param accept either a FilePath or a DirectoryPath.
The FileContentthat WNFS can store includes FileContentRaw, Blob, string, number, and boolean. FileContentRaw is Uint8Array. In addition, the private file system can store Objects.
add
Adds file content at a given path.
Params:
    path: FilePath required
    content: FileContentrequired
Returns: CID the updated root CID for the file system
Example:
1
const content = "hello world"
2
​
3
// create a file called "file" at "public/path/to/a/"
4
await fs.add(
5
wn.path.file("public", "path", "to", "a", "file"),
6
content
7
)
Copied!
cat
Retrieves some file content at a given path.
Params:
    path: FilePath required
Returns: FileContent
Example:
1
const content = await fs.cat(wn.path.file("public", "some", "file"))
Copied!
exists
Checks if there is anything located at a given path.
Params:
    path: DistinctivePath required
Returns: boolean
Example:
1
const bool = await fs.exists(wn.path.file("private", "some", "file"))
Copied!
get
Retrieves the node at the given path, either a File or Tree object
Params:
    path: DistinctivePath required
Returns: Tree | File | null
Example:
1
const node = await fs.get(wn.path.directory("public", "some", "directory"))
Copied!
ls
Returns a list of links at a given directory path
Params:
    path: DirectoryPath required
Returns: { [name: string]: Link } Object with the file name as the key and its Link as the value.
Example:
1
// public directory
2
const publicPath = wn.path.directory("public", "some", "directory")
3
const publicLinksObject = await fs.ls(publicPath)
4
​
5
// private directory
6
const privatePath = wn.path.directory("private", "some", "directory")
7
const privateLinksObject = await fs.ls(privatePath)
8
​
9
// convert private links object to a list
10
const links = Object.entries(privateLinksObject)
11
​
12
// working with links
13
const data = await Promise.all(links.map(([name, _]) => {
14
return fs.cat(
15
wn.path.file("private", "some", "directory", `${name}`)
16
)
17
}))
Copied!
mkdir
Creates a directory at the given path
Params:
    path: DirectoryPath required
Returns: CID the updated root CID for the file system
Example:
1
// create a directory called "directory" at "public/some/"
2
const updatedCID = await fs.mkdir(wn.path.directory("public", "some", "directory"))
Copied!
mv
Move a directory or file from one path to another.
Params:
    from: DistinctivePath required
    to: DistinctivePath required
Returns: CID the updated root CID for the file system
Example:
1
const fromPath = wn.path.file("public", "doc.md")
2
const toPath = wn.path.file("private", "Documents", "notes.md")
3
const updatedCID = await fs.mv(fromPath, toPath)
Copied!
rm
Removes a file or directory at a given path.
Params:
    path: DistinctivePath required
Returns: CID the updated root CID for the file system
Example:
1
const updatedCID = await fs.rm(wn.path.file("private", "some", "file"))
Copied!
write
Alias for add.
Params:
    path: FilePath required
    content: FileContent required
Returns: CID the updated root CID for the file system
Example:
1
const content = "hello world"
2
const updatedCID = await fs.write(
3
wn.path.file("private", "some", "file"),
4
content
5
)
Copied!

Versioning

Each file and directory has a history property, which you can use to get an earlier version of that item. We use the delta variable as the order index, primarily because the timestamps can be slightly out of sequence due to device inconsistencies.
1
const articlePath = wn.path.file("private", "Blog Posts", "article.md")
2
const file = await fs.get(articlePath)
3
​
4
file.history.list()
5
// { delta: -1, timestamp: 1606236743 }
6
// { delta: -2, timestamp: 1606236532 }
7
​
8
// List more than (by default) 5 versions
9
file.history.list(10)
10
​
11
// Get the previous version
12
file.history.back()
13
​
14
// Go back two versions
15
const delta = -2
16
file.history.back(delta)
17
​
18
// Get a version strictly before a timestamp
19
// The first version (delta -2) is prior to
20
// the second version (delta -1) timestamp
21
file.history.prior(1606236743)
Copied!
Requesting many versions with file.history.list can be slow. The acceptable delay will depend on your application.
Last modified 1mo ago
Export as PDF
Copy link