Svelte - Where to go from here?
Tags: javascript, svelte, webdev, html
Published: 2021-11-25 04:08:25

## The basics
I was looking forward to learn a little bit about svelte, since i've heard a lot of fuzz on it on the last couple years. There was this college task to create a web project, and my group decided to do it with svelte. 
At first, i was really thrilled with how easy it was to create new things and how fast the application was being built.
After finishing the MVP for the college discipline, i was left with some questions, which i would love to receive your inputs on, since i was kinda on a hurry developing this but would love to come back to it and code it properly! :) 

## How to properly extend components?
The first thing that struck me was how to properly extend components and leverage most of the structure. The project i've created contained some forms, and i was used to the pattern that consist on creating components for inputs so it is easier to add form group inputs to a form. On svelte, it seems that i'm not able to create a component like:
```
<script>
    export let type = 'text';
    export let label;
</script>
<div>
    <span>{label}</span>
    <input {type} />
</div>
```
The error/warning i'm getting is that the type cannot be dynamic here. The approach I took, only to finish it quicker, was to create a component for each type i've had to use, which sounded bad. **very bad**. At this point it was easier to recreate the span/input structure on each input. 

## Authentication store and user 
In order to save the bearer token used to prove authentication on the api calls, i've created a store using `writable`. To this project, i've created one for the authentication and other one to the user data. The user data one contains just the roles currently, just because i didn't need other informations so far. They looked like this:
`auth.js`
```
import user from './user';
import { writable } from 'svelte/store'
const { subscribe, set } = writable(localStorage.getItem('token'));

const logout = () => {
    set(null);
    localStorage.removeItem('token');
    user.resetUserRole();
}

const update = (newToken) => {
    localStorage.setItem('token', newToken);
    set(newToken);
    user.populateUserData();
}

export default {
    subscribe, logout, update
}
```
`user.js`
```
import { writable } from 'svelte/store'
import auth from './auth'
import { userConnector } from '../backend-connector';

const { subscribe, set } = writable(localStorage.getItem('role'))

const resetUserRole = () => {
    set(null);
    localStorage.removeItem('role');
}

const updateUserRole = (newRole) => {
    localStorage.setItem('role', newRole);
    set(newRole);
}

const populateUserData = () => {
    userConnector.getUserData().then((response) => {
        if (response.ok) {
            response.json().then((data) => {
                updateUserRole(data.roles.map((role) => role.name));
            });
        } else {
            auth.logout();
        }
    }).catch(() => {
        auth.logout();
    });
}

export default {
    subscribe, resetUserRole, updateUserRole, populateUserData
}
```
The `.then()` structure used instead of await was used just because i was teaching my colleague how a promise works and forgot to change to the classier `await` syntax, i know it looked lame hehe
The objective of the `populateUserData` method was to update user informations whenever they log in or enter the system, keeping them consistent with the `localStorage` so it is kept whenever the user quits the tab and enter again. Although i've liked the result, and using the `svelte/store get` method to read the content of any store was quite easy, i would like to know how you would place this structure!


## Role guards on route
Since there isn't any platform component for that, I've tried to create a structure that represent guards to some route based on their role on the system. It looked like this:
```
<script>
    import { Route } from 'svelte-navigator';
    import auth from '../../store/auth';
    import user from '../../store/user';

    export let path;
    export let componentToRoleMapping;

    $: isAuthenticated = $auth;
    $: role = $user;
</script>

{#if isAuthenticated && componentToRoleMapping[role] != null}
    <Route path={path} component={componentToRoleMapping[role]} />
{:else}
    <Route path={path} component={componentToRoleMapping['ELSE']} />
{/if}
```

And the `componentToRoleMapping` object looks like this:
```
let feedComponentToRoleMapping = {
     'DONOR': DonorFeed,
     'ADMIN': AdminFeed,
     'ELSE': Login
}
```
Is there some way to improve this? it felt quite right but as if something is missing. 

## Final thoughts
Svelte was a nice framework to learn, i feel like there is a lot of room for improvement, but it was one of the easiest ways to code from zero to hero that i've found so far. Almost zero bureaucracy and a lot of shortcuts, i would love to work with it in the future. If you have any inputs on how to improve this code, and/or have some material to learn more about the technology, i would love to see that!