diff --git a/docs/ja-JP/agents/opensource-sanitizer.md b/docs/ja-JP/agents/opensource-sanitizer.md index c081e5ef..949b9e7f 100644 --- a/docs/ja-JP/agents/opensource-sanitizer.md +++ b/docs/ja-JP/agents/opensource-sanitizer.md @@ -158,7 +158,7 @@ git log -p | grep -iE '(password|secret|api.?key|token)' | head -20 | 設定の完全性 | PASS/WARN | {count}件の所見 | | git履歴 | PASS/FAIL | {count}件の所見 | -## Critical所見(リリース前に修正必須) +## 重大な所見(リリース前に修正必須) 1. **[SECRETS]** `src/config.py:42` — ハードコードされたデータベースパスワード: `DB_P...`(切り捨て) 2. **[INTERNAL]** `docker-compose.yml:15` — 内部ドメインを参照 @@ -174,9 +174,9 @@ git log -p | grep -iE '(password|secret|api.?key|token)' | head -20 ## 推奨事項 -{FAILの場合: "{N}件のCritical所見を修正してサニタイザーを再実行してください。"} +{FAILの場合: "{N}件の重大な所見を修正してサニタイザーを再実行してください。"} {PASSの場合: "プロジェクトはオープンソースリリースの準備完了。パッケージャーに進んでください。"} -{WARNINGSの場合: "プロジェクトはCriticalチェックに合格。リリース前に{N}件の警告をレビューしてください。"} +{WARNINGSの場合: "プロジェクトは重大チェックに合格。リリース前に{N}件の警告をレビューしてください。"} ``` ## 例 diff --git a/docs/ja-JP/commands/rules-distill.md b/docs/ja-JP/commands/rules-distill.md index f09d092d..41588933 100644 --- a/docs/ja-JP/commands/rules-distill.md +++ b/docs/ja-JP/commands/rules-distill.md @@ -1,10 +1,10 @@ --- -description: "スキルをスキャンして横断的な原則を抽出し、ルールとして提炼する" +description: "スキルをスキャンして横断的な原則を抽出し、ルールとして蒸留する" --- -# /rules-distill — スキルから原則をルールとして提炼する +# /rules-distill — スキルから原則をルールとして蒸留する -インストール済みのスキルをスキャンし、横断的な原則を抽出して、ルールとして提炼します。 +インストール済みのスキルをスキャンし、横断的な原則を抽出して、ルールとして蒸留します。 ## フロー diff --git a/docs/ja-JP/skills/skill-scout/SKILL.md b/docs/ja-JP/skills/skill-scout/SKILL.md new file mode 100644 index 00000000..e0496ea9 --- /dev/null +++ b/docs/ja-JP/skills/skill-scout/SKILL.md @@ -0,0 +1,131 @@ +--- +name: skill-scout +description: Search existing local, marketplace, GitHub, and web skill sources before creating a new skill. Use when the user wants to create, build, fork, or find a skill for a workflow. +origin: community +--- + +# スキルスカウト + +新しいスキルを作成する前にこのスキルを使用してください。目的は、既存のコミュニティやマーケットプレイスの成果を重複して作成することを避けながら、外部のものを採用する前にきちんと審査することです。 + +出典: `redminwang` によるコミュニティの古いPR #1232 から再利用。 + +## 使用するタイミング + +- ユーザーが「スキルを作成する」「スキルをビルドする」「スキルを作る」「新しいスキル」と言ったとき。 +- ユーザーが「Xのスキルはありますか?」または「Yを実行するスキルは存在しますか?」と尋ねたとき。 +- ユーザーがワークフローを説明し、新しいスキルの作成を提案しようとしているとき。 +- ユーザーが既存のスキルをフォークまたは拡張したいとき。 + +ユーザーが検索をスキップして最初から作成するよう明示的に指示した場合は、それを確認してリクエストされた作成ワークフローを進めてください。 + +## 動作の仕組み + +### ステップ1 - 意図の把握 + +以下を抽出します: + +- スキルが実行すべきタスク。 +- スキルを使用するためのトリガー条件。 +- 関連するドメイン、ツール、フレームワーク、またはデータソース。 +- 3〜5個の検索キーワードと有用な同義語。 + +### ステップ2 - ローカルソースを検索する + +まずインストール済みおよびマーケットプレイスのスキル名を検索します。ローカルソースはすでにユーザーの環境に含まれているため優先されます。 + +```bash +find ~/.claude/skills -maxdepth 2 -name SKILL.md 2>/dev/null | grep -iE "keyword|synonym" +find ~/.claude/plugins/marketplaces -path '*/skills/*/SKILL.md' 2>/dev/null | grep -iE "keyword|synonym" +``` + +次にフロントマターの説明を検索します: + +```bash +grep -RilE "keyword|synonym" ~/.claude/skills ~/.claude/plugins/marketplaces 2>/dev/null +``` + +### ステップ3 - リモートソースを検索する + +利用可能なGitHubおよびWebの検索ツールを使用します。簡潔なクエリを優先します: + +```bash +gh search repos "claude code skill keyword" --limit 10 --sort stars +gh search code "name: keyword" --filename SKILL.md --limit 10 +``` + +Web検索では、最大3つのターゲットクエリを使用します(例): + +```text +"claude code skill" keyword +"SKILL.md" keyword +"everything-claude-code" keyword +``` + +### ステップ4 - 外部マッチを審査する + +採用またはフォークのために外部スキルを推奨する前に: + +- `SKILL.md` のフロントマターと手順を読む。 +- 予期しないシェルコマンド、ファイル書き込み、ネットワーク呼び出し、クレデンシャル処理、またはパッケージインストールがないか確認する。 +- リポジトリがメンテナンスされているかどうかを確認する。 +- マーケットプレイスのオリジナルを直接編集するのではなく、新しいローカルブランチにコピーしてdiffを確認することを優先する。 + +### ステップ5 - 結果をランク付けする + +候補を以下の順でランク付けします: + +1. スキル名での完全なキーワードマッチ。 +2. 説明でのキーワードまたは同義語マッチ。 +3. ローカルにインストール済みまたはマーケットプレイスのソース。 +4. 最近のアクティビティがあるメンテナンス済みのGitHubソース。 +5. Web上の言及のみ。 + +最終リストは10件に制限します。 + +### ステップ6 - 判断オプションを提示する + +ユーザーに短いテーブルを提示します: + +| オプション | 意味 | +| --- | --- | +| 既存を使用 | マッチするスキルをそのまま呼び出すかインストールする。 | +| フォークまたは拡張 | 最も近いスキルをコピーして修正する。 | +| 新規作成 | 近いマッチが存在しないことを確認した後、新しいスキルをビルドする。 | + +ユーザーがそのパスを選択した後、または検索で近いマッチが見つからなかった場合にのみ、新しいスキルを作成します。 + +## 例 + +### 結果テーブル + +```markdown +| # | スキル | ソース | マッチする理由 | ギャップ | +| --- | --- | --- | --- | --- | +| 1 | article-writing | ローカル ECC | 記事とガイドの草稿作成 | リリースノートに特化していない | +| 2 | content-engine | ローカル ECC | マルチフォーマットコンテンツワークフロー | 必要以上に重い | +| 3 | blog-writer | GitHub | 最近のコミットがあるブログ執筆スキル | セキュリティレビューが必要 | +``` + +### ユーザー向けサマリー + +```markdown +2つの近いローカルマッチと1つの外部候補が見つかりました。最も近いのは +`article-writing` です。草稿作成と修正をカバーしていますが、 +お求めのリリースノートチェックリストは含まれていません。そのまま使用するか、 +リリースノートバリアントにフォークするか、新しいスキルを作成するかを選択できます。 +``` + +## アンチパターン + +- 検索が適切な場合に、新しいスキルの作成に直接飛びつかないこと。 +- 読まずに外部スキルをインストールしないこと。 +- 弱いマッチの長いランク付けされていないリストを提示しないこと。 +- Web上の言及のみを信頼できるソースとして扱わないこと。 +- インストール済みのマーケットプレイスオリジナルをその場で編集しないこと。 + +## 関連 + +- `search-first` - ビルドする前に検索する一般的なワークフロー。 +- `skill-stocktake` - インストール済みスキルの健全性、重複、ギャップの監査。 +- `agent-sort` - 既存のエージェントとスキルの分類と整理。 diff --git a/docs/ja-JP/skills/swift-actor-persistence/SKILL.md b/docs/ja-JP/skills/swift-actor-persistence/SKILL.md index bc6db7b4..3f5c0afb 100644 --- a/docs/ja-JP/skills/swift-actor-persistence/SKILL.md +++ b/docs/ja-JP/skills/swift-actor-persistence/SKILL.md @@ -35,13 +35,27 @@ public actor LocalRepository where T.ID == String { // MARK: - Public API public func save(_ item: T) throws { + let previous = cache[item.id] cache[item.id] = item - try persistToFile() + do { + try persistToFile() + } catch { + // ディスク書き込み失敗時はキャッシュをロールバックして整合性を維持 + cache[item.id] = previous + throw error + } } public func delete(_ id: String) throws { + let previous = cache[id] cache[id] = nil - try persistToFile() + do { + try persistToFile() + } catch { + // ディスク書き込み失敗時はキャッシュをロールバックして整合性を維持 + cache[id] = previous + throw error + } } public func find(by id: String) -> T? { @@ -131,7 +145,7 @@ final class QuestionListViewModel { * Swiftの新しい並行処理コードでActorの代わりに `DispatchQueue` または `NSLock` を使用する * 内部のキャッシュ辞書を外部の呼び出し元に公開する -* 検証なしでファイルURLを設定可能にする +* 初期化後にファイルURLを外部から変更可能にする(初期化時のみ設定を許可すること) * すべてのActor メソッド呼び出しが `await` であることを忘れる——呼び出し元は非同期コンテキストを処理する必要がある * Actor の分離をバイパスするために `nonisolated` を使用する(本末転倒) diff --git a/docs/ja-JP/skills/tinystruct-patterns/SKILL.md b/docs/ja-JP/skills/tinystruct-patterns/SKILL.md new file mode 100644 index 00000000..8ae96c1a --- /dev/null +++ b/docs/ja-JP/skills/tinystruct-patterns/SKILL.md @@ -0,0 +1,104 @@ +--- +name: tinystruct-patterns +description: Use when developing application modules or microservices with the tinystruct Java framework. Covers routing, context management, JSON handling with Builder, and CLI/HTTP dual-mode patterns. +origin: ECC +--- + +# tinystruct 開発パターン + +**tinystruct** Java フレームワークを使用してモジュールをビルドするためのアーキテクチャと実装パターン。CLIとHTTPが等しく扱われる軽量なシステムです。 + +## 使用するタイミング + +- `AbstractApplication` を拡張して新しい `Application` モジュールを作成するとき。 +- `@Action` を使用してルートとコマンドラインアクションを定義するとき。 +- `Context` を通じてリクエストごとの状態を処理するとき。 +- ネイティブの `Builder` コンポーネントを使用してJSONシリアライゼーションを行うとき。 +- `application.properties` でデータベース接続またはシステム設定を構成するとき。 +- `ApplicationManager.init()` を通じて標準的な `bin/dispatcher` エントリポイントを生成または再生成するとき。 +- ルーティング競合(Action)またはCLI引数解析のデバッグを行うとき。 + +## 動作の仕組み + +tinystruct フレームワークは、`@Action` でアノテーションされたメソッドをターミナルとWeb環境の両方でルーティング可能なエンドポイントとして扱います。アプリケーションは `AbstractApplication` を拡張することで作成され、`init()` などのコアライフサイクルフックとリクエスト `Context` へのアクセスが提供されます。 + +ルーティングは `ActionRegistry` によって処理され、パスセグメントをメソッド引数に自動的にマッピングして依存関係を注入します。データのみのサービスでは、ゼロ依存のフットプリントを維持するために、JSONシリアライゼーションにネイティブの `Builder` コンポーネントを使用すべきです。フレームワークには `ApplicationManager` のユーティリティも含まれており、`bin/dispatcher` スクリプトを生成することでプロジェクトの実行環境をブートストラップします。 + +## 例 + +### 基本アプリケーション(MyService) +```java +public class MyService extends AbstractApplication { + @Override + public void init() { + this.setTemplateRequired(false); // データ/APIアプリの .view 参照を無効化 + } + + @Override public String version() { return "1.0.0"; } + + @Action("greet") + public String greet() { + return "Hello from tinystruct!"; + } +} +``` + +### パラメータ付きルーティング(getUser) +```java +// Web: /api/user/123 または CLI: "bin/dispatcher api/user/123" を処理 +@Action("api/user/(\\d+)") +public String getUser(int userId) { + return "User ID: " + userId; +} +``` + +### HTTPモード分岐(login) +```java +@Action(value = "login", mode = Mode.HTTP_POST) +public boolean doLogin() { + // ログイン処理 + return true; +} +``` + +### ネイティブJSONデータ処理(getData) +```java +@Action("api/data") +public Builder getData() throws ApplicationException { + Builder builder = new Builder(); + builder.put("status", "success"); + Builder nested = new Builder(); + nested.put("id", 1); + nested.put("name", "James"); + builder.put("data", nested); + return builder; +} +``` + +## 設定 + +設定は `src/main/resources/application.properties` で管理されます。 + +## テストパターン + +JUnit 5 を使用して、アクションが `ActionRegistry` に登録されていることを検証することでアクションをテストします。 + +## レッドフラグとアンチパターン + +| 症状 | 正しいパターン | +|---|---| +| `com.google.gson` または `com.fasterxml.jackson` のインポート | `org.tinystruct.data.component.Builder` を使用する。 | +| `.view` ファイルの `FileNotFoundException` | APIのみのアプリでは `init()` 内で `setTemplateRequired(false)` を呼び出す。 | +| `private` メソッドへの `@Action` アノテーション | アクションはフレームワークに登録されるために `public` である必要がある。 | +| アプリ内での `main(String[] args)` のハードコーディング | すべてのモジュールのエントリポイントとして `bin/dispatcher` を使用する。 | +| 手動での `ActionRegistry` 登録 | 自動検出のために `@Action` アノテーションを優先する。 | + +## テクニカルリファレンス + +詳細なガイドは `references/` ディレクトリにあります: + +- [アーキテクチャと設定](references/architecture.md) — 抽象化、パッケージマップ、プロパティ +- [ルーティングと@Action](references/routing.md) — アノテーションの詳細、モード、パラメータ +- [データ処理](references/data-handling.md) — JSONのためのネイティブ `Builder` の使用 +- [システムと使用方法](references/system-usage.md) — Context、セッション、イベント、CLI使用方法 +- [テストパターン](references/testing.md) — JUnit 5 統合と ActionRegistry テスト diff --git a/docs/ja-JP/skills/ui-to-vue/SKILL.md b/docs/ja-JP/skills/ui-to-vue/SKILL.md new file mode 100644 index 00000000..282aa8b5 --- /dev/null +++ b/docs/ja-JP/skills/ui-to-vue/SKILL.md @@ -0,0 +1,86 @@ +--- +name: ui-to-vue +description: Use when the user has UI screenshots or design exports that need batch conversion into Vue 3 components, especially with Vant, Element Plus, or Ant Design Vue. +origin: community +--- + +# UI To Vue + +UIデザインのスクリーンショットをVue 3 Composition APIコンポーネントコードに一括変換します。 + +## 使用するタイミング + +- ユーザーがデザインスクリーンショットまたはデザインエクスポート画像のディレクトリを提供するとき。 +- ターゲットアプリケーションがVue 3のとき。 +- ユーザーがページコンポーネント、共有コンポーネント、ルーター配線の最初の変換を希望するとき。 +- ユーザーがVant、Element Plus、またはAnt Design Vueをコンポーネントライブラリとして指定するとき。 + +## 使用しないタイミング + +- ユーザーがスクリーンショット1枚のみで、特定のコンポーネントを希望するとき。 +- ターゲットプロジェクトがVueでないとき。 +- デザインが詳細なインタラクションロジック、データフロー、またはアクセシビリティレビューを必要とするとき。 +- スクリーンショットに外部モデルAPIに送信できないプライベートな顧客データが含まれるとき。 + +## 入力 + +モジュールとページ状態でスクリーンショットをグループ化したディレクトリを入力として使用します。 + +サポートされている切り出し画像ディレクトリ名:`assets`、`icons`、`sprites`、`cut`、`images`、`cut-images`。 + +## 変換モデル + +- ページグループ化:リスト、詳細、フォーム、ローディング、または空の状態を表す関連スクリーンショットを1つのページコンポーネントにまとめる。 +- UIライブラリマッピング:可能な限りネイティブのビジュアル要素をVant、Element Plus、またはAnt Design Vueコンポーネントにマッピングする。 +- 切り出し画像の優先順位:ページレベルのアセットを優先し、次にモジュールレベル、最後にグローバル共有アセット。 +- コンポーネント抽出:繰り返し使われるUIリージョンが2回以上現れる場合は共有コンポーネントに抽出する。 + +## CLI使用方法 + +グローバルバイナリに依存せず、ドキュメントに記載されたコマンドが機能するように `npx` でコンバーターを実行します: + +```bash +export DASHSCOPE_API_KEY=your_key +npx ui-to-vue-converter@1.0.2 --input ./screenshots --ui vant --output ./src +``` + +## オプション + +| オプション | 説明 | デフォルト | +| --- | --- | --- | +| `--input` | デザイン画像ディレクトリ | `./screenshots` | +| `--ui` | UIライブラリ:`vant`、`element-plus`、または `antd-vue` | `vant` | +| `--output` | 出力ディレクトリ | `./src` | +| `--config` | 設定ファイルのパス | `./.ui-to-vue.config.json` | + +## セキュリティとプライバシー + +- デザインスクリーンショットを外部モデルAPIに送信される可能性があるソース素材として扱う。 +- 許可なくプライベートな顧客デザインでこのフローを実行しないこと。 +- 再現可能なワークフローでは `@latest` の代わりにコンバーターのバージョンを固定すること。 +- コミット前に生成されたVueコードをレビューすること。 +- `.ui-to-vue.config.json`、APIキー、生成されたシークレット、または顧客スクリーンショットをコミットしないこと。 + +## 出力レビューチェックリスト + +- [ ] ページコンポーネントが `views/` または選択した出力ディレクトリの下に生成された。 +- [ ] 繰り返しのUIリージョンが再利用が明確な場合のみ `components/` に抽出された。 +- [ ] ルーター出力がターゲットプロジェクトのルータースタイルと互換性がある。 +- [ ] 生成されたコンポーネントが要求したUIライブラリを一貫して使用している。 +- [ ] 生成されたCSSのユニットがデザインのベースラインと一致している。 +- [ ] コードがプロジェクトのフォーマッター、リンター、型チェッカー、ビルドをパスする。 +- [ ] プレースホルダーのコピー、モックデータ、生成されたアセットをコミット前にレビューした。 + +## トラブルシューティング + +| 問題 | 確認事項 | +| --- | --- | +| `401` または認証エラー | コマンドを実行するシェルで `DASHSCOPE_API_KEY` が設定されていることを確認する。 | +| `command not found: ui-to-vue` | `npx ui-to-vue-converter@1.0.2` の形式を使用するか、パッケージをグローバルインストールする。 | +| 切り出し画像が無視される | アセットディレクトリ名がサポートされており、対応するページまたはモジュールの下にネストされていることを確認する。 | +| コンポーネントが要求されたUIライブラリを無視する | 明示的な `--ui` 値で再実行して、生成されたインポートを確認する。 | +| 生成されたレイアウトの寸法がおかしい | スクリーンショットのエクスポート幅がターゲットライブラリのベースラインと一致していることを確認する。 | + +## リファレンス + +- npmパッケージ:`ui-to-vue-converter` diff --git a/docs/ja-JP/skills/videodb/reference/api-reference.md b/docs/ja-JP/skills/videodb/reference/api-reference.md index a023ce33..9d03d458 100644 --- a/docs/ja-JP/skills/videodb/reference/api-reference.md +++ b/docs/ja-JP/skills/videodb/reference/api-reference.md @@ -362,7 +362,7 @@ asset = CaptionAsset( ) ``` -完全なCaptionAssetの使用方法については、[editor.md](../../../../../skills/videodb/reference/editor.md#caption-overlays) のエディターAPIを参照。 +完全なCaptionAssetの使用方法については、[editor.md](./editor.md#caption-overlays) のエディターAPIを参照。 ## ビデオ検索パラメータ diff --git a/docs/ja-JP/skills/vite-patterns/SKILL.md b/docs/ja-JP/skills/vite-patterns/SKILL.md new file mode 100644 index 00000000..b4b72d90 --- /dev/null +++ b/docs/ja-JP/skills/vite-patterns/SKILL.md @@ -0,0 +1,449 @@ +--- +name: vite-patterns +description: Vite build tool patterns including config, plugins, HMR, env variables, proxy setup, SSR, library mode, dependency pre-bundling, and build optimization. Activate when working with vite.config.ts, Vite plugins, or Vite-based projects. +origin: ECC +--- + +# Vite パターン + +Vite 8+ プロジェクトのビルドツールおよびデベロップメントサーバーのパターン。設定、環境変数、プロキシ設定、ライブラリモード、依存関係の事前バンドル、一般的な本番環境の落とし穴をカバー。 + +## 使用するタイミング + +- `vite.config.ts` または `vite.config.js` を設定するとき +- 環境変数または `.env` ファイルを設定するとき +- APIバックエンド用のデベロップメントサーバープロキシを設定するとき +- ビルド出力(チャンク、ミニファイ、アセット)を最適化するとき +- `build.lib` でライブラリを公開するとき +- 依存関係の事前バンドルまたはCJS/ESM相互運用のトラブルシューティングをするとき +- HMR、デベロップメントサーバー、またはビルドエラーをデバッグするとき +- Viteプラグインの選択または順序付けをするとき + +## 動作の仕組み + +- **デベロップメントモード**はソースファイルをネイティブESMとして提供します(バンドルなし)。変換はモジュールリクエストごとにオンデマンドで行われるため、コールドスタートが速くHMRが精確です。 +- **ビルドモード**はRolldown(v7+)またはRollup(v5〜v6)を使用して、ツリーシェイキング、コード分割、Oxcベースのミニファイでアプリを本番用にバンドルします。 +- **依存関係の事前バンドル**はesbuildを通じてCJS/UMD依存関係をESMに一度変換し、結果を `node_modules/.vite` にキャッシュします。これにより後続の起動では処理をスキップできます。 +- **プラグイン**はデベロップメントとビルドにわたって統一されたインターフェースを共有します。同じプラグインオブジェクトが、デベロップメントサーバーのオンデマンド変換と本番パイプラインの両方で機能します。 +- **環境変数**はビルド時に静的にインライン化されます。`VITE_` プレフィックス付きの変数はバンドル内のパブリック定数になり、プレフィックスなしのものはクライアントコードから見えません。 + +## 例 + +### 設定の構造 + +#### 基本設定 + +```typescript +// vite.config.ts +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { '@': new URL('./src', import.meta.url).pathname }, + }, +}) +``` + +#### 条件付き設定 + +```typescript +// vite.config.ts +import { defineConfig, loadEnv } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig(({ command, mode }) => { + const env = loadEnv(mode, process.cwd()) // VITE_ プレフィックスのみ(安全) + + return { + plugins: [react()], + server: command === 'serve' ? { port: 3000 } : undefined, + define: { + __API_URL__: JSON.stringify(env.VITE_API_URL), + }, + } +}) +``` + +#### 主要な設定オプション + +| キー | デフォルト | 説明 | +|-----|---------|-------------| +| `root` | `'.'` | プロジェクトルート(`index.html` の場所) | +| `base` | `'/'` | デプロイされたアセットのパブリックベースパス | +| `envPrefix` | `'VITE_'` | クライアントに公開する環境変数のプレフィックス | +| `build.outDir` | `'dist'` | 出力ディレクトリ | +| `build.minify` | `'oxc'` | ミニファイアー(`'oxc'`、`'terser'`、または `false`) | +| `build.sourcemap` | `false` | `true`、`'inline'`、または `'hidden'` | + +### プラグイン + +#### 必須プラグイン + +ほとんどのプラグインのニーズは、少数のよく管理されたパッケージでカバーできます。独自のプラグインを作成する前にこれらを検討してください。 + +| プラグイン | 目的 | 使用タイミング | +|--------|---------|-------------| +| `@vitejs/plugin-react-swc` | SWC経由のReact HMR + Fast Refresh | Reactアプリのデフォルト(Babelバリアントより高速) | +| `@vitejs/plugin-react` | Babel経由のReact HMR + Fast Refresh | Babelプラグインが必要な場合のみ(emotion、MobXデコレーター) | +| `@vitejs/plugin-vue` | Vue 3 SFCサポート | Vueアプリ | +| `vite-plugin-checker` | ワーカースレッドでHMRオーバーレイ付きの `tsc` + ESLintを実行 | **TypeScriptアプリ全般** — Viteは `vite build` 中に型チェックを行いません | +| `vite-tsconfig-paths` | `tsconfig.json` の `paths` エイリアスを尊重 | `tsconfig.json` にエイリアスが既にある場合 | +| `vite-plugin-dts` | ライブラリモードで `.d.ts` ファイルを出力 | TypeScriptライブラリを公開するとき | +| `vite-plugin-svgr` | SVGをReactコンポーネントとしてインポート | SVGをコンポーネントとして使用するReactアプリ | +| `rollup-plugin-visualizer` | バンドルのツリーマップ/サンバーストレポート | 定期的なバンドルサイズの監査(`enforce: 'post'` を使用) | +| `vite-plugin-pwa` | ゼロ設定のPWA + Workbox | オフライン対応アプリ | + +**重要な注意:** `vite build` はトランスパイルしますが、型チェックは行いません。`vite-plugin-checker` を追加するか、CIで `tsc --noEmit` を実行しない限り、型エラーは本番環境にサイレントに出荷されます。 + +#### カスタムプラグインの作成 + +カスタムプラグインの作成は稀です。ほとんどのニーズは既存のプラグインでカバーできます。必要な場合は `vite.config.ts` にインラインで書き始め、再利用する場合にのみ抽出してください。 + +```typescript +// vite.config.ts — 最小限のインラインプラグイン +function myPlugin(): Plugin { + return { + name: 'my-plugin', // 必須、一意でなければならない + enforce: 'pre', // 'pre' | 'post'(オプション) + apply: 'build', // 'build' | 'serve'(オプション) + transform(code, id) { + if (!id.endsWith('.custom')) return + return { code: transformCustom(code), map: null } + }, + } +} +``` + +**主要フック:** `transform`(ソースの変更)、`resolveId` + `load`(仮想モジュール)、`transformIndexHtml`(HTMLへの注入)、`configureServer`(デベロップメントミドルウェアの追加)、`hotUpdate`(カスタムHMR — v7+で非推奨の `handleHotUpdate` の代替)。 + +**仮想モジュール**は `\0` プレフィックス規約を使用します — `resolveId` は `'\0virtual:my-id'` を返すことで他のプラグインがスキップします。ユーザーコードは `'virtual:my-id'` をインポートします。 + +完全なプラグインAPIは [vite.dev/guide/api-plugin](https://vite.dev/guide/api-plugin) を参照してください。開発中の変換パイプラインのデバッグには `vite-plugin-inspect` を使用してください。 + +### HMR API + +フレームワークプラグイン(`@vitejs/plugin-react`、`@vitejs/plugin-vue` など)はHMRを自動的に処理します。カスタム状態ストア、デベロップメントツール、または更新を跨いで状態を保持する必要があるフレームワーク非依存のユーティリティをビルドする場合のみ、`import.meta.hot` を直接使用してください。 + +```typescript +// src/store.ts — バニラモジュールの手動HMR +if (import.meta.hot) { + // 更新を跨いで状態を保持する(.dataを再代入せず、必ず変更すること) + import.meta.hot.data.count = import.meta.hot.data.count ?? 0 + + // モジュールが置き換えられる前にサイドエフェクトをクリーンアップ + import.meta.hot.dispose((data) => clearInterval(data.intervalId)) + + // このモジュール自身の更新を受け入れる + import.meta.hot.accept() +} +``` + +すべての `import.meta.hot` コードは本番ビルドからツリーシェイクされます — ガードを削除する必要はありません。 + +### 環境変数 + +Viteは `.env`、`.env.local`、`.env.[mode]`、`.env.[mode].local` をその順序で読み込みます(後のものが前のものを上書き)。`*.local` ファイルはgitignoreされており、ローカルのシークレット用です。 + +#### クライアントサイドアクセス + +`VITE_` プレフィックス付きの変数のみがクライアントコードに公開されます: + +```typescript +import.meta.env.VITE_API_URL // string +import.meta.env.MODE // 'development' | 'production' | カスタム +import.meta.env.BASE_URL // base設定値 +import.meta.env.DEV // boolean +import.meta.env.PROD // boolean +import.meta.env.SSR // boolean +``` + +#### 設定での環境変数使用 + +```typescript +// vite.config.ts +import { defineConfig, loadEnv } from 'vite' + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd()) // VITE_ プレフィックスのみ(安全) + return { + define: { + __API_URL__: JSON.stringify(env.VITE_API_URL), + }, + } +}) +``` + +### セキュリティ + +#### `VITE_` プレフィックスはセキュリティ境界ではない + +`VITE_` でプレフィックスされた変数は**ビルド時にクライアントバンドルに静的にインライン化されます**。ミニファイ、base64エンコード、ソースマップの無効化では隠せません。悪意のある攻撃者は出荷されたJavaScriptから任意の `VITE_` 変数を抽出できます。 + +**ルール:** パブリックな値(APIのURL、フィーチャーフラグ、パブリックキー)のみを `VITE_` 変数に入れてください。シークレット(APIトークン、データベースのURL、プライベートキー)はAPIまたはサーバーレス関数の背後にあるサーバーサイドに置かなければなりません。 + +#### `loadEnv('')` の落とし穴 + +```typescript +// BAD: 第3引数として '' を渡すと、サーバーのシークレットを含む全ての環境変数が読み込まれ、 +// `define` でクライアントコードにインライン化できてしまう。 +const env = loadEnv(mode, process.cwd(), '') + +// GOOD: 明示的なプレフィックスリスト +const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_']) +``` + +#### 本番環境のソースマップ + +本番環境のソースマップはオリジナルのソースコードを漏洩させます。エラートラッカー(Sentry、Bugsnag)にアップロードしてローカルで削除しない限り、無効にしてください: + +```typescript +build: { + sourcemap: false, // デフォルト — このままにする +} +``` + +#### `.gitignore` チェックリスト + +- `.env.local`、`.env.*.local` — ローカルのシークレットオーバーライド +- `dist/` — ビルド出力 +- `node_modules/.vite` — 事前バンドルキャッシュ(古いエントリはゴーストエラーを引き起こす) + +### サーバープロキシ + +```typescript +// vite.config.ts — server.proxy +server: { + proxy: { + '/foo': 'http://localhost:4567', // 文字列の短縮形 + + '/api': { + target: 'http://localhost:8080', + changeOrigin: true, // 仮想ホストバックエンドに必要 + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, +} +``` + +WebSocketプロキシには、ルート設定に `ws: true` を追加してください。 + +### ビルド最適化 + +#### 手動チャンク + +```typescript +// vite.config.ts — build.rolldownOptions +build: { + rolldownOptions: { + output: { + // オブジェクト形式:特定のパッケージをグループ化 + manualChunks: { + 'react-vendor': ['react', 'react-dom'], + 'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'], + }, + }, + }, +} +``` + +```typescript +// 関数形式:ヒューリスティックで分割 +manualChunks(id) { + if (id.includes('node_modules/react')) return 'react-vendor' + if (id.includes('node_modules')) return 'vendor' +} +``` + +### パフォーマンス + +#### バレルファイルを避ける + +バレルファイル(ディレクトリからすべてを再エクスポートする `index.ts`)は、1つのシンボルをインポートする場合でも再エクスポートされたファイルをすべて読み込むことを強制します。これは公式ドキュメントで指摘されているデベロップメントサーバーの速度低下の主な原因です。 + +```typescript +// BAD — 1つのユーティリティのインポートがViteにバレル全体を読み込ませる +import { slash } from '@/utils' + +// GOOD — 直接インポート、そのファイルだけが読み込まれる +import { slash } from '@/utils/slash' +``` + +#### インポート拡張子を明示的にする + +暗黙の拡張子はそれぞれ `resolve.extensions` を通じて最大6回のファイルシステムチェックを強制します。大規模なコードベースでは積み重なります。 + +```typescript +// BAD +import Component from './Component' + +// GOOD +import Component from './Component.tsx' +``` + +`tsconfig.json` の `allowImportingTsExtensions` と `resolve.extensions` を実際に使用する拡張子だけに絞ってください。 + +#### ホットパスルートのウォームアップ + +`server.warmup.clientFiles` は、ブラウザがリクエストする前に既知のホットエントリを事前変換します。これにより大規模アプリでのコールドロードリクエストのウォーターフォールが解消されます。 + +```typescript +// vite.config.ts +server: { + warmup: { + clientFiles: ['./src/main.tsx', './src/routes/**/*.tsx'], + }, +} +``` + +#### 遅いデベロップメントサーバーのプロファイリング + +`vite dev` が遅いと感じたら、`vite --profile` から始めてアプリを操作し、`p+enter` を押して `.cpuprofile` を保存します。[Speedscope](https://www.speedscope.app) で読み込み、どのプラグインが時間を消費しているかを確認します(通常はコミュニティプラグインの `buildStart`、`config`、または `configResolved` フック)。 + +### ライブラリモード + +npmパッケージを公開する場合は `build.lib` を使用します。設定の詳細よりも重要な2つの落とし穴があります: + +1. **型は出力されません** — `vite-plugin-dts` を追加するか、別途 `tsc --emitDeclarationOnly` を実行してください。 +2. **ピア依存関係は必ず外部化しなければなりません** — リストされていないピアがライブラリにバンドルされると、コンシューマーで重複ランタイムエラーが発生します。 + +```typescript +// vite.config.ts +build: { + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: (format) => `my-lib.${format}.js`, + }, + rolldownOptions: { + external: ['react', 'react-dom', 'react/jsx-runtime'], // すべてのピア依存関係 + }, +} +``` + +### SSR外部化 + +ベアの `createServer({ middlewareMode: true })` のセットアップはフレームワーク作者向けです。ほとんどのアプリはNuxt、Remix、SvelteKit、Astro、またはTanStack Startを使用すべきです。フレームワークユーザーとして調整するのは、依存関係がSSRで壊れた場合の外部化設定です: + +```typescript +// vite.config.ts — SSRオプション +ssr: { + external: ['node-native-package'], // SSRバンドルで require() として保持 + noExternal: ['esm-only-package'], // SSR出力に強制バンドル(ほとんどのSSRエラーを修正) + target: 'node', // 'node' または 'webworker' +} +``` + +### 依存関係の事前バンドル + +Viteは依存関係を事前バンドルして、CJS/UMDをESMに変換し、リクエスト数を削減します。 + +```typescript +// vite.config.ts — optimizeDeps +optimizeDeps: { + include: [ + 'lodash-es', // 重い依存関係を強制的に事前バンドル + 'cjs-package', // 相互運用問題を引き起こすCJS依存関係 + 'deep-lib/components/**', // 深いインポートのグロブ + ], + exclude: ['local-esm-package'], // 除外する場合は有効なESMでなければならない + force: true, // キャッシュを無視して再最適化(一時的なデバッグ) +} +``` + +### 一般的な落とし穴 + +#### デベロップメントとビルドが一致しない + +デベロップメントは変換にesbuild/Rolldownを使用し、ビルドはバンドルにRolldownを使用します。CJSライブラリは両者で異なる動作をする場合があります。デプロイ前に必ず `vite build && vite preview` で確認してください。 + +#### デプロイ後の古いチャンク + +新しいビルドは新しいチャンクハッシュを生成します。アクティブなセッションを持つユーザーは、もはや存在しない古いファイル名をリクエストします。Viteには組み込みの解決策がありません。緩和策: + +- デプロイメントウィンドウ中は古い `dist/assets/` ファイルを保持する +- ルーターでダイナミックインポートエラーをキャッチしてページをリロードする + +#### Dockerとコンテナ + +Viteはデフォルトで `localhost` にバインドし、コンテナの外からはアクセスできません: + +```typescript +// vite.config.ts — Docker/コンテナ設定 +server: { + host: true, // 0.0.0.0 にバインド + hmr: { clientPort: 3000 }, // リバースプロキシ経由の場合 +} +``` + +#### モノレポのファイルアクセス + +Viteはプロジェクトルートへのファイル提供を制限します。ルート外のパッケージはブロックされます: + +```typescript +// vite.config.ts — モノレポのファイルアクセス +server: { + fs: { + allow: ['..'], // 親ディレクトリ(ワークスペースルート)を許可 + }, +} +``` + +### アンチパターン + +```typescript +// BAD: envPrefix を '' にすると全ての環境変数(シークレットを含む)がクライアントに公開される +envPrefix: '' + +// BAD: アプリケーションソースコードで require() が動くと思い込む — ViteはESMファースト +const lib = require('some-lib') // 代わりに import を使用 + +// BAD: 全てのnode_moduleを個別のチャンクに分割する — 何百もの小さなファイルを生成 +manualChunks(id) { + if (id.includes('node_modules')) { + return id.split('node_modules/')[1].split('/')[0] // パッケージごとに1チャンク + } +} + +// BAD: ライブラリモードでピア依存関係を外部化しない — 重複ランタイムエラーを引き起こす +// rolldownOptions.external なしの build.lib + +// BAD: 非推奨のesbuildミニファイアーを使用する +build: { minify: 'esbuild' } // 'oxc'(デフォルト)または 'terser' を使用 + +// BAD: import.meta.hot.data を再代入で変更する +import.meta.hot.data = { count: 0 } // 誤り:プロパティを変更すべきで再代入しない +import.meta.hot.data.count = 0 // 正しい +``` + +**プロセスのアンチパターン:** + +- **`vite preview` は本番サーバーではありません** — ビルドされたバンドルのスモークテストです。`dist/` を実際の静的ホスト(NGINX、Cloudflare Pages、Vercel静的)にデプロイするか、マルチステージDockerfileを使用してください。 +- **`vite build` が型チェックを行うと期待する** — トランスパイルのみです。型エラーは本番環境にサイレントに出荷されます。`vite-plugin-checker` を追加するか、CIで `tsc --noEmit` を実行してください。 +- **デフォルトで `@vitejs/plugin-legacy` を導入する** — バンドルサイズが約40%膨らみ、ソースマップのバンドルアナライザーが壊れ、95%以上のモダンブラウザユーザーには不要です。仮定ではなく実際のアナリティクスに基づいて適用してください。 +- **`tsconfig.json` パスを重複した30以上の `resolve.alias` エントリで手動管理する** — 代わりに `vite-tsconfig-paths` を使用してください。ExcalidrawやPostHogで観察されているため、新しいプロジェクトでは避けてください。 +- **依存関係の変更後に古い `node_modules/.vite` を放置する** — 事前バンドルキャッシュがゴーストエラーを引き起こします。ブランチを切り替えたときや依存関係をパッチした後にクリアしてください。 + +## クイックリファレンス + +| パターン | 使用タイミング | +|---------|-------------| +| `defineConfig` | 常に — 型推論を提供する | +| `loadEnv(mode, root, ['VITE_'])` | 設定での環境変数アクセス(明示的なプレフィックス) | +| `vite-plugin-checker` | TypeScriptアプリ(型チェックのギャップを埋める) | +| `vite-tsconfig-paths` | 手動の `resolve.alias` の代わりに | +| `optimizeDeps.include` | 相互運用問題を引き起こすCJS依存関係 | +| `server.proxy` | デベロップメント中にAPIリクエストをバックエンドにルーティング | +| `server.host: true` | Docker、コンテナ、リモートアクセス | +| `server.warmup.clientFiles` | ホットパスルートの事前変換 | +| `build.lib` + `external` | npmパッケージの公開 | +| `manualChunks`(オブジェクト形式) | ベンダーバンドルの分割 | +| `vite --profile` | 遅いデベロップメントサーバーのデバッグ | +| `vite build && vite preview` | 本番バンドルのローカルスモークテスト(本番サーバーではない) | + +## 関連スキル + +- `frontend-patterns` — Reactコンポーネントパターン +- `docker-patterns` — Viteを使用したコンテナ化されたデベロップメント +- `nextjs-turbopack` — Next.jsの代替バンドラー diff --git a/docs/ja-JP/skills/windows-desktop-e2e/SKILL.md b/docs/ja-JP/skills/windows-desktop-e2e/SKILL.md new file mode 100644 index 00000000..47e70a41 --- /dev/null +++ b/docs/ja-JP/skills/windows-desktop-e2e/SKILL.md @@ -0,0 +1,784 @@ +--- +name: windows-desktop-e2e +description: E2E testing for Windows native desktop apps (WPF, WinForms, Win32/MFC, Qt) using pywinauto and Windows UI Automation. +origin: ECC +--- + +# Windows デスクトップ E2E テスト + +**pywinauto** と Windows UI Automation(UIA)を使用したWindowsネイティブデスクトップアプリケーションのエンドツーエンドテスト。WPF、WinForms、Win32/MFC、Qt(5.x / 6.x)をカバーし、Qt固有のガイダンスは専用セクションとして提供します。 + +## アクティベートするタイミング + +- Windowsネイティブデスクトップアプリケーションのエンドツーエンドテストを書くまたは実行するとき +- デスクトップGUIテストスイートをゼロから設定するとき +- 不安定または失敗するデスクトップオートメーションテストを診断するとき +- 既存のアプリにテスタビリティ(AutomationId、アクセシブルな名前)を追加するとき +- デスクトップエンドツーエンドをCI/CDパイプライン(GitHub Actions `windows-latest`)に統合するとき + +### 使用しないタイミング + +- Webアプリケーション → `e2e-testing` スキル(Playwright)を使用する +- Electron / CEF / WebView2 アプリ → HTMLレイヤーにはUIAではなくブラウザオートメーションが必要 +- モバイルアプリ → プラットフォーム固有のツールを使用する(UIAutomator、XCUITest) +- 実行中のGUIを必要としない純粋なユニットまたは統合テスト + +## コアコンセプト + +すべてのWindowsデスクトップオートメーションは**UI Automation(UIA)**に依存します。これはWindowsに組み込まれたアクセシビリティAPIです。サポートされているすべてのフレームワークは、読み取りおよび操作可能なプロパティを持つUIA要素のツリーを公開します: + +``` +テスト(Python) + └── pywinauto(UIAバックエンド) + └── Windows UI Automation API ← Windowsに組み込み、フレームワーク非依存 + └── アプリのUIAプロバイダー ← 各フレームワークが独自に実装 + └── 実行中の .exe +``` + +**フレームワーク別UIA品質:** + +| フレームワーク | AutomationId | 信頼性 | 注記 | +|-----------|-------------|-------------|-------| +| WPF | ★★★★★ | 優秀 | `x:Name` が直接AutomationIdにマッピング | +| WinForms | ★★★★☆ | 良好 | `AccessibleName` = AutomationId | +| UWP / WinUI 3 | ★★★★★ | 優秀 | Microsoftの完全サポート | +| Qt 6.x | ★★★★★ | 優秀 | アクセシビリティがデフォルトで有効;クラス名が `Qt6*` に変更 | +| Qt 5.15+ | ★★★★☆ | 良好 | Accessibilityモジュールが改善 | +| Qt 5.7–5.14 | ★★★☆☆ | 普通 | `QT_ACCESSIBILITY=1` が必要;objectNameは手動設定 | +| Win32 / MFC | ★★★☆☆ | 普通 | コントロールIDにアクセス可能;テキストマッチングが一般的 | + +## セットアップと前提条件 + +```bash +# Python 3.8+、Windowsのみ +pip install pywinauto pytest pytest-html Pillow pytest-timeout +# オプション:画面録画 +# ffmpegをインストールしてPATHに追加:https://ffmpeg.org/download.html +``` + +UIAが到達可能か確認: + +```python +from pywinauto import Desktop +Desktop(backend="uia").windows() # すべてのトップレベルウィンドウを一覧表示 +``` + +**Accessibility Insights for Windows**をインストールしてください(Microsoft提供、無料)— テストを書く前にUIA要素ツリーを検査するためのDevTools相当のツールです。 + +## テスタビリティのセットアップ(フレームワーク別) + +テストを書く前に**全てのインタラクティブなコントロールに安定したAutomationIdを設定すること**が最も効果的です。 + +### WPF + +```xml + + + +