mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-18 14:53:05 +08:00
docs: add native Japanese translation of ECC documentation (ja-JP)
Translate everything-claude-code repository to Japanese including: - 17 root documentation files - 60 agent documentation files - 80 command documentation files - 99 rule files across 18 language directories (common, angular, arkts, cpp, csharp, dart, fsharp, golang, java, kotlin, perl, php, python, ruby, rust, swift, typescript, web) - 199 skill documentation files Total: 455 files translated to Japanese with: - Consistent terminology glossary applied throughout - YAML field names preserved in English (name, description, etc.) - Code blocks and examples untouched (comments translated) - Markdown structure and relative links preserved - Professional translation maintaining technical accuracy This translation expands ECC accessibility to Japanese-speaking developers and teams. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
153
docs/ja-JP/rules/arkts/coding-style.md
Normal file
153
docs/ja-JP/rules/arkts/coding-style.md
Normal file
@@ -0,0 +1,153 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.ets"
|
||||
- "**/*.ts"
|
||||
- "**/module.json5"
|
||||
- "**/oh-package.json5"
|
||||
- "**/build-profile.json5"
|
||||
---
|
||||
# HarmonyOS / ArkTS コーディングスタイル
|
||||
|
||||
> このファイルは [common/coding-style.md](../common/coding-style.md) を HarmonyOS および ArkTS 固有のコンテンツで拡張します。
|
||||
|
||||
## ArkTS 言語の制約
|
||||
|
||||
ArkTS は TypeScript の厳格な静的型付きサブセットです。これらの制約に違反すると**コンパイルエラー**が発生します。
|
||||
|
||||
### 型システム
|
||||
|
||||
- `any` や `unknown` 型は使用不可 — 常に明示的な型を使用する
|
||||
- インデックスアクセス型は使用不可 — 型名を直接使用する
|
||||
- 条件付き型エイリアスや `infer` キーワードは使用不可
|
||||
- 交差型は使用不可 — 継承を使用する
|
||||
- マップ型は使用不可 — クラスと通常のイディオムを使用する
|
||||
- 型注釈に `typeof` は使用不可 — 明示的な型宣言を使用する
|
||||
- `as const` アサーションは使用不可 — 明示的な型注釈を使用する
|
||||
- 構造的型付けは使用不可 — 継承、インターフェース、型エイリアスを使用する
|
||||
- `Partial`、`Required`、`Readonly`、`Record` 以外の TypeScript ユーティリティ型は使用不可
|
||||
- `Record<K, V>` のインデックス式の型は `V | undefined`
|
||||
- `catch` 句では型注釈を省略する(ArkTS は `any`/`unknown` をサポートしない)
|
||||
|
||||
### 関数とクラス
|
||||
|
||||
- 関数式は使用不可 — アロー関数を使用する
|
||||
- ネストした関数は使用不可 — ラムダを使用する
|
||||
- ジェネレーター関数は使用不可 — マルチタスクには `async`/`await` を使用する
|
||||
- `Function.apply`、`Function.call`、`Function.bind` は使用不可 — `this` には従来の OOP を使用する
|
||||
- コンストラクタ型式は使用不可 — ラムダを使用する
|
||||
- インターフェースやオブジェクト型のコンストラクタシグネチャは使用不可 — メソッドかクラスを使用する
|
||||
- コンストラクタ内でのクラスフィールド宣言は不可 — クラス本体で宣言する
|
||||
- スタンドアロン関数や静的メソッドで `this` は使用不可 — インスタンスメソッド内のみ
|
||||
- `new.target` は使用不可
|
||||
- 確実な代入アサーション(`let v!: T`)は使用不可 — 初期化済み宣言を使用する
|
||||
- クラスリテラルは使用不可 — 名前付きクラス型を導入する
|
||||
- クラスをオブジェクトとして使用(変数への代入)は不可 — クラス宣言は値ではなく型を導入する
|
||||
- クラスごとに静的ブロックは1つのみ — すべての静的ステートメントをまとめる
|
||||
|
||||
### オブジェクトとプロパティアクセス
|
||||
|
||||
- 動的フィールド宣言や `obj["field"]` アクセスは使用不可 — `obj.field` 構文を使用する
|
||||
- `delete` 演算子は使用不可 — 不在を示すには `null` を持つ nullable 型を使用する
|
||||
- プロトタイプへの代入は使用不可 — クラスとインターフェースを使用する
|
||||
- `in` 演算子は使用不可 — `instanceof` を使用する
|
||||
- オブジェクトメソッドの再代入は不可 — ラッパー関数や継承を使用する
|
||||
- `Symbol()` API は使用不可(`Symbol.iterator` を除く)
|
||||
- `globalThis` やグローバルスコープは使用不可 — 明示的なモジュールのエクスポート/インポートを使用する
|
||||
- 名前空間をオブジェクトとして使用は不可 — クラスかモジュールを使用する
|
||||
- 名前空間内のステートメントは不可 — 関数を使用する
|
||||
|
||||
### 分割代入とスプレッド
|
||||
|
||||
- 分割代入や変数宣言は使用不可 — 中間オブジェクトとフィールドごとのアクセスを使用する
|
||||
- 分割代入のパラメータ宣言は使用不可 — パラメータを直接渡し、ローカル名を手動で割り当てる
|
||||
- スプレッド演算子は配列(または配列派生クラス)をレストパラメータや配列リテラルに展開する場合のみ使用可
|
||||
|
||||
### モジュールとインポート
|
||||
|
||||
- `require()` は使用不可 — 通常の `import` 構文を使用する
|
||||
- `export = ...` は使用不可 — 通常のエクスポート/インポートを使用する
|
||||
- インポートアサーションは使用不可 — ArkTS ではインポートはコンパイル時に解決される
|
||||
- UMD モジュールは使用不可
|
||||
- モジュール名にワイルドカードは使用不可
|
||||
- すべての `import` ステートメントは他のすべてのステートメントより前に記述する
|
||||
- TypeScript のコードベースは import 経由で ArkTS のコードベースに依存してはならない(逆はサポート)
|
||||
|
||||
### その他の制限
|
||||
|
||||
- `var` は使用不可 — `let` を使用する
|
||||
- `for...in` ループは使用不可 — 配列には通常の `for` ループを使用する
|
||||
- `with` ステートメントは使用不可
|
||||
- JSX 式は使用不可
|
||||
- `#` プライベート識別子は使用不可 — `private` キーワードを使用する
|
||||
- 宣言のマージ(クラス、インターフェース、列挙型)は不可 — 定義をコンパクトに保つ
|
||||
- インデックスシグネチャは使用不可 — 配列を使用する
|
||||
- カンマ演算子は `for` ループ内のみ
|
||||
- 単項演算子 `+`、`-`、`~` は数値型のみ(暗黙の文字列変換なし)
|
||||
- 列挙型のメンバー: 明示的な初期化子には同じ型のコンパイル時式のみ
|
||||
- 関数の戻り値型推論は制限あり — 戻り値型を省略した関数呼び出し時は明示的に指定する
|
||||
|
||||
### オブジェクトリテラル
|
||||
|
||||
- コンパイラが対応するクラスやインターフェースを推論できる場合のみサポート
|
||||
- 次の場合はサポートされない: `any`/`Object`/`object` 型、メソッドを持つクラス/インターフェース、パラメータ付きコンストラクタを持つクラス、`readonly` フィールドを持つクラス
|
||||
|
||||
## 命名規則
|
||||
|
||||
- 変数 / 関数: `camelCase`(例: `getUserInfo`、`goodsList`)
|
||||
- クラス / インターフェース: `PascalCase`(例: `UserViewModel`、`IGoodsModel`)
|
||||
- 定数: `UPPER_SNAKE_CASE`(例: `MAX_PAGE_SIZE`、`COLOR_PRIMARY`)
|
||||
- ファイル名: コンポーネントは `PascalCase`(例: `HomePage.ets`)、ユーティリティは `camelCase`
|
||||
|
||||
## フォーマット
|
||||
|
||||
- 文字列にはダブルクォートを優先する
|
||||
- ステートメント末尾にセミコロンを付ける
|
||||
- `var` は絶対に使用しない — `const` を優先し、次に `let`
|
||||
- すべてのメソッド、パラメータ、戻り値には完全な型注釈を付ける
|
||||
|
||||
## ファイル構成
|
||||
|
||||
- コンポーネントファイル(`.ets`): ファイルごとに1つの `@ComponentV2`
|
||||
- ViewModel ファイル: ファイルごとに1つの ViewModel クラス
|
||||
- モデルファイル: 関連するデータモデルは同じファイルに共存可能
|
||||
- ファイルは400行以内に収める。800行に近づく場合はヘルパーを抽出する
|
||||
|
||||
## コメント
|
||||
|
||||
- ファイルヘッダー: `@file`(ファイルの目的)+ `@author`(開発者)— プロジェクトがすでにファイルヘッダーを使用している場合
|
||||
- パブリックメソッド: JSDoc に `@param`、`@returns` を付ける。複雑なメソッドには `@example` を追加する
|
||||
- プロジェクトの既存のドキュメント言語に合わせる。リポジトリが中国語コメントを標準化していない限り英語を使用する
|
||||
|
||||
## エラーハンドリング
|
||||
|
||||
```typescript
|
||||
// 適切なエラーハンドリングで try/catch を使用する
|
||||
try {
|
||||
const result = await riskyOperation()
|
||||
return result
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'TAG', 'Operation failed: %{public}s', error)
|
||||
throw new Error('User-friendly error message')
|
||||
}
|
||||
```
|
||||
|
||||
## イミュータビリティ
|
||||
|
||||
共通のイミュータビリティ原則に従う — ミューテートするのではなく新しいオブジェクトを作成する:
|
||||
|
||||
```typescript
|
||||
// BAD: ミューテーション
|
||||
function updateUser(user: UserModel, name: string): UserModel {
|
||||
user.name = name // 直接変更
|
||||
return user
|
||||
}
|
||||
|
||||
// GOOD: イミュータブル — 新しいインスタンスを作成
|
||||
function updateUser(user: UserModel, name: string): UserModel {
|
||||
const updated = new UserModel()
|
||||
updated.id = user.id
|
||||
updated.name = name
|
||||
updated.email = user.email
|
||||
return updated
|
||||
}
|
||||
```
|
||||
135
docs/ja-JP/rules/arkts/hooks.md
Normal file
135
docs/ja-JP/rules/arkts/hooks.md
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.ets"
|
||||
- "**/*.ts"
|
||||
- "**/module.json5"
|
||||
- "**/oh-package.json5"
|
||||
---
|
||||
# HarmonyOS / ArkTS フック
|
||||
|
||||
> このファイルは [common/hooks.md](../common/hooks.md) を HarmonyOS 固有のビルドおよび検証フックで拡張します。
|
||||
|
||||
## ビルドコマンド
|
||||
|
||||
### HAP パッケージのビルド
|
||||
|
||||
```bash
|
||||
# HAP パッケージをビルドする(グローバル hvigor 環境)
|
||||
hvigorw assembleHap -p product=default
|
||||
|
||||
# 特定のモジュールでビルドする
|
||||
hvigorw assembleHap -p module=entry -p product=default
|
||||
|
||||
# クリーンビルド
|
||||
hvigorw clean
|
||||
```
|
||||
|
||||
### DevEco Studio CLI
|
||||
|
||||
```bash
|
||||
# プロジェクト構造を確認する
|
||||
hvigorw --version
|
||||
|
||||
# 依存関係をインストールする
|
||||
ohpm install
|
||||
|
||||
# 依存関係を更新する
|
||||
ohpm update
|
||||
```
|
||||
|
||||
## 推奨 PostToolUse フック
|
||||
|
||||
### .ets/.ts ファイル編集後
|
||||
|
||||
ArkTS のコンパイルエラーを確認するために hvigor ビルドを実行する:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PostToolUse",
|
||||
"matcher": {
|
||||
"tool": ["Edit", "Write"],
|
||||
"filePath": ["**/*.ets", "**/*.ts"]
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"command": "hvigorw assembleHap -p product=default 2>&1 | tail -20",
|
||||
"async": true,
|
||||
"timeout": 60000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### module.json5 編集後
|
||||
|
||||
パーミッションとアビリティの宣言を検証する:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PostToolUse",
|
||||
"matcher": {
|
||||
"tool": "Edit",
|
||||
"filePath": "**/module.json5"
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"command": "echo '[HarmonyOS] module.json5 modified - verify permissions and abilities'",
|
||||
"async": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### oh-package.json5 編集後
|
||||
|
||||
依存関係を再インストールする:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PostToolUse",
|
||||
"matcher": {
|
||||
"tool": "Edit",
|
||||
"filePath": "**/oh-package.json5"
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"command": "ohpm install 2>&1 | tail -10",
|
||||
"async": true,
|
||||
"timeout": 30000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## PreToolUse フック
|
||||
|
||||
### V1 デコレーターガード
|
||||
|
||||
コードに V1 状態管理デコレーターが含まれている場合に警告する:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PreToolUse",
|
||||
"matcher": {
|
||||
"tool": ["Write", "Edit"],
|
||||
"filePath": "**/*.ets"
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"command": "echo '[HarmonyOS] Reminder: Use @ComponentV2 / @Local / @Param - V1 decorators (@State, @Prop, @Link) are prohibited'"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 検証チェックリスト
|
||||
|
||||
各実装サイクルの後、以下を確認する:
|
||||
|
||||
- [ ] `hvigorw assembleHap` がエラーなしで完了する
|
||||
- [ ] 新規または変更した `.ets` ファイルに V1 デコレーターがない
|
||||
- [ ] 新規または変更したファイルに `@ohos.router` のインポートがない
|
||||
- [ ] すべての API パーミッションが `module.json5` に宣言されている
|
||||
- [ ] すべての依存関係が `oh-package.json5` に記載されている
|
||||
- [ ] リソース文字列がすべての i18n ディレクトリに追加されている
|
||||
- [ ] 新しいカラーリソースにダークテーマのカラーが提供されている
|
||||
236
docs/ja-JP/rules/arkts/patterns.md
Normal file
236
docs/ja-JP/rules/arkts/patterns.md
Normal file
@@ -0,0 +1,236 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.ets"
|
||||
- "**/*.ts"
|
||||
---
|
||||
# HarmonyOS / ArkTS パターン
|
||||
|
||||
> このファイルは [common/patterns.md](../common/patterns.md) を HarmonyOS および ArkTS 固有のパターンで拡張します。
|
||||
|
||||
## 状態管理: V2 のみ
|
||||
|
||||
ArkUI 状態管理 V2 を**必ず使用**すること。V1 デコレーターは非推奨であり、使用してはならない。
|
||||
|
||||
### V2 デコレーター
|
||||
|
||||
| デコレーター | 用途 |
|
||||
|------------|------|
|
||||
| `@ComponentV2` | 構造体を V2 コンポーネントとしてマークする |
|
||||
| `@Local` | コンポーネント内のローカル状態 |
|
||||
| `@Param` | 親から受け取るプロパティ(読み取り専用) |
|
||||
| `@Event` | 子から親へのコールバックイベント |
|
||||
| `@Provider` | 子孫コンポーネントへ状態を提供する |
|
||||
| `@Consumer` | 祖先の `@Provider` から状態を取得する |
|
||||
| `@Monitor` | 状態変化を監視する(V1 の `@Watch` を置き換え) |
|
||||
| `@Computed` | 派生/計算された値 |
|
||||
| `@ObservedV2` | V2 状態管理のためにクラスをオブザーバブルにする |
|
||||
| `@Trace` | `@ObservedV2` クラスのオブザーバブルプロパティをマークする |
|
||||
|
||||
### 禁止されている V1 デコレーター
|
||||
|
||||
絶対に使用しないこと: `@State`、`@Prop`、`@Link`、`@ObjectLink`、`@Observed`、`@Provide`、`@Consume`、`@Watch`、`@Component`(代わりに `@ComponentV2` を使用)。
|
||||
|
||||
### V2 コンポーネントの例
|
||||
|
||||
```typescript
|
||||
@ObservedV2
|
||||
class UserModel {
|
||||
@Trace name: string = ''
|
||||
@Trace age: number = 0
|
||||
}
|
||||
|
||||
@ComponentV2
|
||||
struct UserCard {
|
||||
@Param user: UserModel = new UserModel()
|
||||
@Event onDelete: () => void = () => {}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text(this.user.name)
|
||||
.fontSize($r('app.float.font_size_title'))
|
||||
Text(`${this.user.age}`)
|
||||
.fontSize($r('app.float.font_size_body'))
|
||||
Button($r('app.string.delete'))
|
||||
.onClick(() => this.onDelete())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 状態の同期
|
||||
|
||||
```typescript
|
||||
@ComponentV2
|
||||
struct ParentPage {
|
||||
@Provider('userState') userModel: UserModel = new UserModel()
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
ChildComponent() // @Consumer('userState') を自動的に受け取る
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ComponentV2
|
||||
struct ChildComponent {
|
||||
@Consumer('userState') userModel: UserModel = new UserModel()
|
||||
|
||||
build() {
|
||||
Text(this.userModel.name)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ルーティング: Navigation のみ
|
||||
|
||||
`NavPathStack` を使用した `Navigation` コンポーネントを**必ず使用**すること。`@ohos.router` は絶対に使用しないこと。
|
||||
|
||||
### Navigation のセットアップ
|
||||
|
||||
```typescript
|
||||
@ComponentV2
|
||||
struct MainPage {
|
||||
@Local navPathStack: NavPathStack = new NavPathStack()
|
||||
|
||||
build() {
|
||||
Navigation(this.navPathStack) {
|
||||
// ホームコンテンツ
|
||||
}
|
||||
.navDestination(this.routerMap)
|
||||
}
|
||||
|
||||
@Builder
|
||||
routerMap(name: string, param: ESObject) {
|
||||
if (name === 'detail') {
|
||||
DetailPage()
|
||||
} else if (name === 'settings') {
|
||||
SettingsPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ページナビゲーション
|
||||
|
||||
```typescript
|
||||
// 新しいページをプッシュする
|
||||
this.navPathStack.pushPath({ name: 'detail', param: { id: '123' } })
|
||||
|
||||
// 現在のページを置き換える
|
||||
this.navPathStack.replacePath({ name: 'settings' })
|
||||
|
||||
// 戻る
|
||||
this.navPathStack.pop()
|
||||
|
||||
// ルートに戻る
|
||||
this.navPathStack.clear()
|
||||
```
|
||||
|
||||
### NavDestination サブページ
|
||||
|
||||
```typescript
|
||||
@ComponentV2
|
||||
struct DetailPage {
|
||||
build() {
|
||||
NavDestination() {
|
||||
Column() {
|
||||
Text($r('app.string.detail_title'))
|
||||
}
|
||||
}
|
||||
.title($r('app.string.detail_nav_title'))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## アーキテクチャパターン: MVVM
|
||||
|
||||
HarmonyOS アプリケーションに推奨されるアーキテクチャ:
|
||||
|
||||
```
|
||||
feature/
|
||||
|-- model/ # データモデル(@ObservedV2 クラス)
|
||||
|-- viewmodel/ # ビジネスロジック(ViewModel クラス)
|
||||
|-- view/ # UI コンポーネント(@ComponentV2 構造体)
|
||||
|-- service/ # API 呼び出し、データアクセス
|
||||
```
|
||||
|
||||
- **View**: レンダリングロジックのみ、`build()` 内にビジネスロジックを含めない
|
||||
- **ViewModel**: すべてのビジネスロジックをここにカプセル化する
|
||||
- **Model**: `@ObservedV2` と `@Trace` を持つ純粋なデータクラス
|
||||
- **Service**: ネットワークリクエスト、データベース操作、ファイル I/O
|
||||
|
||||
## ArkUI アニメーションパターン
|
||||
|
||||
### 状態駆動アニメーション
|
||||
|
||||
```typescript
|
||||
@ComponentV2
|
||||
struct AnimatedCard {
|
||||
@Local isExpanded: boolean = false
|
||||
@Local cardScale: number = 0.8
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
// コンテンツ
|
||||
}
|
||||
.scale({ x: this.cardScale, y: this.cardScale })
|
||||
.animation({ duration: 300, curve: Curve.EaseInOut })
|
||||
.onClick(() => {
|
||||
this.isExpanded = !this.isExpanded
|
||||
this.cardScale = this.isExpanded ? 1.0 : 0.8
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### アニメーションのルール
|
||||
|
||||
- ネイティブ HarmonyOS アニメーション API と高度なテンプレートを優先する
|
||||
- 状態変数の変更でアニメーションをトリガーする状態駆動アニメーションを持つ宣言的 UI を使用する
|
||||
- 複雑なサブコンポーネントアニメーションのレンダリングバッチを削減するために `renderGroup(true)` を設定する
|
||||
- アニメーション中に `width`、`height`、`padding`、`margin` を頻繁に変更しないこと — パフォーマンスに深刻な影響
|
||||
- 明示的なアニメーション制御には `animateTo` を使用する
|
||||
- パフォーマンスの高いアニメーションには `transform`(translate、scale、rotate)と `opacity` を優先する
|
||||
|
||||
## パフォーマンスパターン
|
||||
|
||||
### 大きなリストへの LazyForEach
|
||||
|
||||
```typescript
|
||||
@ComponentV2
|
||||
struct LargeList {
|
||||
@Local dataSource: MyDataSource = new MyDataSource()
|
||||
|
||||
build() {
|
||||
List() {
|
||||
LazyForEach(this.dataSource, (item: ItemModel) => {
|
||||
ListItem() {
|
||||
ItemComponent({ item: item })
|
||||
}
|
||||
}, (item: ItemModel) => item.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### コンポーネントの再利用
|
||||
|
||||
- 再利用可能なコンポーネントを別のファイルに抽出する
|
||||
- コンポーネント内の軽量な UI フラグメントには `@Builder` を使用する
|
||||
- 設定可能なコンポーネントには `@Param` を使用する
|
||||
|
||||
## リソース参照
|
||||
|
||||
UI 定数は常にリソースとして定義し、`$r()` 経由で参照する:
|
||||
|
||||
```typescript
|
||||
// BAD: ハードコードされた値
|
||||
Text('Hello')
|
||||
.fontSize(16)
|
||||
.fontColor('#333333')
|
||||
|
||||
// GOOD: リソース参照
|
||||
Text($r('app.string.greeting'))
|
||||
.fontSize($r('app.float.font_size_body'))
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
```
|
||||
141
docs/ja-JP/rules/arkts/security.md
Normal file
141
docs/ja-JP/rules/arkts/security.md
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.ets"
|
||||
- "**/*.ts"
|
||||
- "**/module.json5"
|
||||
---
|
||||
# HarmonyOS / ArkTS セキュリティ
|
||||
|
||||
> このファイルは [common/security.md](../common/security.md) を HarmonyOS 固有のセキュリティプラクティスで拡張します。
|
||||
|
||||
## パーミッション管理
|
||||
|
||||
### module.json5 でのパーミッション宣言
|
||||
|
||||
パーミッションが必要なすべてのシステム API 呼び出しを宣言する必要がある:
|
||||
|
||||
```json5
|
||||
{
|
||||
"module": {
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.INTERNET",
|
||||
"reason": "$string:internet_permission_reason",
|
||||
"usedScene": {
|
||||
"abilities": ["EntryAbility"],
|
||||
"when": "always"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パーミッションチェックリスト
|
||||
|
||||
システム API を呼び出す前に確認する:
|
||||
|
||||
- [ ] パーミッションが `module.json5` に宣言されている
|
||||
- [ ] パーミッション理由の文字列がリソースで定義されている(ユーザー向けパーミッションの場合)
|
||||
- [ ] 機密性の高いパーミッション(カメラ、位置情報など)に対してランタイムパーミッションリクエストが実装されている
|
||||
- [ ] API 呼び出し前にパーミッションを確認し、拒否時の適切なフォールバックがある
|
||||
|
||||
### ランタイムパーミッションリクエスト
|
||||
|
||||
```typescript
|
||||
import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
|
||||
|
||||
async function checkAndRequestPermission(permission: Permissions): Promise<boolean> {
|
||||
const atManager = abilityAccessCtrl.createAtManager();
|
||||
const bundleInfo = await bundleManager.getBundleInfoForSelf(
|
||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION
|
||||
);
|
||||
const tokenId = bundleInfo.appInfo.accessTokenId;
|
||||
const grantStatus = await atManager.checkAccessToken(tokenId, permission);
|
||||
|
||||
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const result = await atManager.requestPermissionsFromUser(getContext(), [permission]);
|
||||
return result.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
|
||||
}
|
||||
```
|
||||
|
||||
## シークレット管理
|
||||
|
||||
- API キー、トークン、パスワードを `.ets`/`.ts` ソースファイルに**絶対にハードコードしない**
|
||||
- 機密性の低い設定には HarmonyOS Preferences API を使用する
|
||||
- 機密性の高い認証情報には HarmonyOS キーストアを使用する
|
||||
- 環境固有の設定はビルドプロファイルで管理する
|
||||
|
||||
```typescript
|
||||
// BAD: ハードコードされたシークレット
|
||||
const API_KEY: string = 'sk-xxxxxxxxxxxx';
|
||||
|
||||
// GOOD: ビルドプロファイル設定から取得(機密性なし)
|
||||
import { BuildProfile } from 'BuildProfile';
|
||||
const endpoint = BuildProfile.API_ENDPOINT;
|
||||
|
||||
// GOOD: HUKS を使用してキー素材を露出せずにデータを暗号化/復号化する
|
||||
import { huks } from '@kit.UniversalKeystoreKit';
|
||||
async function decryptWithKeystore(alias: string, nonce: Uint8Array, aad: Uint8Array, cipherData: Uint8Array): Promise<Uint8Array> {
|
||||
const options: huks.HuksOptions = {
|
||||
properties: [
|
||||
{ tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
|
||||
{ tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT },
|
||||
{ tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_GCM },
|
||||
{ tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksKeyPadding.HUKS_PADDING_NONE },
|
||||
{ tag: huks.HuksTag.HUKS_TAG_NONCE, value: nonce },
|
||||
{ tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, value: aad }
|
||||
],
|
||||
inData: cipherData
|
||||
};
|
||||
const handle = await huks.initSession(alias, options);
|
||||
const result = await huks.finishSession(handle.handle, options);
|
||||
return result.outData;
|
||||
}
|
||||
```
|
||||
|
||||
## 入力バリデーション
|
||||
|
||||
- 処理前にすべてのユーザー入力を検証する
|
||||
- インジェクションを防ぐため、UI に表示する前にデータをサニタイズする
|
||||
- ナビゲーション前にディープリンクのパラメータを検証する
|
||||
|
||||
```typescript
|
||||
// ナビゲーション前に検証する
|
||||
function handleDeepLink(uri: string): void {
|
||||
const allowedPaths: string[] = ['detail', 'settings', 'profile'];
|
||||
const parsed = new URL(uri);
|
||||
const path = parsed.pathname.replace('/', '');
|
||||
|
||||
if (!allowedPaths.includes(path)) {
|
||||
hilog.warn(0x0000, 'DeepLink', 'Invalid deep link path: %{public}s', path);
|
||||
return;
|
||||
}
|
||||
|
||||
navPathStack.pushPath({ name: path });
|
||||
}
|
||||
```
|
||||
|
||||
## ネットワークセキュリティ
|
||||
|
||||
- ネットワークリクエストには常に HTTPS を使用する
|
||||
- サーバー証明書を検証する
|
||||
- リクエストのタイムアウトとリトライポリシーを実装する
|
||||
- ネットワークリクエスト/レスポンスのログに機密データ(トークン、ユーザー認証情報)を記録しない
|
||||
|
||||
## データストレージセキュリティ
|
||||
|
||||
- 機密性の高いローカルデータには暗号化されたプリファレンスを使用する
|
||||
- 不要になった機密データはメモリから消去する
|
||||
- 適切なデータライフサイクル管理を実装する
|
||||
- ストレージメカニズムを選択する際にデータ分類(公開、内部、機密)を考慮する
|
||||
|
||||
## 依存関係のセキュリティ
|
||||
|
||||
- 信頼できるソース(公式 ohpm レジストリ)からの依存関係のみを使用する
|
||||
- `oh-package.json5` の依存関係バージョンを確認する
|
||||
- サードパーティライブラリの既知の脆弱性を定期的に確認する
|
||||
- 予期しない更新を避けるために依存関係バージョンを固定する
|
||||
126
docs/ja-JP/rules/arkts/testing.md
Normal file
126
docs/ja-JP/rules/arkts/testing.md
Normal file
@@ -0,0 +1,126 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.ets"
|
||||
- "**/*.ts"
|
||||
- "**/ohosTest/**"
|
||||
---
|
||||
# HarmonyOS / ArkTS テスト
|
||||
|
||||
> このファイルは [common/testing.md](../common/testing.md) を HarmonyOS 固有のテストプラクティスで拡張します。
|
||||
|
||||
## テストフレームワーク
|
||||
|
||||
HarmonyOS は `@ohos.test` 機能を持つ組み込みテストフレームワークを使用する:
|
||||
|
||||
- **ユニットテスト**: `src/ohosTest/ets/test/` に配置
|
||||
- **UI テスト**: コンポーネントテストには `@ohos.UiTest` を使用
|
||||
- **インストルメントテスト**: デバイス/エミュレーターで実行
|
||||
|
||||
## テストディレクトリ構成
|
||||
|
||||
```
|
||||
module/
|
||||
|-- src/
|
||||
| |-- main/ets/ # プロダクションコード
|
||||
| |-- ohosTest/ets/ # テストコード
|
||||
| |-- test/
|
||||
| | |-- Ability.test.ets
|
||||
| | |-- List.test.ets
|
||||
| |-- TestAbility.ets
|
||||
| |-- TestRunner.ets
|
||||
```
|
||||
|
||||
## テストの実行
|
||||
|
||||
```bash
|
||||
# モジュールのすべてのテストを実行する
|
||||
hvigorw testHap -p product=default
|
||||
|
||||
# 接続されたデバイスでテストを実行する
|
||||
hdc shell aa test -b com.example.app -m entry_test -s unittest /ets/TestRunner/OpenHarmonyTestRunner
|
||||
```
|
||||
|
||||
## ユニットテストの例
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect } from '@ohos/hypium';
|
||||
|
||||
export default function UserViewModelTest() {
|
||||
describe('UserViewModel', () => {
|
||||
it('should_initialize_with_empty_state', 0, () => {
|
||||
const vm = new UserViewModel();
|
||||
expect(vm.userName).assertEqual('');
|
||||
expect(vm.isLoading).assertFalse();
|
||||
});
|
||||
|
||||
it('should_update_user_name', 0, () => {
|
||||
const vm = new UserViewModel();
|
||||
vm.updateUserName('Alice');
|
||||
expect(vm.userName).assertEqual('Alice');
|
||||
});
|
||||
|
||||
it('should_handle_empty_input', 0, () => {
|
||||
const vm = new UserViewModel();
|
||||
vm.updateUserName('');
|
||||
expect(vm.userName).assertEqual('');
|
||||
expect(vm.hasError).assertFalse();
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## UI テストの例
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect } from '@ohos/hypium';
|
||||
import { Driver, ON } from '@ohos.UiTest';
|
||||
|
||||
export default function HomePageUITest() {
|
||||
describe('HomePage_UI', () => {
|
||||
it('should_display_title', 0, async () => {
|
||||
const driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
|
||||
const title = await driver.findComponent(ON.text('Home'));
|
||||
expect(title !== null).assertTrue();
|
||||
});
|
||||
|
||||
it('should_navigate_to_detail_on_click', 0, async () => {
|
||||
const driver = Driver.create();
|
||||
const button = await driver.findComponent(ON.id('detailButton'));
|
||||
await button.click();
|
||||
await driver.delayMs(500);
|
||||
|
||||
const detailTitle = await driver.findComponent(ON.text('Detail'));
|
||||
expect(detailTitle !== null).assertTrue();
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## HarmonyOS 向け TDD ワークフロー
|
||||
|
||||
HarmonyOS に適応した標準 TDD サイクルに従う:
|
||||
|
||||
1. **RED**: `ohosTest/ets/test/` に失敗するテストを書く
|
||||
2. **GREEN**: `main/ets/` にテストを通過するための最小限のコードを実装する
|
||||
3. **REFACTOR**: テストをグリーンに保ちながらクリーンアップする
|
||||
4. **ビルド**: `hvigorw assembleHap` を実行してコンパイルを確認する
|
||||
5. **VERIFY**: デバイス/エミュレーターでテストを実行する
|
||||
|
||||
## テストカバレッジ要件
|
||||
|
||||
- すべての重要なアプリケーションコード(ViewModels、サービス、ユーティリティ)で最低 80% のカバレッジ
|
||||
- **ユニットテスト**: すべてのユーティリティ関数、ViewModel ロジック、データモデル
|
||||
- **統合テスト**: API 呼び出し、データベース操作、クロスモジュールインタラクション
|
||||
- **E2E / UI テスト**: 重要なユーザーフロー(ログイン、ナビゲーション、データ送信)
|
||||
- エッジケースのテスト: 空のデータ、ネットワークエラー、パーミッション拒否
|
||||
|
||||
## テストのベストプラクティス
|
||||
|
||||
- テストを独立させる — テスト間で共有のミュータブルな状態を持たない
|
||||
- ユニットテストではネットワーク呼び出しとシステム API をモックする
|
||||
- 意味のあるテスト名を使用する: `should_[期待される動作]_when_[条件]`
|
||||
- V2 状態管理のリアクティビティをテストする: `@Trace` プロパティが UI 更新をトリガーすることを確認する
|
||||
- Navigation フローをテストする: `NavPathStack` のプッシュ/ポップ/置き換え操作を確認する
|
||||
- フレームワーク内部のテストは避ける — ビジネスロジックとユーザーが見える動作に集中する
|
||||
Reference in New Issue
Block a user