Using Fission with Elm - Part 2: Integrating Fission into the Elm project
Tags: elm, fission, vite
Published: 2021-10-18 22:47:24

## **Prelude**

This is part of a three-part series. In part one, I demonstrated how to use Vite to manage an Elm application. In part two (this article), I will show you how to integrate Fission into the project from part one. Part three will walk you through how to refactor the project for Fission authentication and Fission Drive.

The Github repository associated with this article can be found here:
https://github.com/xeticode/fission-with-elm-demos/tree/Part-2


---
## **Intro**

Welcome to round two! The time has come to upgrade our project from part one! The upgrade will connect the application to Fission, which I will introduce to you in a short moment. Before the introduction, I want to point out why Fission is a tool of the future. Fission uses a distributed system to store data. To one up that, Fission built a file system in the distributed system and protects it with military grade encryption. That means you can have a whole file system saved and protected across a whole network (in this case, the internet) rather than just on a remote machine or your own. And for app development, it means no need to worry about server maintenance or scaling. Anyways, I am getting ahead of myself. Without further ado, I present to you the InterPlanetary File System (IPFS) and, of course, Fission. 

### **_Enter IPFS…_**

In short, the “IPFS is a distributed system for storing and accessing files, websites, applications, and data” (for more information, see [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/)). No more need for centralized servers! Have you ever heard of blockchain? It uses a similar technical approach: peer-to-peer networking using content addressing. Say goodbye to centralized servers!

### **_Enter Fission…_**

To add to my pre-introduction, Fission is built on top of the IPFS, and implements a layer of military grade encryption. I know I mentioned this before, but it deserves more attention. Fission created a file system called Webnative File System (Wnfs). It has a huge advantage over cloud storage in that it resides in a distributed system rather than centralized servers, meaning it is backed up on a vast network of machines and not at the data centers of some tech company.

Fission developed the `Webnative SDK` to interact with Fission services. Since we are working with an Elm application, we will use the `Webnative-elm` module for Elm (see [Webnative-Elm](https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/)). Using this wrapper allows us to maximize our Elm code and minimize the JavaScript for the project. 

---
## **The Walkthrough**

