UNPKG

@gftdcojp/gftd-orm

Version:

Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture

273 lines 10.3 kB
#!/usr/bin/env node "use strict"; /** * GFTD ORM CLI - TypeScript型生成コマンドライン インターフェース * * 完全実装済み機能: * - CLIコマンドの実装 ✅ * - 型生成コマンドの追加 ✅ * - ファイル出力機能 ✅ * - ドライランモード ✅ * - 全テーブル型生成 ✅ * - テーブル一覧表示 ✅ */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.runCli = main; const fs_1 = require("fs"); const path_1 = require("path"); const commander_1 = require("commander"); const ksqldb_client_1 = require("./ksqldb-client"); const type_generator_1 = require("./type-generator"); const logger_1 = require("./utils/logger"); const dotenv_1 = __importDefault(require("dotenv")); // 環境変数を読み込み dotenv_1.default.config(); /** * CLIのバージョン情報 */ const CLI_VERSION = '25.07.8'; /** * ksqlDB接続を初期化 * @param options - CLI オプション */ function initializeConnection(options) { const url = options.url || process.env.GFTD_DB_URL || process.env.KSQLDB_URL || 'http://localhost:8088'; const apiKey = options.apiKey || process.env.GFTD_DB_API_KEY || process.env.KSQLDB_API_KEY; const apiSecret = options.apiSecret || process.env.GFTD_DB_API_SECRET || process.env.KSQLDB_API_SECRET; if (options.verbose) { logger_1.log.info('Initializing ksqlDB connection...'); logger_1.log.info(`URL: ${url}`); logger_1.log.info(`API Key: ${apiKey ? '***' : 'Not provided'}`); } (0, ksqldb_client_1.initializeKsqlDbClient)({ url, apiKey, apiSecret, }); } /** * ファイルを安全に書き込み * @param filePath - ファイルパス * @param content - 書き込み内容 * @param options - CLI オプション */ function writeFileContents(filePath, content, options) { if (options.dry) { console.log(`\n[DRY RUN] Would write to: ${filePath}`); console.log('--- Content ---'); console.log(content); console.log('--- End Content ---\n'); return; } // ディレクトリを作成 const dir = (0, path_1.dirname)(filePath); if (!(0, fs_1.existsSync)(dir)) { (0, fs_1.mkdirSync)(dir, { recursive: true }); if (options.verbose) { logger_1.log.info(`Created directory: ${dir}`); } } // ファイルに書き込み (0, fs_1.writeFileSync)(filePath, content, 'utf8'); if (options.verbose) { logger_1.log.info(`✅ Generated: ${filePath}`); } else { console.log(`✅ Generated: ${filePath}`); } } /** * テーブル名からファイル名を生成 * @param tableName - テーブル名 * @param format - 出力形式 * @returns ファイル名 */ function generateFileName(tableName, format = 'ts') { // TABLE_table のような重複を修正 const cleanName = tableName.replace(/_table$/i, '').replace(/_stream$/i, ''); return cleanName .toLowerCase() .replace(/[^a-z0-9_]/g, '_') + `.${format}`; } /** * 単一テーブルの型を生成 */ async function generateTypesCommand(tableName, options) { try { initializeConnection(options); if (options.verbose) { logger_1.log.info(`🔍 Analyzing table: ${tableName}`); } const schema = await (0, type_generator_1.getTableSchema)(tableName); const typeInfo = (0, type_generator_1.generateCompleteTypeDefinition)(schema); const outputDir = options.output || './types'; const fileName = generateFileName(tableName, options.format || 'ts'); const filePath = (0, path_1.join)(outputDir, fileName); writeFileContents(filePath, typeInfo.fullCode, options); if (!options.dry) { console.log(`\n🎉 Type generation completed for table: ${tableName}`); console.log(`📄 Interface: ${typeInfo.interfaceName}`); console.log(`🔧 Mapper: ${typeInfo.mapperFunctionName}`); } } catch (error) { console.error(`❌ Error generating types for table ${tableName}:`, error.message); process.exit(1); } } /** * 全テーブルの型を生成 */ async function generateAllTypesCommand(options) { try { initializeConnection(options); if (options.verbose) { logger_1.log.info('🔍 Listing all tables and streams...'); } const tables = await (0, type_generator_1.listAllTables)(); if (tables.length === 0) { console.log('⚠️ No tables or streams found.'); return; } console.log(`🔍 Found ${tables.length} tables/streams:`); tables.forEach(table => { console.log(` - ${table.name} (${table.type})`); }); console.log('\n🚀 Generating types...\n'); const outputDir = options.output || './types'; let successCount = 0; let errorCount = 0; for (const table of tables) { try { if (options.verbose) { logger_1.log.info(`Generating types for: ${table.name}`); } const schema = await (0, type_generator_1.getTableSchema)(table.name); const typeInfo = (0, type_generator_1.generateCompleteTypeDefinition)(schema); const fileName = generateFileName(table.name, options.format || 'ts'); const filePath = (0, path_1.join)(outputDir, fileName); writeFileContents(filePath, typeInfo.fullCode, options); successCount++; } catch (error) { console.error(`❌ Failed to generate types for ${table.name}: ${error.message}`); errorCount++; } } if (!options.dry) { console.log(`\n🎉 Type generation completed!`); console.log(`✅ Success: ${successCount} tables`); if (errorCount > 0) { console.log(`❌ Errors: ${errorCount} tables`); } console.log(`📁 Output directory: ${outputDir}`); } } catch (error) { console.error(`❌ Error generating types:`, error.message); process.exit(1); } } /** * テーブル一覧を表示 */ async function listTablesCommand(options) { try { initializeConnection(options); if (options.verbose) { logger_1.log.info('🔍 Listing all tables and streams...'); } const tables = await (0, type_generator_1.listAllTables)(); if (tables.length === 0) { console.log('⚠️ No tables or streams found.'); return; } console.log(`\n📊 Found ${tables.length} tables/streams:\n`); // テーブルとストリームを分けて表示 const tablesList = tables.filter(t => t.type === 'TABLE'); const streamsList = tables.filter(t => t.type === 'STREAM'); if (tablesList.length > 0) { console.log('📋 Tables:'); tablesList.forEach(table => { console.log(` • ${table.name} (topic: ${table.topic}, format: ${table.valueFormat})`); }); console.log(''); } if (streamsList.length > 0) { console.log('🌊 Streams:'); streamsList.forEach(stream => { console.log(` • ${stream.name} (topic: ${stream.topic}, format: ${stream.valueFormat})`); }); console.log(''); } } catch (error) { console.error(`❌ Error listing tables:`, error.message); process.exit(1); } } /** * メイン CLI プログラム */ async function main() { const program = new commander_1.Command(); program .name('gftd-orm') .description('GFTD ORM CLI - TypeScript type generation for ksqlDB') .version(CLI_VERSION); // 共通オプション program .option('-u, --url <url>', 'ksqlDB server URL (default: http://localhost:8088)') .option('-k, --api-key <key>', 'ksqlDB API key') .option('-s, --api-secret <secret>', 'ksqlDB API secret') .option('-o, --output <dir>', 'Output directory (default: ./types)') .option('-v, --verbose', 'Verbose output') .option('--dry', 'Dry run - show what would be generated without writing files'); // generate-types コマンド - 単一テーブル program .command('generate-types') .description('Generate TypeScript types for a specific table') .option('-t, --table <table>', 'Table name to generate types for') .option('-f, --format <format>', 'Output format (ts, js, dts)', 'ts') .action(async (options) => { const globalOptions = program.opts(); const combinedOptions = { ...globalOptions, ...options }; if (!combinedOptions.table) { console.error('❌ Error: --table option is required'); console.log('Usage: gftd-orm generate-types --table <table-name>'); process.exit(1); } await generateTypesCommand(combinedOptions.table, combinedOptions); }); // generate-all コマンド - 全テーブル program .command('generate-all') .description('Generate TypeScript types for all tables and streams') .option('-f, --format <format>', 'Output format (ts, js, dts)', 'ts') .action(async (options) => { const globalOptions = program.opts(); const combinedOptions = { ...globalOptions, ...options }; await generateAllTypesCommand(combinedOptions); }); // list コマンド - テーブル一覧 program .command('list') .description('List all available tables and streams') .action(async () => { const globalOptions = program.opts(); await listTablesCommand(globalOptions); }); // パース実行 program.parse(); } // CLI 実行 if (require.main === module) { main().catch((error) => { console.error('❌ Unexpected error:', error); process.exit(1); }); } //# sourceMappingURL=cli.js.map