用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/diegosouzapw/awesome-omni-skill --skill api-extend命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | api-extend |
| description | API拡張ワークフロー(ports → provider → handler → Mock → テスト → フロント型 → UI)を自動化 |
| version | 1.0.0 |
| tools | ["Read","Write","Edit","Grep","Glob","Bash"] |
| skill_type | workflow |
| auto_invoke | false |
新しいAPIフィールドやエンドポイントを追加する際の定型フローを自動化します。DDD(ドメイン駆動設計)とクリーンアーキテクチャの原則に従い、以下の8ステップを実行します:
スキル呼び出し時に以下の情報を提供してください:
/api-extend
追加内容:
- データクラス名: <DataClass名>(例: TrainingData)
- フィールド:
- <field_name>: <type> - <説明>
- <field_name>: <type> - <説明>
- エンドポイント(新規の場合): GET /path/{param}
- 既存エンドポイントへの追加(の場合): <エンドポイント名>
ファイル: main/backend/src/domain/ports/race_data_provider.py
パターン:
@dataclass(frozen=True)
class <DataClass>:
"""<説明>."""
field_name: type
field_name: type | None = None # オプショナルフィールド
class RaceDataProvider(ABC):
@abstractmethod
def get_<method_name>(self, <params>) -> <ReturnType>:
"""<説明>."""
pass
重要な規則:
@dataclass(frozen=True) でイミュータブルpass を記述str | None 形式)ファイル: main/backend/src/infrastructure/providers/jravan_race_data_provider.py
パターン:
def get_<method_name>(self, <params>) -> <ReturnType>:
"""<説明>."""
try:
response = self._session.get(
f"{self._base_url}/<endpoint>",
params={"param": value} if needs_params else {},
timeout=self._timeout,
)
if response.status_code == 404:
return None # または []
response.raise_for_status()
# リストの場合
data = response.json()
return [self._to_<data_class>(d) for d in data]
# 単一オブジェクトの場合
return self._to_<data_class>(response.json())
except requests.RequestException as e:
logger.warning(f"Could not get <resource>: {e}")
return None # または []
def _to_<data_class>(self, data: dict) -> <DataClass>:
"""API レスポンスを <DataClass> に変換する."""
return <DataClass>(
field_name=data["field_name"],
optional_field=data.get("optional_field"),
)
重要な規則:
None または空リスト [] を返す_to_<data_class> 変換メソッドを実装data.get("key") でオプショナルフィールドを取得ファイル: main/backend/src/infrastructure/providers/mock_race_data_provider.py
パターン:
def get_<method_name>(self, <params>) -> <ReturnType>:
"""<説明>."""
import random
random.seed(_stable_hash(str(<unique_key>)) % (2**32))
# データを生成
results = []
for i in range(<count>):
data = <DataClass>(
field_name=random.choice(self.SAMPLE_DATA),
numeric_field=random.randint(min, max),
optional_field=random.choice([...]) if needed else None,
)
results.append(data)
return results
重要な規則:
_stable_hash() でシード固定(再現可能なデータ生成)SAMPLE_DATA を定義ファイル: main/backend/src/api/handlers/races.py
レスポンス構築パターン:
def get_<endpoint>(event: dict, context: Any) -> dict:
"""<説明>.
GET /<path>?param=value
Query/Path Parameters:
param: 説明
Returns:
レスポンス説明
"""
# パラメータ取得
param = get_query_parameter(event, "param")
# または
param = get_path_parameter(event, "param")
if not param:
return bad_request_response("param is required")
# ユースケース実行
provider = Dependencies.get_race_data_provider()
result = provider.get_<method>(param)
if result is None:
return not_found_response("<Resource>")
# レスポンス構築
response_data = [
{
"field_name": item.field_name,
"optional_field": item.optional_field,
}
for item in result
]
return success_response({"data": response_data})
重要な規則:
bad_request_response(), not_found_response() を使用ファイル: main/backend/tests/ 配下の適切な場所
テストパターン:
def test_get_<method_name>():
"""<説明>."""
# Arrange
provider = MockRaceDataProvider()
# Act
result = provider.get_<method_name>(<params>)
# Assert
assert result is not None
assert len(result) > 0
assert result[0].field_name == expected_value
重要な規則:
ファイル: main/frontend/src/types/index.ts
パターン:
// API形式(バックエンドレスポンス)
export interface Api<DataClass> {
field_name: string;
optional_field?: number;
}
// フロントエンド表示用
export interface <DataClass> {
fieldName: string;
optionalField?: number;
}
// 変換関数
export function mapApi<DataClass>To<DataClass>(api: Api<DataClass>): <DataClass> {
return {
fieldName: api.field_name,
optionalField: api.optional_field,
};
}
重要な規則:
Api<Name> プレフィックス(snake_case)ファイル: main/frontend/src/api/client.ts
パターン:
async get<Resource>(<params>): Promise<ApiResponse<<DataClass>>> {
const response = await this.request<Api<DataClass>Response>(
`/endpoint/${encodeURIComponent(param)}`
);
if (!response.success || !response.data) {
return { success: false, error: response.error };
}
return {
success: true,
data: mapApi<DataClass>To<DataClass>(response.data),
};
}
重要な規則:
encodeURIComponent() でエンコード対象ファイル: main/frontend/src/pages/*Page.tsx, main/frontend/src/components/*
提供内容:
以下の形式で進捗を報告:
✅ ステップ1: ports定義完了
- <DataClass>を追加
- get_<method>メソッドを追加
✅ ステップ2: JRA-VAN Provider実装完了
- get_<method>を実装
- _to_<data_class>変換メソッドを実装
✅ ステップ3: Mock Provider実装完了
- サンプルデータ生成ロジックを実装
✅ ステップ4: API Handler実装完了
- GET /<endpoint> エンドポイントを実装
✅ ステップ5: テスト作成完了
- test_get_<method> を追加
✅ ステップ6: フロントエンド型定義完了
- Api<DataClass>, <DataClass> 型を追加
- マッピング関数を追加
✅ ステップ7: APIクライアント更新完了
- get<Resource>メソッドを追加
⏳ ステップ8: UI実装ガイダンス
- 更新対象: <component_path>
- 表示例コードを提供
次のアクション:
- [ ] テスト実行(pytest)
- [ ] フロントエンドビルド確認(npm run build)
- [ ] デプロイ前チェック(./scripts/pre-deploy-check.sh)
ImportError: frozen dataclassのimport漏れ
from dataclasses import dataclass を確認型エラー: Optional型の扱い
str | None 形式を使用(Optional[str] は使わない)Mock更新漏れ
フロントエンド型不整合
npm run typecheck で確認/api-extend
追加内容:
- データクラス名: PedigreeData
- フィールド:
- horse_id: str - 馬ID
- horse_name: str | None - 馬名
- sire_name: str | None - 父馬名
- dam_name: str | None - 母馬名
- broodmare_sire: str | None - 母父馬名
- エンドポイント: GET /horses/{horse_id}/pedigree
/api-extend
追加内容:
- データクラス名: WeightData
- フィールド:
- weight: int - 馬体重(kg)
- weight_diff: int - 前走比増減
- 既存エンドポイントへの追加: GET /races/{race_id} のrunnersに追加
実装時は以下のファイルを参照:
main/backend/src/domain/ports/race_data_provider.pymain/backend/src/infrastructure/providers/jravan_race_data_provider.pymain/backend/src/infrastructure/providers/mock_race_data_provider.pymain/backend/src/api/handlers/races.pymain/frontend/src/types/index.tsmain/frontend/src/api/client.tsfrozen=Truenpm run typecheck で確認