思考
在我们使用有些 npm 库(cli)时,我们可以使用某些指令(命令行接口)来使用该库。例如rollup
的rollup src/main.js -f cjs
;或vite
的vite dev
。
那么他们时如何实现的?
关于node
是实现该功能网上有很多文章,大家可自行查阅。
接下来我们使用bun
来实现该功能。其实与 nodejs 实现原理一致。
我们来实现一个简单的输入输出命令printer
;
创建项目
- 新建
printer
文件夹 - 使用
bun init
来初始化项目。
index.ts
#!/usr/bin/env node
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { readFileSync } from "node:fs";
// 获取当前文件的目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// 读取 package.json
const packageJson = JSON.parse(
readFileSync(join(__dirname, "package.json"), "utf-8")
);
const version: string = packageJson.version;
function evaluateMathExpression(expr: string): number {
try {
return new Function(`return ${expr}`)();
} catch (error) {
console.error("无效的数学表达式");
return NaN;
}
}
function printHelp(): void {
console.log(`
打印工具 v${version}
用法:
printer <文本> 打印文本
printer --version 显示版本号
printer --help 显示帮助信息
printer --math <表达式> 计算数学表达式
示例:
printer hello world
printer --math 1+1
`);
}
type StrategyFunction = (args: string[]) => void;
const strategies: { [key: string]: StrategyFunction } = {
"--version": (): void => {
console.log(version);
},
"--help": printHelp,
"--math": (args: string[]): void => {
if (args.length < 2) {
console.error("请提供数学表达式");
return;
}
const expression = args.slice(1).join("");
const result = evaluateMathExpression(expression);
if (!isNaN(result)) {
console.log(result);
}
},
default: (args: string[]): void => {
console.log(args.join(" "));
},
};
function printArgs(): void {
const args: string[] = process.argv.slice(2);
if (args.length === 0) {
printHelp();
return;
}
const strategy: StrategyFunction = strategies[args[0]] || strategies.default;
strategy(args);
}
printArgs();
修改 package.json
{
"name": "printer",
"module": "dist/index.js",
"version": "1.0.0",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"scripts": {
"start": "bun index.ts",
"build": "bun build index.ts --target node --outdir dist && cp package.json dist"
},
"bin": {
"printer": "./dist/index.js"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
打包
bun run build
安装到当前项目
bun link
就可以使用啦
printer hello
hello
printer --math 1+1
2
全局使用
npm install -g .
也可发布到 npm 上面
略