1 | # Webnative SDK
|
2 |
|
3 | [![NPM](https://img.shields.io/npm/v/webnative)](https://www.npmjs.com/package/webnative)
|
4 | [![Build Status](https://travis-ci.org/fission-suite/webnative.svg?branch=master)](https://travis-ci.org/fission-suite/webnative)
|
5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/fission-suite/blob/master/LICENSE)
|
6 | [![Maintainability](https://api.codeclimate.com/v1/badges/524fbe384bb6c312fa11/maintainability)](https://codeclimate.com/github/fission-suite/webnative/maintainability)
|
7 | [![Built by FISSION](https://img.shields.io/badge/⌘-Built_by_FISSION-purple.svg)](https://fission.codes)
|
8 | [![Discord](https://img.shields.io/discord/478735028319158273.svg)](https://discord.gg/zAQBDEq)
|
9 | [![Discourse](https://img.shields.io/discourse/https/talk.fission.codes/topics)](https://talk.fission.codes)
|
10 |
|
11 | Fission helps developers build and scale their apps. We’re building a web native file system that combines files, encryption, and identity, like an open source iCloud.
|
12 |
|
13 | ---
|
14 |
|
15 | **[Read the Guide for extended documentation and getting started information](https://guide.fission.codes/developers/webnative)**.
|
16 | The API reference can be found at [webnative.fission.app](https://webnative.fission.app)
|
17 |
|
18 | ---
|
19 |
|
20 | ## What you'll find here
|
21 |
|
22 | The Fission webnative SDK offers tools for:
|
23 | - authenticating through a Fission **authentication lobby**
|
24 | (a lobby is where you can make a Fission account or link an account)
|
25 | - managing your web native **file system**
|
26 | (this is where a user's data lives)
|
27 | - tools for building DIDs and UCANs.
|
28 | - interacting with the users apps via the **platform APIs**
|
29 |
|
30 | ```ts
|
31 | // ES6
|
32 | import * as wn from 'webnative'
|
33 |
|
34 | // Browser/IIFE build
|
35 | const wn = globalThis.webnative
|
36 | ```
|
37 |
|
38 | # Authentication
|
39 |
|
40 | ```ts
|
41 | const state = await wn.initialise({
|
42 | permissions: {
|
43 | // Will ask the user permission to store
|
44 | // your apps data in `private/Apps/Nullsoft/Winamp`
|
45 | app: {
|
46 | name: "Winamp",
|
47 | creator: "Nullsoft"
|
48 | },
|
49 |
|
50 | // Ask the user permission to additional filesystem paths
|
51 | fs: {
|
52 | private: [ wn.path.directory("Audio", "Music") ],
|
53 | public: [ wn.path.directory("Audio", "Mixtapes") ]
|
54 | }
|
55 | }
|
56 |
|
57 | }).catch(err => {
|
58 | switch (err) {
|
59 | case wn.InitialisationError.InsecureContext:
|
60 | // We need a secure context to do cryptography
|
61 | // Usually this means we need HTTPS or localhost
|
62 |
|
63 | case wn.InitialisationError.UnsupportedBrowser:
|
64 | // Browser not supported.
|
65 | // Example: Firefox private mode can't use indexedDB.
|
66 | }
|
67 |
|
68 | })
|
69 |
|
70 |
|
71 | switch (state.scenario) {
|
72 |
|
73 | case wn.Scenario.AuthCancelled:
|
74 | // User was redirected to lobby,
|
75 | // but cancelled the authorisation
|
76 | break;
|
77 |
|
78 | case wn.Scenario.AuthSucceeded:
|
79 | case wn.Scenario.Continuation:
|
80 | // State:
|
81 | // state.authenticated - Will always be `true` in these scenarios
|
82 | // state.newUser - If the user is new to Fission
|
83 | // state.throughLobby - If the user authenticated through the lobby, or just came back.
|
84 | // state.username - The user's username.
|
85 | //
|
86 | // ☞ We can now interact with our file system (more on that later)
|
87 | state.fs
|
88 | break;
|
89 |
|
90 | case wn.Scenario.NotAuthorised:
|
91 | wn.redirectToLobby(state.permissions)
|
92 | break;
|
93 |
|
94 | }
|
95 | ```
|
96 |
|
97 | `redirectToLobby` will redirect you to [auth.fission.codes](https://auth.fission.codes) our authentication lobby, where you'll be able to make a Fission an account and link with another account that's on another device or browser. The function takes a second, optional, parameter, the url that the lobby should redirect back to (the default is `location.href`).
|
98 |
|
99 | `initialise` will return a rejected Promise if the browser, or context, is not supported.
|
100 |
|
101 |
|
102 |
|
103 | # Web Native File System
|
104 |
|
105 | The Web Native File System (WNFS) is built on top of the InterPlanetary File System (IPFS). It's 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").
|
106 |
|
107 | 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 publically accessible on the Internet. The private tree is encrypted so that only the owner can see the contents.
|
108 |
|
109 | All information (links, data, metadata, etc) in the private tree is encrypted. Decryption keys are stored in such a manner that access to a given folder grants access to all of its subfolders.
|
110 |
|
111 | ```ts
|
112 | // After initialising …
|
113 | const fs = state.fs
|
114 |
|
115 | // List the user's private files that belong to this app
|
116 | await fs.ls(fs.appPath())
|
117 |
|
118 | // Create a sub directory and add some content
|
119 | await fs.write(
|
120 | fs.appPath(wn.path.file("Sub Directory", "hello.txt")),
|
121 | "👋"
|
122 | )
|
123 |
|
124 | // Announce the changes to the server
|
125 | await fs.publish()
|
126 | ```
|
127 |
|
128 |
|
129 | ## Basics
|
130 |
|
131 | WNFS exposes a familiar POSIX-style interface:
|
132 | - `add`: add a file
|
133 | - `cat`: retrieve a file
|
134 | - `exists`: check if a file or directory exists
|
135 | - `ls`: list a directory
|
136 | - `mkdir`: create a directory
|
137 | - `mv`: move a file or directory
|
138 | - `read`: alias for `cat`
|
139 | - `rm`: remove a file or directory
|
140 | - `write`: alias for `add`
|
141 |
|
142 |
|
143 | ## Publish
|
144 |
|
145 | The `publish` function synchronises your file system with the Fission API and IPFS. We don't do this automatically because if you add a large set of data, you only want to do this after everything is added. Otherwise it would be too slow and we would have too many network requests to the API.
|
146 |
|
147 |
|
148 | ## Versioning
|
149 |
|
150 | 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.
|
151 |
|
152 | ```ts
|
153 | const file = await fs.get(wn.path.file("private", "Blog Posts", "article.md"))
|
154 |
|
155 | file.history.list()
|
156 | // { delta: -1, timestamp: 1606236743 }
|
157 | // { delta: -2, timestamp: 1606236532 }
|
158 |
|
159 | // Get the previous version
|
160 | file.history.back()
|
161 |
|
162 | // Go back two versions
|
163 | const delta = -2
|
164 | file.history.back(delta)
|
165 |
|
166 | // Get the first version (ie. delta -2)
|
167 | // by providing a timestamp
|
168 | file.history.prior(1606236743)
|
169 | ```
|
170 |
|
171 |
|
172 |
|
173 | # Development
|
174 |
|
175 | ```
|
176 | # install dependencies
|
177 | yarn
|
178 |
|
179 | # run development server
|
180 | yarn start
|
181 |
|
182 | # build
|
183 | yarn build
|
184 |
|
185 | # test
|
186 | yarn test:prod
|
187 | yarn test:watch
|
188 |
|
189 | # generate docs
|
190 | yarn docs
|
191 |
|
192 | # publish
|
193 | yarn publish-latest
|
194 | yarn publish-alpha
|
195 | ```
|