A thin wrapper around webnative for Elm.
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.
elm install fission-suite/webnative-elm
# requires webnative version 0.24 or later
npm install webnative
npm install webnative-elm
Setup the necessary ports on your Elm app.
port module Ports exposing (..)
import Webnative
port webnativeRequest : Webnative.Request -> Cmd msg
port webnativeResponse : (Webnative.Response -> msg) -> Sub msg
Then import the javascript portion of this library to connect up the ports.
import * as webnativeElm from "webnative-elm"
// elmApp = Elm.Main.init()
webnativeElm.setup({ app: elmApp })
Once we have that setup, we can write our webnative Elm code.
import Webnative exposing (Artifact(..), DecodedResponse(..))
import Webnative.Path as Path
import Wnfs
-- INIT
appPermissions : Webnative.AppPermissions
appPermissions =
{ creator = "Fission", name = "Example" }
permissions : Webnative.Permissions
permissions =
{ app = Just appPermissions, fs = Nothing }
init : (Model, Cmd Msg)
init =
( {}
, permissions
|> Webnative.init
|> Ports.webnativeRequest
-- π We'll get a response in the `GotWebnativeResponse` msg
)
-- FILESYSTEM PREP
type Tag
= ReadHelloTxt
| Mutation
| PointerUpdated
base : Wnfs.Base
base =
Wnfs.AppData appPermissions
-- UPDATE
type Msg
= GotWebnativeResponse Webnative.Response
--
| ReadWnfsFile
| WriteToWnfsFile
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
GotWebnativeResponse response ->
case Webnative.decodeResponse tagFromString response of
-----------------------------------------
-- π
-----------------------------------------
Webnative ( Initialisation state ) ->
if Webnative.isAuthenticated state then
loadUserData
else
welcome
-----------------------------------------
-- πΎ
-----------------------------------------
Wnfs ReadHelloTxt ( Utf8Content helloContents ) ->
-- Do something with content from hello.txt
Wnfs Mutation _ ->
( model
, { tag = PointerUpdated }
|> Wnfs.publish
|> Ports.webnativeRequest
)
-----------------------------------------
-- π₯΅
-----------------------------------------
-- Do something with the errors,
-- here we cast them to strings
WebnativeError err -> Webnative.error err
WnfsError err -> Wnfs.error err
--
ReadWnfsFile ->
{ path = Path.file [ "hello.txt" ]
, tag = tagToString ReadHelloTxt
}
|> Wnfs.readUtf8 base
|> Ports.webnativeRequest
|> Tuple.pair model
WriteToWnfsFile ->
"π"
|> Wnfs.writeUtf8 base
{ path = Path.file [ "hello.txt" ]
, tag = tagToString Mutation
}
|> Ports.webnativeRequest
|> Tuple.pair model
subscriptions : Sub Msg
subscriptions =
Ports.webnativeResponse GotWebnativeResponse
-- TAG ENCODING/DECODING
tagToString : Tag -> String
tagToString tag =
case tag of
ReadHelloTxt -> "ReadHelloTxt"
Mutation -> "Mutation"
tagFromString : String -> Result String Tag
tagFromString string =
case string of
"ReadHelloTxt" -> Ok ReadHelloTxt
"Mutation" -> Ok Mutation
_ -> Err "Invalid tag"
You can chain webnative commands in Elm by providing a tag, which is then attached to the response. In the following example I have a custom type for my tags, which I then encode/decode to/from a string.
import Webnative exposing (DecodedResponse(..))
import Webnative.Path as Path
import Wnfs
type Tag = Mutation | PointerUpdated
-- Request
Wnfs.writeUtf8 base
{ path = Path.file [ "hello.txt" ]
, tag = tagToString Mutation
}
-- Response
case Webnative.decodeResponse tagFromString response of
Wnfs Mutation _ ->
( model
, Ports.webnativeRequest (Wnfs.publish PointerUpdated)
)
We don't support all the functions from webnative yet.
For now you can do the following from Elm:
- All WNFS interactions
- Redirect to lobby
- Leave / Sign out
More coming later.
Let us know if you have any requests.
Alternatively you can load the filesystem separately.
You may want to do this when working with a web worker.
import Webnative exposing (defaultInitOptions)
Webnative.initWithOptions
{ defaultInitOptions | loadFileSystem = False }
And then load it either in Elm or in javascript.
Webnative.loadFileSystem permissions
const fs = await webnative.loadFileSystem(permissions)
webnativeElm.setup({ app: elmApp, getFs: () => fs })
There's various customisation options:
webnativeElm.setup({
app: elmApp,
portNames: {
incoming: "webnativeRequest",
outgoing: "webnativeResponse"
},
webnative: require("webnative")
})