I'm trying to implement JWT authentication in my SvelteKit SPA. I'm new to TS (and thus Svelte[Kit]) and there is a lot to learn, so my problem might not strictly be with Svelte and its store system but also with TS in general.
My root +layout.svelte for all routes that require authentication looks like this:
<script lang="ts">
import { goto } from '$app/navigation';
import auth from '$lib/stores/auth';
</script>
{#await auth.init() then user}
<slot />
{:catch}
{goto('/login')}
{/await}
lib/stores/auth.ts:
import { writable, get } from 'svelte/store';
import { jwtDecode, type JwtPayload } from 'jwt-decode';
type User = {
email: string;
name: string;
};
interface Token extends JwtPayload {
user: User;
}
function createStore() {
const user = {};
const { subscribe, update, set } = writable(user as User);
return {
subscribe,
async init() {
const tokenStr = localStorage.getItem('token')!;
const token = jwtDecode<Token>(tokenStr);
set(token.user);
},
setToken(tokenStr: string) {
const token = jwtDecode<Token>(tokenStr);
let storeValue = get(this);
storeValue = token.user;
update(() => storeValue);
localStorage.setItem('token', tokenStr);
}
};
}
export default createStore();
My problem is that I can't use the user result object in my layout (e.g. to display the username in the navigation, etc.) It is undefined. Why is that?
So I ended up using svelte-persisted-store as also suggested by @José.
lib/stores/auth.ts:layout.svelte: