📦 Dependency Impact Analyzer — Dependency Impact 分析器
v1.0.0Analyze the blast radius of upgrading, removing, or replacing a dependency — 追踪 导入s, find affected files, 检查 test coverage of impacted code, 检测...
详细分析 ▾
运行时依赖
版本
echo "--- 正在检查破坏性变更 ---"
安装命令
点击复制技能文档
依赖影响分析器 在升级或移除依赖前,先弄清到底会波及什么。追踪所有 import,找出每一处引用该包的文件,检查受影响代码的测试覆盖率,识别潜在破坏性变更。
适用场景: “升级 X 会发生什么”、“移除 lodash 的影响”、“能否安全更新”、“依赖爆炸半径”、“哪些文件用了包 X”、“升级风险评估”,或任何重大依赖变更前。
命令
- trace — 追踪依赖的所有用法
PACKAGE="${1:?Usage: trace }" echo "=== 正在追踪:$PACKAGE ===" # 直接引入(JS/TS) echo "--- 直接引入 ---" rg -n "from ['\"]$PACKAGE['\"/]|require\(['\"]$PACKAGE['\"/]\)|import ['\"]$PACKAGE['\"]" \ -g '.{js,ts,jsx,tsx,mjs,cjs}' -g '!node_modules' -g '!dist' -g '!build' 2>/dev/null # 子路径引入 echo "--- 子路径引入 ---" rg -n "from ['\"]$PACKAGE/" \ -g '.{js,ts,jsx,tsx}' -g '!node_modules' -g '!dist' 2>/dev/null # Python 引入 rg -n "^import $PACKAGE|^from $PACKAGE" \ -g '.py' -g '!vendor' -g '!dist' 2>/dev/null # Go 引入 rg -n "\".$PACKAGE" \ -g '.go' -g '!vendor' 2>/dev/null # 统计 USAGE_COUNT=$(rg -c "$PACKAGE" \ -g '!node_modules' -g '!vendor' -g '!dist' -g '!.lock' -g '!package-lock.json' \ --type-not binary 2>/dev/null | awk -F: '{s+=$2} END {print s+0}') FILE_COUNT=$(rg -l "$PACKAGE" \ -g '!node_modules' -g '!vendor' -g '!dist' -g '!.lock' -g '!package-lock.json' \ --type-not binary 2>/dev/null | wc -l) echo "" echo "总计:$USAGE_COUNT 处引用,分布在 $FILE_COUNT 个文件"
提取具体用到的导出/API: rg -o "import \{([^}]+)\} from ['\"]$PACKAGE['\"]" \ -g '.{ts,js,tsx,jsx}' -g '!node_modules' 2>/dev/null | \ sed "s/.{//;s/}.//" | tr ',' '\n' | sed 's/^\s//;s/\s$//' | sort | uniq -c | sort -rn rg -o "const \{([^}]+)\} = require\(['\"]$PACKAGE['\"]\)" \ -g '.{js,ts}' -g '!node_modules' 2>/dev/null | \ sed "s/.{//;s/}.//" | tr ',' '\n' | sed 's/^\s//;s/\s$//' | sort | uniq -c | sort -rn
- impact — 完整影响评估
PACKAGE="${1:?Usage: impact [target-version]}" TARGET_VERSION="${2:-latest}"
# 当前版本与目标版本 if [ -f "package.json" ]; then CURRENT=$(python3 -c "import json;d=json.load(open('package.json'));v=d.get('dependencies',{}).get('$PACKAGE')or d.get('devDependencies',{}).get('$PACKAGE')or'not found';print(v)" 2>/dev/null) echo "当前:$PACKAGE@$CURRENT" fi if [ -f "requirements.txt" ]; then grep -i "^$PACKAGE" requirements.txt 2>/dev/null fi
# 破坏性变更检测 echo "--- 检查破坏性变更 ---" if [ -f "package.json" ]; then npm info "$PACKAGE" versions --json 2>/dev/null | python3 -c " import json,sys,re try: versions=json.load(sys.stdin) current='$CURRENT'.lstrip('^~>=') current_major=current.split('.')[0] if current!='not found'else'0' latest=versions[-1] if isinstance(versions,list)else versions latest_major=latest.split('.')[0] if current_major!=latest_major: print(f'⚠️ 主版本号变化:{current} → {latest}(可能含破坏性变更)') else: print(f'✅ 主版本号相同:{current} → {latest}(应向下兼容)') except Exception as e: print(f'无法检查版本:{e}') " 2>/dev/null fi # 检查 npm 弃用 npm info "$PACKAGE" deprecated 2>/dev/null | grep -v "^$" && echo "⚠️ 包已被弃用"
# 受影响文件的测试覆盖率 AFFECTED_FILES=$(rg -l "$PACKAGE" \ -g '!node_modules' -g '!vendor' -g '!dist' -g '!.lock' -g '!.test.' -g '!.spec.' \ -g '.{js,ts,jsx,tsx,py,go}' --type-not binary 2>/dev/null) echo "--- 受影响文件的测试覆盖 ---" for f in $AFFECTED_FILES; do BASE=$(basename "$f" | sed 's/\.[^.]$//') DIR=$(dirname "$f") TEST=$(find "$DIR" -maxdepth 2 \( -name "${BASE}.test." -o -name "${BASE}.spec." -o -name "test_${BASE}." \) \ -not -path '/node_modules/*' 2>/dev/null | head -1) if [ -n "$TEST" ]; then echo "✅ $f → $TEST" else echo "❌ $f → 无测试(升级风险!)" fi done
# 依赖树影响 echo "--- 反向依赖 ---" if [ -f "package-lock.json" ]; then python3 -c " import json lock=json.load(open('package-lock.json')) pkg='$PACKAGE' rdeps=[] packages=lock.get('packages',lock.get('dependencies',{})) for name,info in packages.items(): deps=info.get('dependencies',{}) if pkg in deps: clean_name=name.replace('node_modules/','') rdeps.append(f'{clean_name}') if rdeps: print('\n'.join(rdeps)) else: print('无其他包依赖此包')" fi