JA Architecture Module Structure - aku11i/phantom GitHub Wiki
English | 日本語
このドキュメントでは、Phantomのコード編成、モジュール依存関係、アーキテクチャ境界について詳しく説明します。
ソース: CLAUDE.md#L17-L42
phantom/
├── src/ # ソースコードルート
│ ├── bin/ # エントリーポイント
│ │ └── phantom.ts # メインCLI実行可能ファイル
│ ├── cli/ # CLI固有のレイヤー
│ │ ├── handlers/ # コマンド実装
│ │ ├── output.ts # コンソールフォーマット
│ │ └── errors.ts # エラーハンドリング
│ └── core/ # ビジネスロジックレイヤー
│ ├── worktree/ # Worktree操作
│ ├── git/ # Git抽象化
│ ├── process/ # プロセス実行
│ ├── paths.ts # パス管理
│ ├── version.ts # バージョン情報
│ └── types/ # 型定義
├── dist/ # ビルド出力
├── docs/ # ドキュメント
└── wiki/ # GitHub Wikiコンテンツ
graph TB
subgraph "エントリーレイヤー"
bin[bin/phantom.ts]
end
subgraph "CLIレイヤー"
handlers[cli/handlers/*]
output[cli/output.ts]
errors[cli/errors.ts]
end
subgraph "コアレイヤー - ドメイン"
worktree[core/worktree/*]
version[core/version.ts]
paths[core/paths.ts]
end
subgraph "コアレイヤー - インフラストラクチャ"
git[core/git/*]
process[core/process/*]
types[core/types/*]
end
bin --> handlers
handlers --> output
handlers --> errors
handlers --> worktree
handlers --> process
handlers --> version
worktree --> git
worktree --> paths
worktree --> types
process --> types
git --> types
paths --> types
classDef entry fill:#f9f,stroke:#333,stroke-width:2px
classDef cli fill:#9ff,stroke:#333,stroke-width:2px
classDef domain fill:#ff9,stroke:#333,stroke-width:2px
classDef infra fill:#9f9,stroke:#333,stroke-width:2px
class bin entry
class handlers,output,errors cli
class worktree,version,paths domain
class git,process,types infra
目的: アプリケーションエントリーポイント
ファイル:
-
phantom.ts
- メインCLIエントリーポイント
責任:
- アプリケーションのブートストラップ
- コマンドライン引数の解析
- 適切なハンドラーへのルーティング
- キャッチされていないエラーの処理
依存関係:
- CLIレイヤーからのみインポート
- 直接のコアインポートなし
目的: ユーザーインターフェースとインタラクション
ソース: src/cli/handlers/
ファイル:
-
create.ts
- phantom作成コマンド -
delete.ts
- phantom削除コマンド -
list.ts
- phantomリスト表示コマンド -
exec.ts
- phantom内でコマンド実行 -
shell.ts
- インタラクティブシェルコマンド -
where.ts
- phantomパス取得コマンド -
version.ts
- バージョン表示コマンド -
attach.ts
- 既存worktreeをアタッチ
責任:
- コア操作のオーケストレート
- ユーザー入力の検証処理
- 出力メッセージのフォーマット
- 終了コードの管理
ソース: src/cli/output.ts
責任:
- コンソール出力フォーマット
- テーブルレンダリング
- カラー管理
- 進行状況インジケーター
主要関数:
-
formatTable()
- データをテーブルとしてレンダリング -
formatError()
- エラーメッセージのフォーマット -
formatSuccess()
- 成功メッセージのフォーマット
ソース: src/cli/errors.ts
責任:
- エラーを終了コードにマップ
- エラーメッセージのフォーマット
- 予期しないエラーの処理
目的: ビジネスロジックとドメイン操作
ソース: src/core/worktree/
ファイル:
-
create.ts
- Worktree作成ロジック -
delete.ts
- Worktree削除ロジック -
list.ts
- Worktreeリスト表示ロジック -
where.ts
- Worktree位置特定ロジック -
attach.ts
- 既存worktreeをアタッチ -
validate.ts
- 名前検証 -
errors.ts
- ドメイン固有のエラー
コア型:
interface WorktreeInfo {
name: string;
path: string;
branch: string;
isMain: boolean;
}
依存関係:
- 操作にGitモジュールを使用
- 場所にPathsモジュールを使用
- Result型を返す
ソース: src/core/git/
構造:
git/
├── executor.ts # メインGitコマンドエグゼキューター
└── libs/ # Git操作ラッパー
├── add-worktree.ts
├── attach-worktree.ts
├── branch-exists.ts
├── get-current-branch.ts
├── get-git-root.ts
└── list-worktrees.ts
Gitエグゼキューター:
class GitExecutor {
execute(args: string[]): Result<string>;
executeJson<T>(args: string[]): Result<T>;
}
Gitライブラリ: 各ライブラリは特定のGit操作をラップします:
-
addWorktree()
- 新しいworktreeを作成 -
getCurrentBranch()
- アクティブブランチを取得 -
getGitRoot()
- リポジトリルートを検索 -
listWorktrees()
- すべてのworktreeをリスト表示
ソース: src/core/process/
ファイル:
-
spawn.ts
- コアプロセス生成 -
exec.ts
- コマンド実行 -
shell.ts
- インタラクティブシェル -
errors.ts
- プロセスエラー
主要型:
interface SpawnOptions {
cwd?: string;
env?: Record<string, string>;
stdio?: StdioOptions;
}
責任:
- 安全なプロセス生成
- I/Oストリーム管理
- シグナル処理
- エラー伝播
ソース: src/core/paths.ts
関数:
-
getWorktreeBasePath()
- phantomのベースディレクトリ -
getWorktreePath()
- phantomへのフルパス -
ensureWorktreeDirectory()
- ディレクトリを作成
パス構造:
/tmp/phantom/
└── <repo-name>/
├── <phantom-1>/
├── <phantom-2>/
└── <phantom-3>/
ソース: src/core/types/
ファイル:
-
result.ts
- Result型実装
Result型:
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E }
namespace Result {
function ok<T>(value: T): Result<T>;
function error<E>(error: E): Result<never, E>;
}
sequenceDiagram
participant CLI
participant Handler
participant Core
participant Git
CLI->>Handler: コマンド + 引数
Handler->>Core: ビジネス操作
Core->>Git: Gitコマンド
Git-->>Core: Result<Data>
Core-->>Handler: Result<DomainObject>
Handler->>CLI: 出力をフォーマット
graph LR
A[Gitエラー] --> B[Result.error]
B --> C[コアレイヤー]
C --> D[ドメインエラー]
D --> E[ハンドラー]
E --> F[ユーザーメッセージ]
style A fill:#f99
style F fill:#9f9
各レイヤーはデータを適切に変換します:
- Gitレイヤー: 生の文字列 → 解析されたデータ
- コアレイヤー: 解析されたデータ → ドメインオブジェクト
- CLIレイヤー: ドメインオブジェクト → ユーザー出力
- 下向きのみ: 上位レイヤーは下位レイヤーに依存
- 上向きなし: コアはCLIからインポートしない
- 循環なし: 構造により強制
各モジュールは明確なインターフェースを公開します:
// 良い: 明確なモジュールインターフェース
export function createWorktree(
name: string,
branch?: string
): Result<WorktreeInfo>
// 悪い: 内部を公開
export function executeGitCommand(
args: string[]
): ChildProcess // Node.js型を公開しない
- コアレイヤーのドメイン型
- CLIレイヤーにとどまるCLI型
-
types/
モジュールの共有型
テストファイルはソースと同じ場所に配置されます:
src/
├── core/
│ ├── worktree/
│ │ ├── create.ts
│ │ ├── create.test.ts # ユニットテスト
│ │ ├── delete.ts
│ │ └── delete.test.ts
│ └── git/
│ ├── executor.ts
│ └── executor.test.ts
テストパターン:
- 外部依存関係をモック
- 純粋関数を直接テスト
- ワークフローの統合テスト
モジュール | 責任 | 責任ではない |
---|---|---|
CLIハンドラー | ユーザーインタラクション | ビジネスロジック |
Core Worktree | Phantomライフサイクル | Gitコマンド |
Gitモジュール | Git実行 | ビジネスルール |
Processモジュール | プロセス生成 | コマンドロジック |
Typesモジュール | 共有型 | 実装 |
良い - 単一責任:
// validate.ts - 検証のみ
export function validateWorktreeName(name: string): Result<void>
// create.ts - 作成のみ
export function createWorktree(name: string): Result<WorktreeInfo>
悪い - 複数の責任:
// 関心事を混在させない
export function createAndValidateWorktree(
name: string,
showOutput: boolean // コアにUIの関心事!
): Result<WorktreeInfo>
// 1. Node.js組み込み
import { spawn } from "node:child_process";
import { existsSync } from "node:fs";
// 2. 外部依存関係(ランタイムにはなし)
// 3. 内部 - 絶対パス
import { Result } from "../types/result.js";
// 4. 内部 - 相対パス
import { validateWorktreeName } from "./validate.js";
バレルエクスポート(index.ts)を避ける理由:
- インポートを明示的に保つ
- ツリーシェイキングを改善
- 循環依存を減らす
常に.js
拡張子を含める:
// 正しい - ESMは拡張子を必要とする
import { createWorktree } from "./create.js";
// 間違い - ランタイムで失敗する
import { createWorktree } from "./create";
-
Configモジュール
- ユーザー設定
- リポジトリ設定
- デフォルト値
-
Pluginモジュール
- プラグインローディング
- フック管理
- APIサーフェス
-
Telemetryモジュール
- 使用状況メトリクス
- パフォーマンストラッキング
- エラーレポート
新しいモジュールを追加する際:
- 単一目的: 明確な責任が1つ
- 明確なインターフェース: 明確に定義されたパブリックAPI
- テスト可能: 可能な限り純粋関数
- 文書化: 明確なモジュールドキュメント
- 一貫性: 既存のパターンに従う
Phantomのモジュール構造は以下を提供します:
- 明確な境界: 明確に定義されたレイヤーと責任
- 保守性: コードの検索と変更が簡単
- テスト可能性: 明確なインターフェースを持つ分離されたモジュール
- スケーラビリティ: 新機能が自然に適合
- 型安全性: 全体を通じた強い型付け
モジュラーアーキテクチャにより、プロジェクトが成長してもコードベースがクリーンで理解しやすく、拡張可能なままであることが保証されます。