npm package: @kiyakuto/js
Description: Kiyakuto consent management JS SDK
Latest version: 0.1.0

# @kiyakuto/js

利用規約への同意管理を Web サイトに組み込むための JavaScript SDK です。
ダイアログ形式で利用規約を表示し、ユーザーの同意を取得できます。

## インストール

### IIFE（script タグ）

ビルド済みの `widget.js` を `<script>` タグで読み込みます。
グローバル変数 `Kiyakuto` が公開されます。

```html
<script src="https://cdn.example.com/kiyakuto/widget.js"></script>
<script>
  Kiyakuto.init({
    projectId: "your-project-id",
    userId: "current-user-id",
    publicKey: "your-public-key",
  });
</script>
```

### ESM（npm パッケージ）

```bash
npm install @kiyakuto/js
```

```typescript
import { init, show } from "@kiyakuto/js";
```

> **注意**: ESM ビルドでは `react` と `react-dom` が peerDependencies です。
> ホストアプリケーション側で React 18 または 19 をインストールしてください。

## 基本的な使い方

### 1. 初期化

`init()` で SDK を初期化します。`show()` を呼び出す前に必ず実行してください。

```typescript
Kiyakuto.init({
  projectId: "your-project-id",   // プロジェクト ID（必須）
  userId: "current-user-id",      // ユーザー ID（必須）
  publicKey: "your-public-key",   // パブリックキー（必須）
  skipConsented: true,             // true の場合、既に同意済みの規約はダイアログに表示されない（省略時: true）
});
```

### 2. 同意ダイアログの表示

`show()` を呼び出すと同意ダイアログが表示されます。
ユーザーが操作を完了すると `ConsentResult` で解決される Promise を返します。

```typescript
const result = await Kiyakuto.show();

if (result.success) {
  // ユーザーが全ての規約に同意した
  console.log("同意完了", result.agreements);
} else if (result.error) {
  // エラーが発生した
  console.error(result.error.message);
} else {
  // ユーザーがダイアログを閉じた（同意せずキャンセル）
  console.log("キャンセル");
}
```

## `show()` の多重呼び出し時の振る舞い

`show()` を連続して呼び出した場合、**最後の呼び出しのみが有効**になります。

前回の `show()` が返した Promise がまだ未解決の状態で新たに `show()` を呼び出すと、前回の Promise は以下の結果で自動的に resolve されます。

```typescript
{
  success: false,
  agreements: [],
  error: new Error("[Kiyakuto] Superseded by a new show() call")
}
```

### 具体例

```typescript
// 1回目の呼び出し
const firstPromise = Kiyakuto.show();

// 2回目の呼び出し（1回目はまだ未解決）
const secondPromise = Kiyakuto.show();

// 1回目は即座に resolve される
const firstResult = await firstPromise;
console.log(firstResult.success);        // false
console.log(firstResult.agreements);     // []
console.log(firstResult.error?.message); // "[Kiyakuto] Superseded by a new show() call"

// 2回目のみがアクティブなダイアログとして動作する
const secondResult = await secondPromise;
```

### 判定方法

前回の呼び出しがキャンセルされたかどうかは、`error` プロパティの有無で判定できます。

```typescript
const result = await Kiyakuto.show();
if (!result.success && result.error) {
  // 新しい show() 呼び出しによってキャンセルされた
  // または他のエラーが発生した
}
```

## ConsentResult

`show()` が返す Promise の解決値です。

```typescript
interface ConsentResult {
  /** 同意が正常に完了したかどうか */
  success: boolean;
  /** 同意対象の規約一覧 */
  agreements: Agreement[];
  /** エラー情報（エラー時のみ） */
  error?: Error;
}
```

| パターン | `success` | `agreements` | `error` |
|---|---|---|---|
| 全規約に同意完了 | `true` | 同意した規約の配列 | `undefined` |
| ユーザーがキャンセル | `false` | `[]` | `undefined` |
| 多重呼び出しによるキャンセル | `false` | `[]` | `Error` (`"[Kiyakuto] Superseded by a new show() call"`) |

### Agreement

```typescript
interface Agreement {
  id: string;
  title: string;
  currentVersion: AgreementVersion;
  consented?: boolean;
  createdAt: string;
  updatedAt: string;
}

interface AgreementVersion {
  id: string;
  label: string;
  content: string;
  publishedAt: string;
}
```