Files
customer-im-client-dev/scripts/table_gen.sh
Happi (哈比) 113ecb633a 更新数据库
2026-03-06 16:54:51 +08:00

185 lines
5.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"