---
title: "@unikvs/indexeddb"
description: "Learn how to use the storage plugin that saves arbitrary data to the browser's IndexedDB."
---

## Overview [#overview]

Browser only

`@unikvs/indexeddb` is a storage plugin that uses the browser's IndexedDB as its persistence layer. It stores arbitrary data keyed by name.

It uses the `idb` package (`8.0.3`) internally and implements `IStorage` from `@unikvs/core`.

Install it as follows.

```package-install
npm install @unikvs/indexeddb
```

## Usage [#usage]

The storage class is `Indexeddb`, provided as a default export. Its `name` is `"Indexeddb"`.

```ts
import Indexeddb from "@unikvs/indexeddb";
```

Both constructor arguments are optional.

| Argument | Type | Default | Description |
| ---- | -- | ------ | ---- |
| `dbName` | `string` | `"unikvs_db"` | The database name. |
| `storeName` | `string` | `"kvs_store"` | The object store name. |
| `options` | `IndexeddbOptions` | `{}` | Additional behavior options. |
| `options.allowRepair` | `boolean` | `false` | Whether to allow repair writes. When `false`, `write` and `getWritable` with a repair marker throw an error. |

```ts
import Indexeddb from "@unikvs/indexeddb";

// Using the defaults (unikvs_db / kvs_store)
const storage = new Indexeddb();

// Specifying names
const customStorage = new Indexeddb("my-app-db", "my-store");
```

Call `open()` before use. It connects with version `1` and creates the store when missing. It does nothing when already open. Check with `isOpen` and close with `close()`.

Registering with `UniKvs` looks like this.

```ts
import Indexeddb from "@unikvs/indexeddb";
import { UniKvs } from "unikvs";

const kvs = UniKvs.config()
  .appendStorage(new Indexeddb())
  .create();

await kvs.open();
await kvs.set("greeting", "hello");
const value = await kvs.get("greeting");
await kvs.close();
```

## Data Format [#data]

`write` accepts `any`, and `read` returns `any`. Values are forwarded to `idb`'s `put`/`get` as is, so non-byte values can be stored too.

Streams are also supported, but IndexedDB has no native streaming, so they are emulated in memory.

- `getWritable` buffers chunks in memory and concatenates them into a single `Uint8Array` on close.
- `getReadable` loads the whole value into memory, then emits it as a single chunk before closing.

:::warning
`getWritable` and `getReadable` hold the whole value in memory. Watch usage with large data.
:::

Existence checks use `count()`, deletion uses `delete()`, and full clearing uses `clear()`.

## Notes [#notes]

- All methods are async. Don't call `write`, `read`, `exists`, `delete`, or `clear` before `open()` completes. The connection is `null` until then.
- `read` throws a `DOMException` (`NotFoundError`) for a missing key. This matches the Opfs plugin. Check beforehand with `exists()`.
- The database version is fixed at `1`, and the store is auto-created when missing. No migration logic is included.
- Browser only. It uses IndexedDB, `DOMException`, `WritableStream`, and `ReadableStream`.
- Capacity and quota depend on the browser. Data may not persist in private mode.

## Examples [#examples]

1. **Open**

    Create with defaults and connect with `open()`.

    ```ts
    import Indexeddb from "@unikvs/indexeddb";

    const storage = new Indexeddb();

    await storage.open();
    ```

2. **Write**

    ```ts
    await storage.write({ key: "greeting", data: "hello" });
    ```

3. **Read**

    ```ts
    if (await storage.exists({ key: "greeting" })) {
      const value = await storage.read({ key: "greeting" });
      console.log(value);
    }
    ```

4. **Delete and close**

    ```ts
    await storage.delete({ key: "greeting" });
    await storage.close();
    ```
