#!/bin/bash # 只更新 @DriftDatabase(tables: [...]), imports 和 getTableRegistry # 其余内容保持不变 APP_DATABASE="apps/im_app/lib/data/local/drift/app_database.dart" # ── 扫描表类 ──────────────────────────────────────────────────────────────── TABLE_CLASSES=() DATA_CLASSES=() GETTERS=() IMPORTS=() # 项目根目录(脚本所在目录的上一层) ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" # app_database.dart 所在目录(用于计算相对 import 路径) APP_DATABASE_DIR="$(dirname "$ROOT_DIR/$APP_DATABASE")" echo "🔍 扫描所有包中的 drift 表文件..." echo " 根目录: $ROOT_DIR" echo " app_database 目录: $APP_DATABASE_DIR" # 搜索所有包中的 lib/data/local/drift/tables 目录下的 dart 文件 while IFS= read -r FILE; do echo " 📄 $FILE" # 提取继承 Table 或 View 的类名 while IFS= read -r LINE; do CLASS=$(echo "$LINE" | sed -E "s/.*class ([A-Za-z0-9]+) extends (Table|View).*/\1/") if [ -z "$CLASS" ]; then continue fi TABLE_CLASSES+=("$CLASS") # 提取 @DataClassName 注解 DATA_CLASS=$(grep -E "@DataClassName\('([^']+)'\)" "$FILE" | sed -E "s/.*@DataClassName\('([^']+)'\).*/\1/" | head -1) if [ -z "$DATA_CLASS" ]; then # 无注解时去掉末尾 's' 推断数据类名 DATA_CLASS="${CLASS%s}" fi DATA_CLASSES+=("$DATA_CLASS") # getter 名 = 表类名首字母小写(跟 drift 生成一致) GETTER=$(echo "$CLASS" | awk '{print tolower(substr($0,1,1)) substr($0,2)}') GETTERS+=("$GETTER") # 计算 package: import 路径(找到 pubspec.yaml 确定 package 名) PKG_IMPORT=$(python3 -c " import os, re file_path = '$FILE' search = os.path.dirname(file_path) pkg_name = None pkg_root = None while search != '/': pubspec = os.path.join(search, 'pubspec.yaml') if os.path.exists(pubspec): with open(pubspec) as f: for line in f: m = re.match(r'^name:\s*(\S+)', line) if m: pkg_name = m.group(1) pkg_root = search break break search = os.path.dirname(search) if pkg_name and pkg_root: lib_path = os.path.join(pkg_root, 'lib') rel = os.path.relpath(file_path, lib_path) print(f'package:{pkg_name}/{rel}') else: db_dir = '$APP_DATABASE_DIR' print(os.path.relpath(file_path, db_dir)) ") IMPORTS+=("$PKG_IMPORT") echo " ✅ 表类: $CLASS → 数据类: $DATA_CLASS → getter: $GETTER" echo " 📦 import: $PKG_IMPORT" done < <(grep -E "^class [A-Za-z0-9]+ extends (Table|View)" "$FILE") done < <(find "$ROOT_DIR" \ -type f \ -name "*.dart" \ -path "*/lib/data/local/drift/tables/*" \ ! -path "*/build/*" \ ! -path "*/.dart_tool/*" \ ! -path "*/.*") if [ ${#TABLE_CLASSES[@]} -eq 0 ]; then echo "❌ 未找到任何 drift 表类,请检查搜索路径。" exit 1 fi echo "" echo "✅ 共找到 ${#TABLE_CLASSES[@]} 个表类:" for i in "${!TABLE_CLASSES[@]}"; do echo " [${TABLE_CLASSES[$i]}] → [${DATA_CLASSES[$i]}] → getter: ${GETTERS[$i]} → ${IMPORTS[$i]}" done TABLES_LIST=$(IFS=', '; echo "${TABLE_CLASSES[*]}") echo "" echo "📋 @DriftDatabase(tables: [$TABLES_LIST])" # ── 用 sed 替换 @DriftDatabase(tables: [...]) ────────────────────────────── echo "" echo "✍️ 更新 @DriftDatabase..." sed -i '' "s/@DriftDatabase(tables: \[.*\])/@DriftDatabase(tables: [$TABLES_LIST])/" "$ROOT_DIR/$APP_DATABASE" echo "✅ @DriftDatabase 已更新" # ── 生成 import 块和 registry ───────────────────────────────────────────── IMPORT_BLOCK="" for IMPORT_PATH in "${IMPORTS[@]}"; do IMPORT_BLOCK+="import '$IMPORT_PATH';\n" done REGISTRY="" for i in "${!TABLE_CLASSES[@]}"; do DATA="${DATA_CLASSES[$i]}" GETTER="${GETTERS[$i]}" REGISTRY+=" $DATA: database.$GETTER,\n" echo " 注册: $DATA → database.$GETTER" done echo "" echo "✍️ 更新 imports + getTableRegistry..." python3 - "$ROOT_DIR/$APP_DATABASE" "$REGISTRY" "$IMPORT_BLOCK" << 'PYEOF' import sys, re file_path = sys.argv[1] registry = sys.argv[2].replace('\\n', '\n') imports = sys.argv[3].replace('\\n', '\n') with open(file_path, 'r') as f: content = f.read() # 替换 import 块(保留 drift import,替换其余 table imports) new_content = re.sub( r"(import 'package:drift/drift\.dart';\n)(?:import '[^']+\';\n)*", "import 'package:drift/drift.dart';\n" + imports, content ) # 替换 getTableRegistry 里的第二个 return { 块(不依赖注释) parts = new_content.split('getTableRegistry', 1) if len(parts) == 2: after = parts[1] # 跳过第一个 return {}(is! AppDatabase 那个),替换第二个 count = [0] def replace_second(m): count[0] += 1 if count[0] == 2: return m.group(1) + '\n' + registry + ' ' + m.group(2) return m.group(0) new_after = re.sub( r'(return \{)(.*?)(\};)', lambda m: replace_second(re.match(r'(return \{)(.*?)(\};)', m.group(0), re.DOTALL)), after, flags=re.DOTALL ) # 用更简单直接的方式:找到所有 return { 块,替换第二个 matches = list(re.finditer(r'return \{.*?\};', after, re.DOTALL)) if len(matches) >= 2: m = matches[1] new_after = after[:m.start()] + 'return {\n' + registry + ' };' + after[m.end():] new_content = parts[0] + 'getTableRegistry' + new_after with open(file_path, 'w') as f: f.write(new_content) print("✅ imports + getTableRegistry 已更新") PYEOF echo "" echo "🎉 完成!下一步运行:" echo " melos run gen"