Skip to main content
Glama
test-data.ts18.7 kB
#!/usr/bin/env node /** * テストデータを流し込むスクリプト * サーバーが起動している状態で実行してください */ import * as readline from 'readline'; // コマンドライン引数の解析 function parseArgs() { const args = process.argv.slice(2); let patternKey: string | undefined; let port = 3000; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg === '--port' || arg === '-p') { const portStr = args[i + 1]; if (portStr && !isNaN(parseInt(portStr, 10))) { port = parseInt(portStr, 10); i++; // 次の引数をスキップ } } else if (!arg.startsWith('-')) { // 数値のみの場合はポート番号として扱う const num = parseInt(arg, 10); if (!isNaN(num) && num >= 1000 && num <= 65535) { port = num; } else if (!patternKey) { // 数値以外の場合はパターン名として扱う patternKey = arg; } } } return { patternKey, port }; } const { patternKey: PATTERN_KEY, port: PORT } = parseArgs(); const API_BASE = process.env.API_BASE || `http://localhost:${PORT}/api`; interface Node { id: string; label: string; x?: number; y?: number; color?: string; solution?: string; filePath?: string; lineNumber?: number; code?: string; group?: string; } interface Edge { from: string; to: string; label?: string; } interface Group { id: string; label: string; color?: string; } interface Diagram { nodes: Node[]; edges: Edge[]; groups?: Group[]; } async function setDiagram(diagram: Diagram): Promise<void> { try { const response = await fetch(`${API_BASE}/diagram`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(diagram), }); if (!response.ok) { throw new Error(`Failed to set diagram: ${response.statusText}`); } const data = await response.json(); console.log(`✓ ダイアグラムを設定しました: ${data.nodes}個のノード、${data.edges}個のエッジ`); } catch (error) { console.error(`✗ ダイアグラム設定失敗:`, error); throw error; } } // ダイアグラムパターン1: Webアプリケーションアーキテクチャ const webAppArchitecture: Diagram = { nodes: [ { id: 'client', label: 'ブラウザ', color: '#64748b', memo: '## クライアント\n\nユーザーのWebブラウザ。\n\n### 対応ブラウザ\n- Chrome\n- Firefox\n- Safari\n- Edge' }, { id: 'cdn', label: 'CDN', color: '#0ea5e9' }, { id: 'lb', label: 'ロードバランサー', color: '#8b5cf6', memo: '## ロードバランサー\n\nトラフィックを複数のWebサーバーに分散します。\n\n```nginx\nupstream backend {\n server web1:8080;\n server web2:8080;\n}\n```' }, { id: 'web1', label: 'Webサーバー1', color: '#2563eb' }, { id: 'web2', label: 'Webサーバー2', color: '#2563eb' }, { id: 'cache', label: 'Redis Cache', color: '#dc2626', memo: '### Redis設定\n\n```bash\nredis-cli CONFIG SET maxmemory 2gb\nredis-cli CONFIG SET maxmemory-policy allkeys-lru\n```' }, { id: 'app', label: 'APIサーバー', color: '#059669', memo: '## APIサーバー\n\nビジネスロジックを処理するバックエンドサーバー。\n\n### 主な機能\n- ユーザー認証\n- データ処理\n- 外部API連携' }, { id: 'db-primary', label: 'DB (Primary)', color: '#7c3aed' }, { id: 'db-replica', label: 'DB (Replica)', color: '#9333ea' }, { id: 'queue', label: 'メッセージキュー', color: '#ea580c' }, { id: 'worker', label: 'バックグラウンドワーカー', color: '#d97706', memo: '## バックグラウンドワーカー\n\n非同期タスクを処理します。\n\n- メール送信\n- レポート生成\n- データ集計' }, ], edges: [ { from: 'client', to: 'cdn', label: 'HTTPS' }, { from: 'client', to: 'lb', label: 'HTTPS' }, { from: 'lb', to: 'web1', label: 'HTTP' }, { from: 'lb', to: 'web2', label: 'HTTP' }, { from: 'web1', to: 'cache', label: 'Cache' }, { from: 'web2', to: 'cache', label: 'Cache' }, { from: 'web1', to: 'app', label: 'REST API' }, { from: 'web2', to: 'app', label: 'REST API' }, { from: 'app', to: 'db-primary', label: 'SQL (Write)' }, { from: 'app', to: 'db-replica', label: 'SQL (Read)' }, { from: 'db-primary', to: 'db-replica', label: 'Replication' }, { from: 'app', to: 'queue', label: 'Publish' }, { from: 'queue', to: 'worker', label: 'Subscribe' }, { from: 'worker', to: 'db-primary', label: 'SQL' }, ], }; // ダイアグラムパターン2: マイクロサービスアーキテクチャ const microservicesArchitecture: Diagram = { groups: [ { id: 'core', label: 'コアサービス', color: '#dbeafe' }, { id: 'business', label: 'ビジネスロジック', color: '#dcfce7' }, { id: 'infrastructure', label: 'インフラ', color: '#fef3c7' }, ], nodes: [ { id: 'gateway', label: 'API Gateway', color: '#0891b2', group: 'infrastructure', memo: '## API Gateway\n\nすべてのクライアントリクエストの入口。\n\n### 機能\n- ルーティング\n- 認証・認可\n- レート制限\n- リクエスト/レスポンス変換' }, { id: 'auth', label: '認証サービス', color: '#dc2626', group: 'core', memo: '## 認証サービス\n\nJWT発行と検証を担当。\n\n```typescript\nconst token = jwt.sign({ userId }, SECRET, { expiresIn: "24h" });\n```' }, { id: 'user', label: 'ユーザーサービス', color: '#2563eb', group: 'core' }, { id: 'order', label: '注文サービス', color: '#059669', group: 'business', memo: '## 注文サービス\n\n注文処理のコアロジック。\n\n1. 注文検証\n2. 在庫確認\n3. 決済処理\n4. 注文確定' }, { id: 'payment', label: '決済サービス', color: '#7c3aed', group: 'business' }, { id: 'inventory', label: '在庫サービス', color: '#d97706', group: 'business' }, { id: 'notification', label: '通知サービス', color: '#ea580c', group: 'core' }, { id: 'eventbus', label: 'イベントバス', color: '#4b5563', group: 'infrastructure', memo: '## イベントバス\n\nサービス間の非同期通信を実現。\n\n### 使用技術\n- Apache Kafka\n- RabbitMQ\n- AWS EventBridge' }, { id: 'service-mesh', label: 'サービスメッシュ', color: '#6366f1', group: 'infrastructure' }, ], edges: [ { from: 'gateway', to: 'auth', label: 'JWT検証' }, { from: 'gateway', to: 'user', label: 'REST' }, { from: 'gateway', to: 'order', label: 'REST' }, { from: 'order', to: 'payment', label: 'gRPC' }, { from: 'order', to: 'inventory', label: 'gRPC' }, { from: 'payment', to: 'eventbus', label: 'Publish' }, { from: 'order', to: 'eventbus', label: 'Publish' }, { from: 'eventbus', to: 'notification', label: 'Subscribe' }, { from: 'service-mesh', to: 'user', label: 'トラフィック管理' }, { from: 'service-mesh', to: 'order', label: 'トラフィック管理' }, { from: 'service-mesh', to: 'payment', label: 'トラフィック管理' }, ], }; // ダイアグラムパターン3: データパイプライン const dataPipeline: Diagram = { nodes: [ { id: 'source1', label: 'データソース1 (API)' }, { id: 'source2', label: 'データソース2 (DB)' }, { id: 'source3', label: 'データソース3 (ファイル)' }, { id: 'ingestion', label: 'データ取込' }, { id: 'raw', label: 'Raw Data Lake' }, { id: 'transform', label: 'ETL処理' }, { id: 'warehouse', label: 'Data Warehouse' }, { id: 'ml', label: '機械学習モデル' }, { id: 'analytics', label: '分析ツール' }, { id: 'dashboard', label: 'ダッシュボード' }, ], edges: [ { from: 'source1', to: 'ingestion', label: 'REST API' }, { from: 'source2', to: 'ingestion', label: 'CDC' }, { from: 'source3', to: 'ingestion', label: 'S3' }, { from: 'ingestion', to: 'raw', label: 'Batch' }, { from: 'raw', to: 'transform', label: 'Spark Job' }, { from: 'transform', to: 'warehouse', label: 'Load' }, { from: 'warehouse', to: 'ml', label: 'Training Data' }, { from: 'warehouse', to: 'analytics', label: 'Query' }, { from: 'analytics', to: 'dashboard', label: 'Visualization' }, { from: 'ml', to: 'dashboard', label: '予測結果' }, ], }; // ダイアグラムパターン4: CI/CDパイプライン const cicdPipeline: Diagram = { nodes: [ { id: 'git', label: 'Git Repository' }, { id: 'ci', label: 'CI Server' }, { id: 'build', label: 'ビルド' }, { id: 'test', label: 'テスト実行' }, { id: 'scan', label: 'セキュリティスキャン' }, { id: 'artifact', label: 'アーティファクトリポジトリ' }, { id: 'staging', label: 'ステージング環境' }, { id: 'approval', label: '承認プロセス' }, { id: 'production', label: '本番環境' }, { id: 'monitoring', label: 'モニタリング' }, ], edges: [ { from: 'git', to: 'ci', label: 'Webhook' }, { from: 'ci', to: 'build', label: 'Trigger' }, { from: 'build', to: 'test', label: 'Artifact' }, { from: 'test', to: 'scan', label: 'Success' }, { from: 'scan', to: 'artifact', label: 'Upload' }, { from: 'artifact', to: 'staging', label: 'Deploy' }, { from: 'staging', to: 'approval', label: 'テスト完了' }, { from: 'approval', to: 'production', label: 'Deploy' }, { from: 'production', to: 'monitoring', label: 'Metrics' }, { from: 'monitoring', to: 'git', label: 'Alert → Issue' }, ], }; // ダイアグラムパターン5: クラウドインフラストラクチャ const cloudInfrastructure: Diagram = { nodes: [ { id: 'internet', label: 'インターネット' }, { id: 'cloudflare', label: 'Cloudflare' }, { id: 'alb', label: 'ALB' }, { id: 'ecs1', label: 'ECSタスク1' }, { id: 'ecs2', label: 'ECSタスク2' }, { id: 's3', label: 'S3バケット' }, { id: 'rds', label: 'RDS (PostgreSQL)' }, { id: 'elasticache', label: 'ElastiCache' }, { id: 'lambda', label: 'Lambda関数' }, { id: 'sqs', label: 'SQSキュー' }, { id: 'cloudwatch', label: 'CloudWatch' }, ], edges: [ { from: 'internet', to: 'cloudflare', label: 'HTTPS' }, { from: 'cloudflare', to: 'alb', label: 'HTTPS' }, { from: 'alb', to: 'ecs1', label: 'HTTP' }, { from: 'alb', to: 'ecs2', label: 'HTTP' }, { from: 'ecs1', to: 'rds', label: 'SQL' }, { from: 'ecs2', to: 'rds', label: 'SQL' }, { from: 'ecs1', to: 'elasticache', label: 'Redis' }, { from: 'ecs1', to: 's3', label: 'S3 API' }, { from: 'ecs1', to: 'sqs', label: 'SendMessage' }, { from: 'sqs', to: 'lambda', label: 'Trigger' }, { from: 'lambda', to: 'rds', label: 'SQL' }, { from: 'cloudwatch', to: 'ecs1', label: 'ログ収集' }, { from: 'cloudwatch', to: 'lambda', label: 'ログ収集' }, ], }; // ダイアグラムパターン6: シンプルな3層アーキテクチャ const simpleThreeTier: Diagram = { nodes: [ { id: 'browser', label: 'Webブラウザ', color: '#64748b', }, { id: 'frontend', label: 'フロントエンド (React)', color: '#2563eb', solution: 'MyApp', filePath: 'src/frontend/App.tsx', lineNumber: 15, code: `function App() { const [data, setData] = useState([]); useEffect(() => { fetch("/api/data") .then(res => res.json()) .then(setData); }, []); return <Dashboard data={data} />; }` }, { id: 'backend', label: 'バックエンド (Node.js)', color: '#059669', solution: 'MyApp', filePath: 'src/backend/api.ts', lineNumber: 42, code: `app.get('/api/data', async (req, res) => { const data = await db.query( 'SELECT * FROM users' ); res.json(data); });` }, { id: 'database', label: 'データベース (MySQL)', color: '#dc2626', solution: 'MyApp', filePath: 'db/schema.sql', lineNumber: 1, code: `CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );` }, ], edges: [ { from: 'browser', to: 'frontend', label: 'HTTPS' }, { from: 'frontend', to: 'backend', label: 'REST API' }, { from: 'backend', to: 'database', label: 'SQL' }, ], }; // ダイアグラムパターン7: Forest(複数の独立したtree) const forestExample: Diagram = { nodes: [ // Tree 1: ユーザー管理システム { id: 'user-api', label: 'User API', color: '#2563eb' }, { id: 'user-db', label: 'User DB', color: '#1e40af' }, { id: 'auth', label: '認証', color: '#3b82f6' }, // Tree 2: 商品管理システム { id: 'product-api', label: 'Product API', color: '#059669' }, { id: 'product-db', label: 'Product DB', color: '#047857' }, { id: 'inventory', label: '在庫管理', color: '#10b981' }, { id: 'catalog', label: 'カタログ', color: '#34d399' }, // Tree 3: 注文システム { id: 'order-api', label: 'Order API', color: '#dc2626' }, { id: 'order-db', label: 'Order DB', color: '#b91c1c' }, { id: 'payment', label: '決済', color: '#ef4444' }, // Tree 4: 通知システム { id: 'notification', label: '通知サービス', color: '#7c3aed' }, { id: 'email', label: 'Email', color: '#6d28d9' }, { id: 'sms', label: 'SMS', color: '#8b5cf6' }, ], edges: [ // Tree 1の接続 { from: 'user-api', to: 'user-db', label: 'Query' }, { from: 'user-api', to: 'auth', label: 'Verify' }, // Tree 2の接続 { from: 'product-api', to: 'product-db', label: 'Query' }, { from: 'product-api', to: 'inventory', label: 'Check' }, { from: 'product-api', to: 'catalog', label: 'List' }, // Tree 3の接続 { from: 'order-api', to: 'order-db', label: 'Store' }, { from: 'order-api', to: 'payment', label: 'Process' }, // Tree 4の接続 { from: 'notification', to: 'email', label: 'Send' }, { from: 'notification', to: 'sms', label: 'Send' }, ], }; // 全パターンの定義 const patterns: Record<string, { name: string; diagram: Diagram }> = { 'webapp': { name: 'Webアプリケーションアーキテクチャ', diagram: webAppArchitecture }, 'microservices': { name: 'マイクロサービスアーキテクチャ', diagram: microservicesArchitecture }, 'datapipeline': { name: 'データパイプライン', diagram: dataPipeline }, 'cicd': { name: 'CI/CDパイプライン', diagram: cicdPipeline }, 'cloud': { name: 'クラウドインフラストラクチャ', diagram: cloudInfrastructure }, 'simple': { name: 'シンプルな3層アーキテクチャ', diagram: simpleThreeTier }, 'forest': { name: 'Forest(複数の独立したTree)', diagram: forestExample }, }; // Enterキーの入力を待つ関数 function waitForEnter(message: string): Promise<void> { return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question(message, () => { rl.close(); resolve(); }); }); } async function main() { console.log('=== ネットワークダイアグラム テストデータ投入 ===\n'); console.log(`接続先: ${API_BASE}\n`); // サーバーが起動しているか確認 try { const healthResponse = await fetch(`${API_BASE}/health`); if (!healthResponse.ok) { throw new Error('Server is not responding'); } console.log('✓ サーバー接続確認\n'); } catch (error) { console.error('✗ サーバーに接続できません。先にサーバーを起動してください。'); console.error(' 起動コマンド: npm start\n'); process.exit(1); } // 特定のパターンが指定された場合は、そのパターンのみ表示 if (PATTERN_KEY && patterns[PATTERN_KEY]) { const pattern = patterns[PATTERN_KEY]; console.log(`--- ${pattern.name} ---\n`); await setDiagram(pattern.diagram); console.log('\n=== 完了 ==='); console.log(`\nWebインターフェースで確認: http://localhost:${PORT}`); console.log(`APIで確認: curl http://localhost:${PORT}/api/diagram\n`); return; } // パターンが指定されていない場合は対話モード if (!PATTERN_KEY) { console.log('対話モード: Enterキーで次のパターンに切り替わります'); console.log('終了するには Ctrl+C を押してください\n'); const patternEntries = Object.entries(patterns); let currentIndex = 0; while (true) { const [key, pattern] = patternEntries[currentIndex]; console.log(`\n[${ currentIndex + 1}/${patternEntries.length}] --- ${pattern.name} ---\n`); await setDiagram(pattern.diagram); currentIndex = (currentIndex + 1) % patternEntries.length; if (currentIndex === 0) { await waitForEnter('\nEnterキーで最初から繰り返す (Ctrl+Cで終了): '); } else { await waitForEnter('\nEnterキーで次のパターンへ (Ctrl+Cで終了): '); } } } // 不明なパターンの場合 console.error(`✗ 不明なパターン: ${PATTERN_KEY}\n`); console.log('利用可能なパターン:'); Object.entries(patterns).forEach(([key, pattern]) => { console.log(` ${key.padEnd(15)} - ${pattern.name}`); }); console.log('\n使用例:'); console.log(' npm run test-data # 対話モード(Enterで切り替え)'); console.log(' npm run test-data webapp # Webアプリケーション'); console.log(' npm run test-data microservices # マイクロサービス'); console.log(' npm run test-data simple # シンプルな3層'); console.log(' npm run test-data microservices 3001 # ポート3001を指定(簡潔形式)'); console.log(' npm run test-data -- simple --port 3001 # ポート3001を指定(明示形式)'); console.log(' npm run test-data -- webapp -p 3002 # ポート3002を指定(短縮形)'); process.exit(1); } main().catch(error => { console.error('エラーが発生しました:', error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fogrexon/network-diagram-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server