---
title: "自作プラグイン"
description: "Storage と Transformer の自作方法と実装時の注意点を説明します。"
---

## インターフェースの全体像 [#overview]

プラグインは `@unikvs/core` の型に従って作ります。ストレージは保存先、トランスフォーマーは透過的な変換を担当します。

1. **ストレージは IStorage を実装する**

    `write`・`read`・`exists`・`delete`・`clear` を実装します。

2. **トランスフォーマーは ITransformer を実装する**

    エンコードとデコードの対応を実装します。

3. **必要に応じてストリーム対応を追加する**

    必要なら入出力別のストリーム用インターフェースを追加します。

4. **エラーは ErrorBase を継承する**

    説明・原因・解決方法を含むメッセージを定義します。

詳細なシグネチャーは `@unikvs/core` を参照してください。

## ストレージの実装 [#storage]

1. `write`・`read`・`exists`・`delete`・`clear` を正確に実装します。
2. 存在しないキーの `read`・`delete` ではキー未検出エラーを投げます。
3. 必要なら `open`・`close`・`isOpen` を実装します。不要なら常時オープン扱いにできます。メモリーは常時オープンの例です。
4. ストリーム保存が必要なら書き込み用と読み込み用の取得処理を追加し、バイト列以外を受け取った場合の扱いを決めます。
5. ファイル名やキーに制約がある場合は、`@unikvs/utils` の検証関数を再利用します。

```ts
import type { IStorage } from "@unikvs/core";

export default class MyStorage implements IStorage {
  public readonly name = "MyStorage";

  public get isOpen(): boolean {
    return true;
  }

  public write(args: Pick<IStorage.WriteArgs<any>, "key" | "data">): void {
    // 保存処理を実装します
  }

  public read(args: Pick<IStorage.ReadArgs, "key">): unknown {
    // 取得処理を実装します
  }

  public exists(args: Pick<IStorage.ExistsArgs, "key">): boolean {
    // 存在確認を実装します
    return false;
  }

  public delete(args: Pick<IStorage.DeleteArgs, "key">): void {
    // 削除処理を実装します
  }

  public clear(): void {
    // 全削除処理を実装します
  }
}
```

上記は構造の例です。引数と戻り値の詳細はコアの型定義に従ってください。

**プラグインの足場の例**

- my-plugin/
  - src/
    - index.ts
    - my-storage.ts
    - errors.ts
  - package.json
  - tsconfig.json

:::tip
キーやファイル名に制約がある場合は、`@unikvs/utils` の検証関数を使うとファイル系ストレージと一貫したメッセージになります。
:::

## トランスフォーマーの実装 [#transformer]

1. エンコードとデコードの対応を明確にし、往復で元に戻ることを単体テストで確認します。
2. ストリーム変換の対応可否を明確にし、未対応なら対応するエラーを投げます。
3. 追加情報が必要なら実行時変数で受け取ります。チェックサムのハッシュ指定がその例です。
4. 必要なら `open`・`close` を実装します。

## エラー定義 [#errors]

`ErrorBase` を継承し、説明・原因・解決方法を含むメッセージを定義します。i18n 対応できます。`InvalidFilenameError` やチェックサム不一致エラーが参考になります。

## テストの観点 [#testing]

- 保存して取得した値が一致することを確認します。
- 未検出キー、空データ、大容量データの境界を確認します。
- ストリーム対応がある場合は、複数チャンクの結合と中断時の挙動を確認します。
- 複数ストレージ構成での動作を確認します。
