---
title: "@unikvs/indexeddb"
description: "ブラウザーの IndexedDB に任意のデータを保存するストレージプラグインの使い方を説明します。"
---

## 概要 [#overview]

ブラウザー専用

`@unikvs/indexeddb` は、ブラウザーの IndexedDB に保存するストレージプラグインです。任意のデータをキーとひも付けて保存できます。

内部操作には `idb` パッケージ（`8.0.3`）を使い、`@unikvs/core` の `IStorage` を実装しています。

インストールは次のとおりです。

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

## 使い方 [#usage]

クラス名は `Indexeddb` で、デフォルトエクスポートです。`name` は `"Indexeddb"` です。

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

コンストラクターの引数はどちらも省略できます。

| 引数 | 型 | 既定値 | 説明 |
| ---- | -- | ------ | ---- |
| `dbName` | `string` | `"unikvs_db"` | データベース名です。 |
| `storeName` | `string` | `"kvs_store"` | オブジェクトストア名です。 |
| `options` | `IndexeddbOptions` | `{}` | 追加の動作を指定します。 |
| `options.allowRepair` | `boolean` | `false` | 書き戻しによる書き込みを許可するかどうかです。`false` の場合、書き戻しの `write`・`getWritable` はエラーを投げます。 |

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

// 既定値（unikvs_db / kvs_store）を使う場合
const storage = new Indexeddb();

// 名前を指定する場合
const customStorage = new Indexeddb("my-app-db", "my-store");
```

使う前に `open()` を呼びます。バージョン `1` で接続し、ストアがなければ作ります。オープン済みなら何もしません。`isOpen` で確認し、`close()` で閉じます。

`UniKvs` に登録する例は次のとおりです。

```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]

`write` は `any` を受け付け、`read` は `any` を返します。値はそのまま `idb` の `put`・`get` に渡すため、バイト列以外も保存できます。

ストリームにも対応していますが、IndexedDB にネイティブ機能はないためメモリー上でエミュレートします。

- `getWritable` はチャンクをメモリーにため、クローズ時に結合して 1 つの `Uint8Array` として保存します。`signal` を中断するとバッファーを破棄し、以降の操作は中断理由で失敗します。
- `getReadable` は全体をメモリーに読み込んでから、単一チャンクとして送出してクローズします。`signal` を中断すると読み取りは中断理由で失敗します。

:::warning
`getWritable`・`getReadable` は全体をメモリーに保持します。大きなデータでは使用量に注意してください。
:::

存在確認は `count()`、削除は `delete()`、全消去は `clear()` を使います。

## 注意点 [#notes]

- すべて非同期です。`open()` 完了前に `write`・`read`・`exists`・`delete`・`clear` を呼ばないでください。接続は完了まで `null` です。
- すべてのメソッドは `signal` を受け取ります。IndexedDB にネイティブの中断機能はないため、各操作は待機の区切りで `signal` を確認し、中断されていればその中断理由で失敗します。`open` が中断された場合は未オープンのままです。
- `read` はキーがないと `DOMException`（`NotFoundError`）を投げます。Opfs に合わせた挙動です。事前に `exists()` で確認できます。
- データベースバージョンは `1` 固定で、ストアは不足時に自動作成します。既存構造の変更処理は含みません。
- IndexedDB・`DOMException`・`WritableStream`・`ReadableStream` を使うブラウザー専用です。
- 容量やクォータはブラウザー依存です。プライベートモードなどでは永続化されない場合があります。

## 使用例 [#examples]

1. **開く**

    既定値で作り、`open()` で接続します。

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

    const storage = new Indexeddb();

    await storage.open();
    ```

2. **書き込む**

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

3. **読み取る**

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

4. **削除して閉じる**

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