1const npmBinsToPackageName = {2 'ts-node': 'ts-node',3 'eslint': 'eslint',4 'tsc': 'typescript',5 'mocha': 'mocha',6};78const paths = [];9for(const k of Object.keys(npmBinsToPackageName)) {10 paths.push([k], ['run', k]);11}1213module.exports = {14 name: 'plugin-root-bin',15 factory: require => {16 const {BaseCommand} = require('@yarnpkg/cli');17 const {Option} = require('clipanion');1819 class ExecuteBinFromRootCommand extends BaseCommand {20 static paths = paths;2122 args = Option.Proxy();2324 async execute() {25 const fs = require('fs');26 const path = require('path');2728 const ownPackageJson = JSON.parse(await fs.promises.readFile('package.json', 'utf-8'));29 const cmd = this.path[this.path.length - 1];3031 if(ownPackageJson.scripts?.[cmd]) {32 throw new Error(`'${cmd}' is defined in package.json but the 'plugin-root-bin' also defined it. To avoid unexpected results, please rename the script in package.json`);33 }3435 const dir = await this.getBinaryPackageDirectory(fs, path, cmd, ownPackageJson);36 const pkg = JSON.parse(await fs.promises.readFile(path.join(dir, 'package.json'), 'utf-8'));3738 const packageRelativeBinPath = typeof pkg.bin === 'object'39 ? pkg.bin[cmd]40 : pkg.bin;4142 const binPath = path.join(dir, packageRelativeBinPath);4344 process.exitCode = await this.cli.run(['node', binPath, ...this.args]);4546 // seems something in yarn resets the exit code, so force exit47 process.exit();48 }4950 async getBinaryPackageDirectory(_fs, path, cmd, _ownPackageJson) {51 const res = path.resolve(__dirname, '../../node_modules', npmBinsToPackageName[cmd]);52 console.error(res);53 return res;54 }55 }5657 return {58 commands: [59 ExecuteBinFromRootCommand,60 ],61 };62 },63};