{
"name": "tnpm",
"version": "1.2.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"nrm",
"npm",
"cnpm",
"yarn"
],
"bin": {
"tnpm": "./src/index.js"
},
"repository": {
"url": "你的git地址",
"type": "git"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.0.0",
"commander": "^10.0.0",
"inquirer": "^8.0.0",
"node-http-ping": "^0.3.1"
}
}
{
"npm": {
"home": "https://www.npmjs.org",
"registry": "https://registry.npmjs.org/",
"ping": "https://registry.npmjs.org"
},
"yarn": {
"home": "https://yarnpkg.com",
"registry": "https://registry.yarnpkg.com/",
"ping": "https://registry.yarnpkg.com"
},
"tencent": {
"home": "https://mirrors.cloud.tencent.com/npm/",
"registry": "https://mirrors.cloud.tencent.com/npm/",
"ping": "https://mirrors.cloud.tencent.com/npm"
},
"cnpm": {
"home": "https://cnpmjs.org",
"registry": "https://r.cnpmjs.org/",
"ping": "https://r.cnpmjs.org"
},
"taobao": {
"home": "https://npmmirror.com",
"registry": "https://registry.npmmirror.com/",
"ping": "https://registry.npmmirror.com"
},
"npmMirror": {
"home": "https://skimdb.npmjs.com/",
"registry": "https://skimdb.npmjs.com/registry/",
"ping": "https://skimdb.npmjs.com/registry"
}
}
const { program } = require('commander')
const PKG = require('../package.json')
const registries = require('../registries.json');
const inquirer = require('inquirer');
const { exec, execSync } = require('child_process')
const ping = require('node-http-ping')
const fs = require('fs')
const chalk = require("chalk");
const path = require('path')
program.version(PKG.version)
const whiteList = ['npm', 'yarn', 'tencent', 'cnpm', 'taobao', 'npmMirror']
const getOrigin = async () => {
return await execSync('npm get registry', { encoding: "utf-8" })
}
program.command('ls').description('查看镜像').action(async () => {
const res = await getOrigin()
const keys = Object.keys(registries)
const message = []
const max = Math.max(...keys.map(v => v.length)) + 3
keys.forEach(k => {
const newK = registries[k].registry == res.trim() ? ('* ' + k) : (' ' + k)
const Arr = new Array(...newK)
Arr.length = max;
const prefix = Array.from(Arr).map(v => v ? v : '-').join('')
message.push(prefix + ' ' + registries[k].registry)
})
console.log(message.join('\n'))
})
program.command('use').description('请选择镜像').action(() => {
inquirer.prompt([
{
type: "list",
name: "sel",
message: "请选择镜像",
choices: Object.keys(registries)
}
]).then(result => {
const reg = registries[result.sel].registry
exec(`npm config set registry ${reg}`, null, (err, stdout, stderr) => {
if (err) {
console.error('切换错误', err)
} else {
console.log('切换成功')
}
})
})
})
program.command('current').description('查看当前源').action(async () => {
const reg = await getOrigin()
const v = Object.keys(registries).find(k => {
if (registries[k].registry === reg.trim()) {
return k;
}
})
console.log(chalk.blue('当前源:', v))
})
program.command('ping').description('测试镜像地址速度').action(() => {
inquirer.prompt([
{
type: "list",
name: "sel",
message: "请选择镜像",
choices: Object.keys(registries)
}
]).then(result => {
const url = registries[result.sel].ping.trim()
ping(url).then(time => console.log(chalk.blue(`响应时长: ${time}ms`)))
.catch(() => console.log(chalk.red('GG','timeout')))
})
})
program.command('add').description('自定义镜像').action(() => {
inquirer.prompt([
{
type: "input",
name: "name",
message: "请输入镜像名称",
validate(answer) {
const keys = Object.keys(registries)
if (keys.includes(answer)) {
return `不能起名${answer}跟保留字冲突`
}
if (!answer) {
return '名称不能为空'
}
return true
}
},
{
type: "input",
name: "url",
message: "请输入镜像地址",
validate(answer) {
if (!answer) {
return `url不能为空`
}
return true
}
}
]).then(result => {
const del = (url) => {
const arr = url.split('')
return arr[arr.length - 1] == '/' ? (arr.pop() && arr.join('')) : arr.join('')
}
registries[result.name] = {
home: result.url.trim(),
registry: result.url.trim(),
ping: del(result.url.trim()),
}
try {
fs.writeFileSync(path.join(__dirname, '../registries.json'), JSON.stringify(registries, null, 4))
console.log(chalk.blue('添加完成'))
}
catch (e) {
console.log(chalk.red(err))
}
})
})
program.command('delete').description('删除自定义的源').action(() => {
const keys = Object.keys(registries)
if (keys.length === whiteList.length) {
return console.log(chalk.red('当前无自定义源可以删除'))
} else {
const Difference = keys.filter((key) => !whiteList.includes(key))
inquirer.prompt([
{
type: "list",
name: "sel",
message: "请选择删除的镜像",
choices: Difference
}
]).then(async result => {
const current = await getOrigin()
const selOrigin = registries[result.sel]
if (current.trim() == selOrigin.registry.trim()) {
console.log(chalk.red(`当前还在使用该镜像${registries[result.sel].registry},请切换其他镜像删除`))
} else {
try {
delete registries[result.sel]
fs.writeFileSync(path.join(__dirname, '../registries.json'), JSON.stringify(registries, null, 4))
console.log(chalk.green('SUCCESS 操作完成'))
}
catch (e) {
console.log(chalk.red(err))
}
}
})
}
})
program.parse(process.argv)