Custom Svelte Store with Appwrite and Caching
Published: 2022-06-28 15:10:53

Who wouldn’t love cache, right? Let’s see how we can cache data with Svelte & Appwrite!

We're going to explore how we can create a Svelte store that caches our data and is dynamically updated.

Luckily for us, it’s pretty easy.

The TL;DR is:
- Create a store with set, subscribe, and load
- Set the data to the cache
- Update the cache by subscribing to the data changes
- Update the data dynamically by calling the load function in your component


## Let's set everything up :package:
We’ll start by creating an appwrite.js store to make our life easier:

```js
import { Client } from 'appwrite';

const server = {
	endpoint: import.meta.env.VITE_APP_ENDPOINT.toString(),
	project: import.meta.env.VITE_APP_PROJECT.toString(),
	collection: import.meta.env.VITE_APP_COLLECTION_ID.toString(),
	database: import.meta.env.VITE_APP_DATABASE_ID.toString()

};

const client = new Client();

client.setEndpoint(server.endpoint).setProject(server.project);

export { client, server };
```
You can check a complete example [here](https://github.com/appwrite/demo-todo-with-svelte)

This allows us to access Appwrite's sdk from wherever we want.
Remember to add all the endpoints in the .env file at your project's root.


# The fun begins! :partying_face:
Now let's initialize another store where we will implement our caching:

```js
import { client, server } from './appwrite'; // This is the store we created previously
import { Databases } from 'appwrite';
import { writable } from 'svelte/store';
import { browser } from '$app/env'; // We'll use this to check if we are in the browser

function createDocumentsListStore() {
// Magic unicorns 🦄 
}

export const documentsList = createDocumentsListStore();
```

Great! Let's work a little bit on that function. We want to create a [writable store](https://svelte.dev/tutorial/writable-stores) that can fetch our cached data, and is easy to update.

```js
function createDocumentsListStore() {
    const { subscribe, set } = writable({
/* Check if we're in the browser. 
If we are check the session storage for a item named documents, and parse it. This is our response. 
If we're not in the browser or if there is no item stored the response is null */
        response: browser ? JSON.parse(sessionStorage.getItem('documents')) : null
    });

    return {
        subscribe,
        set,
        load: async ( queries ,limit, offset) => {
            try {
                const database = new Databases(client, server.database);
                const response = database.listDocuments(
				server.collection, // We imported server from the appwrite.js store
				queries,
				limit,
				offset,
				undefined,
				undefined,
				['created_at'],
				['DESC']
			);
                set({
                    response
                });
            } catch (error) {
               // Handle the error
            }
        }
    };
}
```
So, with this function, we check if there is data in the session storage and set the response to it.

## Where's my cache? :confused:
We have a small problem: we've yet to save anything in our cache!

Luckily for us it's pretty straightforward:

```js
if (browser) {
    documentsList.subscribe((n) => sessionStorage?.setItem('documents', JSON.stringify(n.response ?? '')));
}
```

We simply subscribe to the store and save the data in the session storage each time it changes.

## :white_check_mark: set, :white_check_mark: subscribe, :wrench: load
Now we have another problem! The data is set, and our cache is always up-to-date... but the data never changes!
That's what "load" is for ;)


For example, in our component we can do something like this:

```js
<script>
import { documentsList } from './store';
let queries, limit, offset

$: documentsList.load(queries, limit, offset);
</script>

{#if $documentsList?.response?.total}
    {#each $documenstList.response.document as document}
        <pre>{document}</pre>
    {/each}
{/if}
```
This way, each time one of the arguments passed to "load" changes, the data will be updated!

And now we have an Appwrite store with cached data!

# Let's put it all together :raised_hands:
In the end our store looks like this:
```js
import { client, server } from './appwrite'; 
import { Databases } from 'appwrite';
import { writable } from 'svelte/store';
import { browser } from '$app/env'; 


function createDocumentsListStore() {
    const { subscribe, set } = writable({
        response: browser ? JSON.parse(sessionStorage.getItem('documents')) : null
    });

    return {
        subscribe,
        set,
        load: async ( queries ,limit, offset) => {
            try {
                const database = new Databases(client, server.database);
                const response = database.listDocuments(
				server.collection, 
				queries,
				limit,
				offset,
				undefined,
				undefined,
				['created_at'],
				['DESC']
			);
                set({
                    response
                });
            } catch (error) {
               // Handle the error
            }
        }
    };
}

export const documentsList = createDocumentsListStore();
if (browser) {
    documentsList.subscribe((n) => sessionStorage?.setItem('documents', JSON.stringify(n.response ?? '')));
}
```

## 🏁 Conclusion
And that’s all it takes to implement a custom svelte store with Appwrite & caching. You can view the following resources as well if you want to explore Appwrite further:

[Appwrite Docs](https://appwrite.io/docs)
[Appwrite Discord](https://appwrite.io/discord)
[Appwrite GitHub](https://github.com/appwrite/appwrite)