私服 nexus 之间迁移 npm 仓库

本文介绍如何将一个 Nexus 特定仓库中的 npm 包内容迁移到另一个 Nexus 特定仓库。此过程适用于需要重构仓库结构或合并仓库的场景。

迁移脚本

以下是完整的迁移脚本,它会自动完成以下操作:

  1. 从源仓库获取所有 npm 包列表
  2. 下载每个包的 .tgz 文件
  3. 解压并重新发布到目标仓库
bash 复制代码
#!/bin/bash

# === 配置区域 ===
NEXUS_URL="https://nexus.test.com"
USERNAME="test"
PASSWORD="123456"

SOURCE_REPO="npm-a"
TARGET_REPO="npm-b"

SOURCE_REGISTRY="$NEXUS_URL/repository/$SOURCE_REPO/"
TARGET_REGISTRY="$NEXUS_URL/repository/$TARGET_REPO/"

TMP_DIR="/tmp/npm-migrate"
mkdir -p "$TMP_DIR"
cd "$TMP_DIR" || exit 1
# =================

# ✅ 日志处理:同时输出到终端和日志文件
LOG_FILE="$TMP_DIR/npm-migrate.log"
exec > >(tee -a "$LOG_FILE") 2>&1

log() {
  echo "[$(date '+%F %T')] $*"
}

log "🚀 启动 npm 仓库迁移脚本"

# 遇到错误不中断脚本
set +e

TOKEN=""

while true; do
    log "📥 获取包列表,continuationToken=$TOKEN"

    RESPONSE=$(curl -s -u "$USERNAME:$PASSWORD" \
      "$NEXUS_URL/service/rest/v1/components?repository=$SOURCE_REPO${TOKEN:+&continuationToken=$TOKEN}")

    ITEM_COUNT=$(echo "$RESPONSE" | jq '.items | length')
    log "📦 本页包含 $ITEM_COUNT 个包"

    echo "$RESPONSE" | jq -c '.items[]' | while read -r item; do
        name=$(echo "$item" | jq -r '.assets[0].path' | cut -d/ -f1)
        version=$(echo "$item" | jq -r '.version')

        log "➡️ 处理 $name@$version"

        tarball_url="${SOURCE_REGISTRY}${name}/-/${name}-${version}.tgz"
        tarball_file="${name}-${version}.tgz"

        log "🌐 下载包: $tarball_url"
        curl -s -u "$USERNAME:$PASSWORD" -O "$tarball_url"

        if [[ -f "$tarball_file" ]]; then
            tar -xzf "$tarball_file"
            pkg_dir="package"

            # 可选:检查是否已存在(加快速度)
            EXISTS=$(curl -s -u "$USERNAME:$PASSWORD" "$TARGET_REGISTRY$name" | grep "\"$version\"")
            if [[ -n "$EXISTS" ]]; then
                log "✅ $name@$version 已存在于目标仓库,跳过发布"
            else
                log "🚀 发布 $name@$version 到 $TARGET_REPO"
                npm publish "$pkg_dir" --registry "$TARGET_REGISTRY" --force
                if [[ $? -ne 0 ]]; then
                    log "❌ 发布失败:$name@$version"
                else
                    log "✅ 发布成功:$name@$version"
                fi
            fi

            rm -rf "$tarball_file" "$pkg_dir"
        else
            log "❌ 下载失败:$tarball_url"
        fi
    done

    # 分页处理
    TOKEN=$(echo "$RESPONSE" | jq -r '.continuationToken')
    if [[ "$TOKEN" == "null" || -z "$TOKEN" ]]; then
        log "✅ 所有包处理完成,无更多分页"
        break
    else
        log "➡️ 获取下一页 continuationToken=$TOKEN"
    fi
done

log "🏁 所有迁移已完成"

~/.npmrc 中配置目标仓库的 auth 认证信息,因为发布包要使用,内容如下示例:

bash 复制代码
registry=https://nexus.test.com/repository/npm-b/
//nexus.test.com/repository/npm-b/:_auth=c45h2312asmh3dsfYW3fassaawRAxMde=
//nexus.test.com/repository/npm-b/:always-auth=true

其中 _auth 后面的内容是对 "账号:密码" 进行base64之后的字符串,注意账号密码使用英文冒号分隔拼接在一起后统一 base64。

使用说明

  • 确保已安装 curl, jq, npmtar 工具

  • 确保有源仓库和目标仓库的访问权限

执行脚本:

bash 复制代码
chmod +x migrate.sh
./migrate.sh

注意事项

  • 此脚本仅处理源仓库中的第一页数据(默认100条记录),如需处理更多数据,需要添加分页逻辑

  • 迁移过程中会保留原始包的版本信息

  • 使用 --force 参数强制发布,可能会覆盖目标仓库中已存在的同名包

  • 脚本执行完毕后会自动清理临时文件


(END)

相关推荐
lastHertz4 天前
openskill 实战指南:像管理 npm 包一样管理你的 AI Skill
前端·人工智能·npm
qq_589666055 天前
npm install npm install -g @vue/cli 分别是什么意思以及安装路径
前端·vue.js·npm
Dreamboat-L6 天前
NVM的安装与使用(保姆级教程)
npm·node.js
无责任此方_修行中7 天前
踩坑实录:为什么 `pnpm run` 会偷偷帮你装依赖?—— 浅析 pnpm 与 npm run 的底层差异
javascript·后端·npm
ShiXZ2139 天前
指令集-NPM 常用指令速查手册
前端·npm·node.js
是烨笙啊9 天前
从 npm 与 Bun 的选择看 AI 时代的“最佳实践”焦虑
前端·人工智能·npm
小杍随笔9 天前
【 .npmrc 终极配置指南:统一管理 npm/pnpm 缓存与全局目录,告别磁盘混乱】
前端·缓存·npm
ppshuX10 天前
npm-cli-造轮子初体验
npm
前端工作日常11 天前
我学习到的npx内部实现机制
npm
minglie112 天前
npm ali-oss库依赖冲突
前端·npm