NOTE: This article assumes you have completed the project as described in part 1. If you have not completed that project, please go back and follow the steps in part 1 to complete it or download the part 1 reference project. See [Fission with Elm, Part 1: Using Vite to manage Elm applications](https://dev.to/xeticode/using-fission-with-elm-part-1-using-vite-to-manage-elm-applications-4ahk) for both options.

### **_Installing Webnative dependencies_**

To start things off, we will need to install Webnative to our node modules and `elm.json` file. To do this, run the following commands in the terminal from the root directory of the project:
```
npm install --save-dev webnative webnative-elm
npx elm-json install fission-suite/webnative-elm
```
These commands do the following:
-   **_`npm install webnative webnative-elm`_** will install both `webnative` and `webnative-elm` libraries to the project (check `package.json` for the new additions).
-   **_`npx elm-json install fission-suite/webnative-elm`_** will install the Elm dependency of the `fission-suite/webnative-elm` module (check `elm.json` for the new addition). This module is a wrapper, written in Elm, for `Webnative`.

### **_Modifying js/index.js_**

This is pretty simple. 

At the top of the file, add these two lines:
```javascript
import * as webnative from “webnative”
import * as webnativeElm from “webnative-elm”
```
And after the `const app = Elm.Main.init({});` line, add these two lines:
```javascript
webnative.setup.debug({enabled:true});
webnativeElm.setup({app, webnative});
```
Here is a quick breakdown of the new lines:
-   **_`webnative.setup.debug({enabled:true});`_** toggles on the debug mode. If enabled, the debug mode will output Webnative-related messages to the `Console` tab in the `Developer Tools` window. Toggle debug mode with this window open and you will easily see the difference.
-   **_`webnativeElm.setup({app, webnative});`_** initiates the `webnative-elm` wrapper, taking the initialized Elm application and the `Webnative SDK` connection as parameters.

### **_Modifying src/Main.elm_**

#### **_Ports_**

Elm ports are how an Elm application can communicate with JavaScript, or the “outside world” as I like to call it (for an in-depth explanation of Elm ports, see [Elm Ports](https://guide.elm-lang.org/interop/ports.html)). The current state of the `Main.elm` file does not permit the use of ports. To change this, we need to change the file from a standard module to a port module. On line 1 of `Main.elm`, add `port` before `module`. We can now use ports in this Elm file! Let’s add some!
Normally, Elm ports require two ends: one Elm, and one in JavaScript. What makes this situation “abby”-normal (if you know, you know) is that this application is only concerned with interacting with Fission. The `webnative-elm` wrapper handles the JavaScript end of the Webnative-related ports. The wrapper has also consolidated all of the ports we may need into two ports: one for all Webnative requests, and one for all Webnative responses.
The `Webnative SDK` requires two ports: one for requests, and one for responses. Add these two lines just after the import block at the top of the file in `Main.elm` to satisfy the requirement:
```elm
port webnativeRequest : Webnative.Request -> Cmd msg
port webnativeResponse : (Webnative.Response -> msg) -> Sub msg 
```
Once you have them added, you will notice the red squiggles under `Webnative.Request` and `Webnative.Response`. This is because we have yet to import `Webnative` to the file. Add:
```elm
import Webnative
```
to the import block at the top of the file.

#### **_Adding Permissions_**

Every Fission-based application requires a set of defined permissions to initialize the application.
There are three functions we will add to our project to define these permissions: `appPermissions`, `fsPermissions`, and `permissions`.

_`appPermissions`_ will return a record with fields indicating the name of the application and the creator of the application. Add the following just after the Webnative ports in `Main.elm`:
```elm
appPermissions : Webnative.AppPermissions
appPermissions =
    { creator = "Trillian"
    , name = "fission-with-elm"
    }
```
This is what Fission will use to create a file path within the Wnfs to the files produced by this application (i.e. `Apps/Trillian/fission-with-elm/`). Feel free to change the creator field to your own username if you so desire.

_`fsPermissions`_ will return a record with fields indicating what public and private parts of the Wnfs for which the application will request access (“fs” stands for File System here). Add the following a couple of lines after `appPermissions`, but before `type alias Flags`:
```elm
fsPermissions : Webnative.FileSystemPermissions
fsPermissions = 
    { public =
            { directories = []
        , files = []
            }
    , private = 
            { directories = []
            , files = []
            }
    }
```
This application is not asking to access any parts of the Wnfs external to this application, so the lists will remain empty. 

_`permissions`_ the icing on the cake. This will return a record with two fields: `app` and `fs`. These correspond to the two previous code blocks we talked about. Add the following a couple of lines after `fsPermissions`, but before `type alias Flags`:
``` elm
permissions : Webnative.Permissions
permissions =
    { app = Just appPermissions
    , fs = Just fsPermissions
    }
```
We will pass this, our newly defined `permissions`, through the `webnativeRequest` port in the next step.

#### **_The `init` and `subscriptions` functions_**

##### **_`init`_**

The only difference here is changing the Cmd msg from `Cmd.none` to a command that will initialize the application as a Webnative application. The new `init` function should look like this:
```elm
init : Flags -> Url.Url -> Navigation.Key -> (Model, Cmd Msg)
init {} url key =
    ( Model
    , permissions
        |> Webnative.init
        |> webnativeRequest
    )
```
Here is a quick explanation of the new command:
- **_`permissions`_** was previously defined in the walkthrough. It indicates both the name and creator of the application and contains a list of Wnfs access requests.
- **_`Webnative.init`_** is a function of `webnative-elm` that will load a user's Wenative File System, if said user is authenticated.
- **_`webnativeRequest`_** is our port for our Webnative related requests.
**_`subscriptions`_** 
We now need to subscribe to `webnativeResponse` so the response will be properly handled and not left by the wayside. In the `subscriptions` function, change `Sub.none` to:
```elm
webnativeResponse GotWebnativeResponse
```
This will set the application to watch our `webnativeResponse` port for any changes. `GotWebnativeResponse` is a `Msg` variant we will add in a few moments and will be where we handle the response.

#### **_Adding a variant to the `Msg` and updating the `update` function_**

##### **_`Msg`_**

At this point, we have only two `Msg` variants: `UrlChanged Url.Url` and `LinkClicked Browser.UrlRequest`. To handle the `webnativeResponse`, we need to add the `GotWebnativeResponse` variant. Add the new variant to the `Msg` so that it looks like this:
```elm
type Msg 
    = UrlChanged Url.Url
    | LinkClicked Browser.UrlRequest
    | GotWebnativeResponse Webnative.Response
```
This new variant will allow us to dictate how to handle each response the application receives from `webnativeResponse`. Our friendly red squiggles should now be present on our `update` function. This is because our new `Msg` variant is a new branch the case statement in our `update` function needs to handle. The only problem? We have yet to add the branch to the case statement. This exemplifies one of the beauties of Elm, it forces us to handle each defined potential outcome or branch of whatever it is that is the subject of a case statement. Super helpful if you are, at times, forgetful 😉 Let us now add the new branch to update.

##### **_`update`_** 

That being said, as much as we may enjoy the red squiggles, they need to go. Add the following branch to the `update` function's case statement:
```elm
GotWebnativeResponse response ->
    (model, Cmd.none)
```
This will satisfy the Elm compiler, but it needs to be noted that this state of the `GotWebnativeResponse` branch does not handle anything. It is currently a dead end for the Webnative response, and for the time being, it will stay that way. The reason for this decision is that adding the proper logic to this branch fits beautifully with what is covered in part three of this series: authentication and interacting with the Wnfs. So be sure to check out part three!

---
## **The Ending**

### **_Before its over: See that it works_**

So far we have done all this work, but have yet to visually see any of that work in our app. If you have not done so already, get your dev server running. Once you have the app running, open the `Developer Tools` window in your browser, and go to the `Console` tab. You should see the following message in the list of messages:
```
[vite-plugin-elm] ports. webnativeRequest.subscribe called
```
This indicates that our application is listening to the `webnativeRequest` port! Visually, it is not much, but internally this is very important. 

### **_Adieu_**

And there you have it! The application has been upgraded with Fission integration. In this article, I showed you how to build upon what we made in the first article. In the third article, we will see the culmination as functionality is added to the project. If you wish to learn more about Fission or the Webntive-Elm module, check out these links: 
- Fission
    - https://fission.codes/
    - https://docs.fission.io/docs/
    - https://guide.fission.codes/
- Webnative-elm
    - https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/