如何通过npm API获取私有包版本并迁移至Verdaccio私有仓库?
解决私有npm包迁移到Verdaccio的实用思路
我之前也碰到过类似的私有包迁移需求,现成工具确实大多对私有包支持不友好,分享几个亲测可行的方案给你:
一、正确获取私有包及版本列表
你之前用curl没拿到数据,大概率是请求头或API端点不对。npm Registry的私有包查询需要携带有效的authToken,且要调用正确的私有包查询接口:
1. 查询私有作用域下的所有包
用curl请求npm的搜索API,指定作用域和私有访问权限,记得带上Authorization头:
curl -H "Authorization: Bearer YOUR_OLD_AUTH_TOKEN" \ "https://old-registry-url/-/v1/search?text=scope:YOUR_PRIVATE_SCOPE&access=private"
如果是npmjs官方仓库,把old-registry-url换成registry.npmjs.org就行。返回的JSON里会包含该作用域下所有私有包的基本信息。
2. 获取单个包的所有版本
拿到包名后,用npm view命令(需配置旧仓库的authToken)就能获取所有版本:
# 先临时配置旧仓库的认证 npm config set registry https://old-registry-url/ npm config set //old-registry-url/:_authToken YOUR_OLD_AUTH_TOKEN # 查询某个包的所有版本,返回JSON格式 npm view @your-scope/your-package versions --json
或者用API请求更灵活:
curl -H "Authorization: Bearer YOUR_OLD_AUTH_TOKEN" \ "https://old-registry-url/@your-scope%2Fyour-package"
返回的JSON中versions字段就是该包的所有版本号。
二、自动化迁移脚本的核心逻辑
用Node.js写脚本是最灵活的方式,能完整控制迁移流程,下面是核心步骤:
1. 收集用户输入
用inquirer包让用户输入必要信息:
const inquirer = require('inquirer'); const answers = await inquirer.prompt([ { type: 'input', name: 'oldRegistry', message: '旧npm仓库地址:' }, { type: 'input', name: 'oldAuthToken', message: '旧仓库authToken:' }, { type: 'input', name: 'verdaccioUrl', message: 'Verdaccio仓库地址:' }, { type: 'input', name: 'verdaccioAuthToken', message: 'Verdaccio的authToken:' }, { type: 'input', name: 'privateScope', message: '私有包作用域(如@myorg):' } ]);
2. 获取私有包列表
用axios请求旧仓库API:
const axios = require('axios'); const searchUrl = `${answers.oldRegistry}/-/v1/search?text=scope:${answers.privateScope.replace('@', '')}&access=private`; const searchRes = await axios.get(searchUrl, { headers: { Authorization: `Bearer ${answers.oldAuthToken}` } }); const packageNames = searchRes.data.objects.map(item => item.package.name);
3. 遍历包并迁移所有版本
对每个包,先获取版本,再下载tar包,最后发布到Verdaccio:
const { execSync } = require('child_process'); const fs = require('fs'); // 配置旧仓库 execSync(`npm config set registry ${answers.oldRegistry}`); execSync(`npm config set //${answers.oldRegistry.replace('https://', '')}/:_authToken ${answers.oldAuthToken}`); // 配置Verdaccio execSync(`npm config set registry ${answers.verdaccioUrl}`); execSync(`npm config set //${answers.verdaccioUrl.replace('http://', '')}/:_authToken ${answers.verdaccioAuthToken}`); for (const pkgName of packageNames) { // 获取所有版本 const versionsStr = execSync(`npm view ${pkgName} versions --json`).toString(); const versions = JSON.parse(versionsStr); for (const version of versions) { // 下载包为tarball execSync(`npm pack ${pkgName}@${version}`); const tarball = `${pkgName.replace('/', '-')}-${version}.tgz`; // 发布到Verdaccio execSync(`npm publish ${tarball} --access private`); // 删除本地tarball fs.unlinkSync(tarball); } }
三、关键注意事项
- 权限验证:旧仓库的authToken必须拥有私有包的读取权限,Verdaccio的authToken必须拥有发布权限。
- Verdaccio配置:确保Verdaccio的
config.yaml中允许私有作用域的包发布,比如:packages: '@your-scope/*': access: $authenticated publish: $authenticated unpublish: $authenticated - Dist-Tags保留:如果需要保留原包的dist-tags(如
latest),发布后可以执行npm dist-tag add ${pkgName}@${version} ${tag}。 - 依赖处理:如果迁移的包依赖其他私有包,要确保这些依赖也被迁移,否则用户
npm install时会失败。
内容的提问来源于stack exchange,提问作者Dan Scrima
相关产品推荐
相关产品推荐

