更新数据库

This commit is contained in:
Happi (哈比)
2026-03-06 16:54:51 +08:00
parent bf9e099747
commit 113ecb633a
17 changed files with 604 additions and 117 deletions

184
scripts/table_gen.sh Normal file
View File

@@ -0,0 +1,184 @@
#!/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"