#!/usr/bin/env python3 import csv import json from collections import defaultdict from typing import Dict, List, Any def oracle_to_typescript_type(oracle_type: str, data_length: str, nullable: str) -> str: """Oracle 데이터 타입을 TypeScript 타입으로 변환""" oracle_type = oracle_type.upper() is_nullable = nullable.upper() == 'Y' if oracle_type == 'VARCHAR2': ts_type = 'string' elif oracle_type == 'NUMBER': ts_type = 'number' elif oracle_type.startswith('DATE') or oracle_type.endswith('_DT'): ts_type = 'string' # Oracle DATE는 보통 string으로 처리 else: ts_type = 'string' # 기본값 return f"{ts_type} | null" if is_nullable else ts_type def generate_column_object(table_name: str, columns: List[Dict[str, Any]]) -> str: """테이블의 컬럼 객체 생성 - Table.테이블명.컬럼명 형태로 사용하기 위함""" lines = [f" {table_name}: {{"] for col in columns: column_name = col['COLUMN_NAME'] comment = col['COLUMN_COMMENTS'] if comment: lines.append(f" /** {comment} */") lines.append(f" {column_name}: '{column_name}' as const,") lines.append(" },") return "\n".join(lines) def generate_table_interface(table_name: str, columns: List[Dict[str, Any]]) -> str: """테이블별 TypeScript 인터페이스 생성""" interface_name = table_name # Oracle 테이블명 그대로 사용 lines = [f"export interface {interface_name} {{"] for col in columns: column_name = col['COLUMN_NAME'] ts_type = oracle_to_typescript_type( col['DATA_TYPE'], col['DATA_LENGTH'], col['NULLABLE'] ) comment = col['COLUMN_COMMENTS'] if comment: lines.append(f" /** {comment} */") lines.append(f" {column_name}: {ts_type};") lines.append("}") return "\n".join(lines) def generate_database_schema(tables: Dict[str, List[Dict[str, Any]]]) -> str: """전체 데이터베이스 스키마 타입 생성""" lines = ["// Auto-generated Oracle DB types", ""] # 1. 각 테이블 인터페이스 생성 interfaces = [] for table_name, columns in tables.items(): interface_code = generate_table_interface(table_name, columns) lines.extend([interface_code, ""]) interfaces.append(table_name) # Oracle 테이블명 그대로 사용 # 2. Table 객체 생성 - 핵심 부분! lines.extend([ "// Table 객체 - Table.테이블명.컬럼명 형태로 사용", "export const Table = {", ]) for table_name, columns in tables.items(): column_object = generate_column_object(table_name, columns) lines.append(column_object) lines.extend(["} as const;", ""]) # 3. 기존 Database 스키마 타입도 유지 (Knex 호환성) lines.extend([ "// Database schema type for Knex", "export interface DatabaseSchema {", ]) for table_name, interface_name in zip(tables.keys(), interfaces): lines.append(f" {table_name}: {interface_name};") lines.extend(["}", ""]) # 4. TableNames 객체 생성 (키-값 형태) lines.extend([ "// Table names constants (key-value pairs)", "export const TableNames = {", ]) for table_name in tables.keys(): lines.append(f" {table_name}: '{table_name}' as const,") lines.extend(["} as const;", ""]) # 5. 테이블 목록 배열 생성 (동기화용) lines.extend([ "// Table names array for synchronization", "export const ALL_TABLE_NAMES: TableName[] = [", ]) for table_name in tables.keys(): lines.append(f" '{table_name}',") lines.extend(["] as const;", ""]) # 6. 타입 헬퍼 추가 lines.extend([ "// 타입 헬퍼", "export type TableName = keyof typeof Table;", "export type ColumnName = keyof typeof Table[T];", "export type TableRow = DatabaseSchema[T];", "" ]) return "\n".join(lines) def main(): tables: Dict[str, List[Dict[str, Any]]] = defaultdict(list) # 기본 테이블 목록 (CSV 파일이 없을 때 fallback) default_tables = [ 'CMCTB_CD', 'CMCTB_CDNM', 'CMCTB_CD_CLF', 'CMCTB_CD_CLF_NM', 'CMCTB_CUSTOMER_ADDR', 'CMCTB_CUSTOMER_CFPN', 'CMCTB_CUSTOMER_COMPNY', 'CMCTB_CUSTOMER_GENERAL', 'CMCTB_CUSTOMER_REPREMAIL', 'CMCTB_CUSTOMER_REPRFAX', 'CMCTB_CUSTOMER_REPRTEL', 'CMCTB_CUSTOMER_REPRURL', 'CMCTB_CUSTOMER_SORG', 'CMCTB_CUSTOMER_TAXCD', 'CMCTB_CUSTOMER_TAXNUM', 'CMCTB_MAT_BSE', 'CMCTB_MAT_CLAS', 'CMCTB_MAT_CLAS_SPCHAR', 'CMCTB_MAT_DSC', 'CMCTB_MAT_PLNT', 'CMCTB_MAT_SPCHAR', 'CMCTB_MAT_SPCHAR_MAST', 'CMCTB_MAT_SPCHAR_VAL', 'CMCTB_MAT_UOM', 'CMCTB_PROJ_BIZCLS', 'CMCTB_PROJ_MAST', 'CMCTB_PROJ_WBS', 'CMCTB_VENDOR_ADDR', 'CMCTB_VENDOR_COMPNY', 'CMCTB_VENDOR_GENERAL', 'CMCTB_VENDOR_GRP', 'CMCTB_VENDOR_INCO', 'CMCTB_VENDOR_PORG', 'CMCTB_VENDOR_REPREMAIL', 'CMCTB_VENDOR_REPRFAX', 'CMCTB_VENDOR_REPRTEL', 'CMCTB_VENDOR_REPRURL', 'CMCTB_VENDOR_TAXNUM', 'CMCTB_VENDOR_VFPN', 'CMCTB_VENDOR_WHTHX', 'PLFTB_ESTM_PROJ_MAST' ] try: # CSV 파일 읽기 with open('1.table-and-columns-info.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: table_name = row['TABLE_NAME'] tables[table_name].append(row) print(f"Loaded {len(tables)} tables from CSV file") except FileNotFoundError: print("CSV file not found, using default table structure") # 기본 테이블 구조 생성 for table_name in default_tables: tables[table_name] = [{ 'TABLE_NAME': table_name, 'COLUMN_NAME': 'ID', # 기본 컬럼 'DATA_TYPE': 'VARCHAR2', 'DATA_LENGTH': '10', 'NULLABLE': 'N', 'COLUMN_COMMENTS': f'{table_name} Primary Key' }] # 테이블이 없으면 기본 목록 사용 if not tables: print("No tables found, using default table list") for table_name in default_tables: tables[table_name] = [{ 'TABLE_NAME': table_name, 'COLUMN_NAME': 'ID', 'DATA_TYPE': 'VARCHAR2', 'DATA_LENGTH': '10', 'NULLABLE': 'N', 'COLUMN_COMMENTS': f'{table_name} Primary Key' }] # TypeScript 코드 생성 typescript_code = generate_database_schema(tables) # 파일 저장 with open('oracle-schema.ts', 'w', encoding='utf-8') as f: f.write(typescript_code) print(f"Generated TypeScript types for {len(tables)} tables") print("Output: oracle-schema.ts") print() print("사용법:") print(" import { Table } from './oracle-schema';") print(" const vendorCode = Table.CMCTB_VENDOR_GENERAL.VNDRCD; // 'VNDRCD'") print(" const tableName = 'CMCTB_VENDOR_GENERAL';") print(" const columnName = Table[tableName].VNDRNM_1; // 'VNDRNM_1'") if __name__ == "__main__": main()