npm package: @ooopenlab/module-sdk
Description: SDK for developing SuperQuiz modules independently
Author: OOOpen Lab
Latest version: 1.0.0

# @ooopenlab/module-sdk

獨立開發 OOOPEN Lab 模組的官方 SDK。此 SDK 讓開發者可以創建測驗模組，而不需要存取整個 OOOPEN Lab 程式碼庫。

## 🚀 快速開始

```bash
# 使用 CLI 工具建立新模組
npx @ooopenlab/create-module my-awesome-quiz

# 安裝相依套件
cd my-awesome-quiz
npm install

# 開始開發
npm run dev
```

## 📦 安裝

```bash
npm install @ooopenlab/module-sdk
```

## 🎯 核心概念

### 模組開發者的兩大任務

開發 OOOPEN Lab 模組時，您只需要專注於兩個核心任務：

1. **欄位配置** - 定義測驗編輯器中顯示的表單欄位
2. **UI 元件** - 創建封面、問題和結果的 React 元件

其他一切（路由、資料儲存、整合）都由 SDK 自動處理。

## 📖 基本用法

### 1. 建立您的模組類別

```typescript
import { BaseModule, ModuleFieldConfig, ModuleComponents } from '@ooopenlab/module-sdk';
import { CoverComponent } from './components/CoverComponent';
import { QuestionComponent } from './components/QuestionComponent';
import { ResultComponent } from './components/ResultComponent';

export class MyQuizModule extends BaseModule {
  public readonly manifest = require('../package.json');
  
  public getFieldConfig(): ModuleFieldConfig {
    return {
      cover: [
        {
          key: 'title',
          type: 'text',
          label: 'modules.myquiz.cover.title.label',
          required: true
        }
      ],
      question: [
        {
          key: 'questionText',
          type: 'text',
          label: 'modules.myquiz.question.text.label',
          required: true
        }
      ],
      result: [
        {
          key: 'resultTitle',
          type: 'text',
          label: 'modules.myquiz.result.title.label',
          required: true
        }
      ]
    };
  }
  
  public getComponents(): ModuleComponents {
    return {
      CoverComponent,
      QuestionComponent,
      ResultComponent
    };
  }
}
```

### 2. 建立您的 React 元件

```typescript
// components/QuestionComponent.tsx
import React from 'react';
import { QuestionProps } from '@ooopenlab/module-sdk';

export const QuestionComponent: React.FC<QuestionProps> = ({
  data,
  onAnswer,
  t
}) => {
  const handleOptionClick = (option: string) => {
    onAnswer({ selectedOption: option });
  };

  return (
    <div>
      <h2>{data.questionText}</h2>
      <div>
        {data.options?.map((option: string, index: number) => (
          <button 
            key={index}
            onClick={() => handleOptionClick(option)}
          >
            {option}
          </button>
        ))}
      </div>
    </div>
  );
};
```

## 🛠️ API 參考

### BaseModule

所有模組必須繼承的抽象基底類別。

#### 抽象方法

- `getFieldConfig(): ModuleFieldConfig` - 定義測驗編輯器的表單欄位
- `getComponents(): ModuleComponents` - 定義測驗畫面的 React 元件

#### 提供的方法

- `toOOOPEN LabConfig(): OOOPEN LabModuleConfig` - 轉換為平台相容格式
- `validate(): ValidationResult` - 驗證模組完整性
- `getI18nKeys(): string[]` - 取得所有翻譯鍵值
- `getCompatibilityInfo()` - 取得相容性資訊

### 欄位類型

表單配置可用的欄位類型：

- `text` - 單行文字輸入
- `textarea` - 多行文字輸入
- `image` - 圖片上傳
- `color` - 顏色選擇器
- `select` - 下拉選單/多選
- `number` - 數字輸入
- `boolean` - 核取方塊
- `richtext` - 富文本編輯器
- `slider` - 範圍滑桿
- `tags` - 標籤輸入
- `file` - 檔案上傳
- `datetime` - 日期時間選擇器

### 元件屬性

#### CoverProps
- `data` - 表單資料物件
- `onStart` - 開始測驗的函數
- `t` - 翻譯函數
- `locale` - 目前語系

#### QuestionProps
- `data` - 表單資料物件
- `questionIndex` - 目前問題索引（從 0 開始）
- `totalQuestions` - 總問題數
- `onAnswer` - 提交答案的函數
- `onNext` - 前往下一題的函數
- `onPrevious` - 返回上一題的函數
- `t` - 翻譯函數
- `locale` - 目前語系

