快速link monorepo仓库下的包
需求
业务项目需要快速link某一些包,这些包使用的pnpm的workspace去管理(monorepo)
index.js
#! node
import path from 'path'
import fs from 'fs'
import { program } from 'commander'
import yaml from 'yamljs'
import chalk from 'chalk'
import shell from 'shelljs'
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))
program.version(packageJson.version, '-v, --version')
program
.command('link')
.description('使用指定库的全局link,如@vue')
.argument('[namespace]', '请输入要link的库的namespace', (v) => v)
.action((namespace) => {
const workspaceConfig = getWorkspaceConfig()
if (workspaceConfig) {
console.log(chalk.red('当前目录是monorepo目录,请勿使用全局link,以避免bug'));
shell.exit()
}
const ls = shell.ls()
const packageJson = ls.find(v => v.endsWith('package.json'))
if (!packageJson) {
console.log(chalk.red('当前目录非npm项目,无package.json。已停止运行'));
shell.exit()
}
console.log(chalk.blue(`当前工作区,正在从global link ${namespace}`));
const globalDir = shell.exec('pnpm root -g').replace('\n', '')
const packagePath = path.resolve(globalDir, namespace)
const packages = shell.ls(packagePath)
if (!packages.length) {
console.log(chalk.red(`当前全局域内无${namespace}对应的link,请先前往${namespace}执行全局link`));
shell.exit()
}
shell.exec(`pnpm link -g ${packages.map(v => `${namespace}/${v}`).join(' ')}`)
console.log(chalk.green(`当前工作区,已使用${namespace}的全局link`));
})
program
.command('unlink')
.description('unlink指定库,如@vue')
.argument('[namespace]', '请输入要unlink的库的namespace', (v) => v)
.action((namespace) => {
const workspaceConfig = getWorkspaceConfig()
if (workspaceConfig) {
console.log(chalk.red('当前目录是monorepo目录,请勿使用全局link,以避免bug'));
shell.exit()
}
const ls = shell.ls()
const packageJson = ls.find(v => v.endsWith('package.json'))
if (!packageJson) {
console.log(chalk.red('当前目录非npm项目,无package.json。已停止运行'));
shell.exit()
}
console.log(chalk.blue(`当前工作区,正在unlink ${namespace}`));
const globalDir = shell.exec('pnpm root -g').replace('\n', '')
const packagePath = path.resolve(globalDir, namespace)
const packages = shell.ls(packagePath)
shell.exec(`pnpm unlink ${packages.map(v => `${namespace}/${v}`).join(' ')}`)
console.log(chalk.green(`当前工作区,已unlink ${namespace}`));
})
program
.command('global')
.description('将当前库link到全局')
.action(() => {
console.log(chalk.blue(`当前工作区,正在link到global,请稍等...`));
const workspaceDirs = getWordspaceDir()
workspaceDirs.forEach(v => {
shell.cd(v)
shell.exec(`pnpm link -g`)
})
console.log(chalk.green(`当前工作区已设置全局link`));
})
program
.command('clear')
.description('清除当前库全局link')
.action(() => {
console.log(chalk.blue(`当前工作区,正在从global清除link`));
const workspaceDirs = getWordspaceDir()
const globalDir = shell.exec('pnpm root -g').replace('\n', '')
const existsDirs = []
const emptyDirs = []
workspaceDirs.forEach(v => {
const json = JSON.parse(fs.readFileSync(path.resolve(v, 'package.json'), 'utf8'))
// console.log(path.resolve(globalDir.toString(), json.name));
if (fs.existsSync(path.resolve(globalDir, json.name))) {
existsDirs.push(json.name)
} else {
emptyDirs.push(json.name)
}
})
if (existsDirs.length) {
shell.exec(`pnpm rm -g ${existsDirs.join(' ')}`)
console.log(chalk.green(`已清除当前工作区${existsDirs.length}个全局link`));
} else {
console.log(chalk.yellow('当前工作区没有需要清除的全局link'));
}
})
program.parse(process.argv)
function getWorkspaceConfig() {
const ls = shell.ls()
return ls.find(v => v.endsWith('workspace.yaml'))
}
function getWordspaceDir() {
const workspaceConfig = getWorkspaceConfig()
if (!workspaceConfig) {
console.log(chalk.red('当前目录非workspace目录,已停止操作'));
shell.exit()
}
const yml = yaml.load(workspaceConfig)
// console.log(yml)
const workspaceList = yml.packages
let workspaceDirs = []
if (workspaceList.findIndex(v => v.includes('*')) > -1) {
const packagePath = workspaceList.find(v => v.includes('*')).split('/*')[0]
workspaceDirs = shell.ls(packagePath).map(v => path.resolve(`${packagePath}/${v}`))
}
return workspaceDirs
}package.json
{
"name": "qlink",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"bin": {
"qlink": "index.js"
},
"keywords": [],
"author": "liq245",
"license": "ISC",
"publishConfig": {
"registry": "https://github.com/repository/xxx/",
"access": "public"
},
"dependencies": {
"chalk": "^5.0.1",
"commander": "^9.3.0",
"shelljs": "^0.8.5",
"yamljs": "^0.3.0"
}
}