The modern way of setting up IndexedDB
Tags: database, webdev, indexeddb, storage
Published: 2021-08-18 13:04:12

<sub>*Updated for Aug 2021*</sub>
<br>
Look! What is that? Is it a plane? is it localStorage?
No, it's IndexedDB - an unnecessarily complicated low-level API for client-side storage of lots of structured data.
I would like to meet the person who instantly understands how to implement it into their project, because he might have the ability to crack this modern version of the Enigma Code.

Pathetic jokes aside; I was required to use this pretty cool way of storing data for a school project, and decided to document how I made it work. For my future self, and any other frustrated developer who has also started yelling at their rubber ducky for not giving the answer.

To make it very clear, I know very little of what goes on behind the API, but simply how I personally made it work - and how you, future Thor, might also need to.
SO! Let's get started.

IndexedDB isn't exactly a normal SQL-based relational database, but more of a javascript-based object oriented one. Ever seen this type of data before? 
`key: "value"`
That's what we're working with, and it's great for simple applications like the Movie PWA I was building.
Right out the box the API works by events, but I recommend ditching that and instead installing Jake Archibald's 'IndexedDB Promised Library', which pretty much mirrors the API, and uses... you guessed it. Promises.

## Disclaimer
Many tutorials like the one by Google, use an old version of the library, and will **not** work if you follow it. Ask me how I figured that out.

To understand how IndexedDB works, you first need to know the different ways of handling data therein.
Before anything can be done, the database has to be 'opened'. I'm putting that in quotes, because you actually also need to 'open' it to create it, so you're kind of doing both at the same time.
The way you'll probably see it imported in online tutorials is like this:
```javascript
import idb from 'idb';
```
You would use it like `idb.open()`
but since becoming a module we're instead required to import it like so:
```javascript
import { openDB } from 'idb';
```
<br>
### Highest Level
To start the whole process we'll open/create the actual database
For that create an async function somewhere and write this inside.
```javascript
async function myDatabase() {
   const db = await openDB('Database_name', 1, {

   });
}
```
This is the highest level of the database.
You can create as many as you want, but usually there's only one of these per app.

### The Object Store
This is one of the buckets that we're gonna store our data in, it's like a table in traditional relational databases.
```javascript
const db = await openDB('Database_name', 1, {
   upgrade(db) {
     const store = db.createObjectStore('name_of_store', {
        keyPath: "id_of_the_thing"
     });
   }
});
```
We need the `upgrade` if this version of the database hasn't been opened before, which it hasn't... I don't think.
Honestly I would look this up if you need to, because the methods of IndexedDB are quite weirdly named and you might not need it in your project. But for the sake of not breaking mine, I'm keeping it for now.

Inside of that, we're creating the *store*, also called a bucket, or table. Well, It's where we *store* our data. Ha.
If your project breaks, or you need a random ID for your stuff, add an autoIncrement like this:
```javascript
const store = db.createObjectStore('name_of_store', {
   keyPath: "id_of_the_thing",
   autoIncrement: true
});
```
#### Test time!
Whenever or however you call your async function, an IndexedDB should show up in your browsers dev tools. You'll find it in the application tab, right next to localStorage.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df5pwyswgmb3dt0uwyt9.png)
Cool. We have a database, and a store/bucket/table ready to receive our stuff.

To add our first item to the store, stay inside our `async function`, and write like so:
```javascript
await db.add('name_of_store', {
   apple: "delicious"
});
```
And in the browser:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uivdqiywmvgpjl6z5m98.png)
We have our first piece of data!

But... how do you get the thing back you ask?
```javascript
var myThing = await db.get('name_of_store', 1)
```
The 1 is the id of our apple in the store. If you specified it to be something specific instead of an auto incremented one, you of course use that instead.
The variable `myThing` now has an object ready to be used!
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvr03d4jgxyewokw029m.png)

## Full code
```javascript
async function myDatabase() {
   // It's a good idea to have this error handling just in case
   if (!('indexedDB' in window)) {
      console.log('This browser doesn\'t support IndexedDB');
      return;
   }

   const db = await openDB('Database_name', 1, {
      upgrade(db) {
        const store = db.createObjectStore('name_of_store', {
           keyPath: "id_of_the_thing",
           autoIncrement: true
        });
      }
   });

   await db.add('name_of_store', {
      apple: "delicious"
   });

   var myThing = await db.get('name_of_store', 1);

   console.log(myThing);
}
```

So that kind of ends this simple setup.
It's incredible how little help you're able to find online regarding all of this, so hopefully this will help myself in the future, and maybe some lost soul will stumble upon it as well.
There's loads of other features that can be used, but I won't get into that right now.
You can find more examples on Jake Archibald's library readme:
https://github.com/jakearchibald/idb