#### ResultProps
- `data` - 表單資料物件
- `answers` - 使用者答案陣列
- `score` - 計算分數（如適用）
- `factors` - 因子分數（如適用）
- `onRestart` - 重新開始測驗的函數
- `onShare` - 分享結果的函數
- `t` - 翻譯函數
- `locale` - 目前語系

## 🌍 國際化

SDK 提供完整的 i18n 支援。在欄位定義中使用翻譯鍵值：

```typescript
{
  key: 'title',
  type: 'text',
  label: 'modules.myquiz.cover.title.label',
  ui: {
    placeholder: 'modules.myquiz.cover.title.placeholder',
    helpText: 'modules.myquiz.cover.title.help'
  }
}
```

### 必要的翻譯結構

在模組的 `i18n/` 目錄中建立翻譯檔案：

```json
// i18n/zh.json
{
  "modules": {
    "myquiz": {
      "title": "我的測驗",
      "cover": {
        "title": {
          "label": "標題",
          "placeholder": "請輸入測驗標題"
        }
      }
    }
  }
}
```

## ✅ 驗證

SDK 提供內建的欄位和模組驗證：

```typescript
import { validateFieldDefinition, validateModuleData } from '@ooopenlab/module-sdk';

// 驗證欄位定義
const fieldResult = validateFieldDefinition(myField);
if (!fieldResult.valid) {
  console.error('欄位錯誤:', fieldResult.errors);
}

// 驗證模組資料
const dataResult = validateModuleData(formData, fieldDefinitions);
if (!dataResult.valid) {
  console.error('資料錯誤:', dataResult.errors);
}
```

## 🔧 開發工具

### CLI 指令

```bash
# 建置模組
npm run build

# 開發模式（監看檔案變更）
npm run dev

# 執行測試
npm test

# 程式碼檢查
npm run lint

# 修復程式碼檢查問題
npm run lint:fix
```

### 測試

SDK 包含 Jest 設定以測試您的模組：

```typescript
// __tests__/MyQuizModule.test.ts
import { MyQuizModule } from '../src/MyQuizModule';

describe('MyQuizModule', () => {
  const module = new MyQuizModule();
  
  it('應該成功驗證', () => {
    const result = module.validate();
    expect(result.valid).toBe(true);
  });
  
  it('應該具有必要元件', () => {
    const components = module.getComponents();
    expect(components.CoverComponent).toBeDefined();
    expect(components.QuestionComponent).toBeDefined();
    expect(components.ResultComponent).toBeDefined();
  });
});
```

## 📚 範例

### 完整模組範例

請參閱 [範例模組](./examples/) 目錄中的完整可運作範例：

- **經典測驗** - 基於因子的性格測試
- **問卷模組** - 簡單問卷調查
- **計分測驗** - 數值計分系統

### 欄位配置範例

```typescript
// 具驗證的圖片欄位
{
  key: 'backgroundImage',
  type: 'image',
  label: 'modules.myquiz.cover.background.label',
  ui: {
    accept: 'image/*',
    helpText: 'modules.myquiz.cover.background.help'
  }
}

// 具選項的下拉欄位
{
  key: 'difficulty',
  type: 'select',
  label: 'modules.myquiz.question.difficulty.label',
  required: true,
  ui: {
    options: [
      { label: '簡單', value: 'easy' },
      { label: '中等', value: 'medium' },
      { label: '困難', value: 'hard' }
    ]
  }
}

// 具驗證的數字欄位
{
  key: 'timeLimit',
  type: 'number',
  label: 'modules.myquiz.question.timeLimit.label',
  validation: {
    min: 10,
    max: 300,
    message: '時間限制必須介於 10 到 300 秒之間'
  }
}
```

## 🚀 發布您的模組

模組完成後，發布到 npm：

```bash
# 建置模組
npm run build

# 發布到 npm
npm publish --access public
```

您的模組將以 `@ooopenlab-modules/your-module-name` 的名稱提供使用。

## 🔗 與 OOOPEN Lab 整合

使用此 SDK 建置的模組會自動與 OOOPEN Lab 平台整合：

1. **欄位配置** → 測驗編輯器表單欄位
2. **元件** → 測驗執行時期渲染
3. **驗證** → 表單和資料驗證
4. **國際化** → 多語言支援
5. **路由** → 三畫面測驗流程（封面 → 問題 → 結果）

## 📄 授權條款

MIT

## 🤝 貢獻

歡迎貢獻！請閱讀我們的 [貢獻指南](../../CONTRIBUTING.md) 瞭解詳情。

## 📞 支援

- [說明文件](https://github.com/relabcc/superquiz-open-lab/tree/main/docs)
- [問題回報](https://github.com/relabcc/superquiz-open-lab/issues)
- [討論區](https://github.com/relabcc/superquiz-open-lab/discussions)