背景:我们在发布 npm package 的时候,需要注册私有的 registry,使用 npm adduser, 在这个过程中我们会和 npm 进行交互式连接,npm-proxy-login 就是帮助我们使用 nodejs 进行交互式输入 账号、密码、邮箱, 在此过程中无需手动输入任何信息,nodejs脚本实现一键登录
-
正常情况下发布一个
npm包,需要对发布的registry进行adduser, 会触发npm的 交互式命令行 (需要手动 一行一行的 输入username、password、email, 比较麻烦, 而且在CI Runner也没办法进行一行一行的输入,此时就需要一个脚本完成一次新输入)- 见下图,当我们执行
npm adduser的时候需要我们输入username,当username输入完成 - 按下回车,需要输入
password, 当password输入完成 - 按下回车,需要输入
email - 通过上述
username、password、email输入完成,才可以login成功
- 见下图,当我们执行
- 使用
npm-proxy-login实现一行脚本自动login
// package.json
{
"initPrivateRegistry": "npx npm-proxy-login https://priveta-registry username password email"
}
3. 通过 npx 调用 该脚本,需要传入4个参数,分别代表 (私有的 npm 源、 账号、密码、邮箱)
-
如果在
CI Runner里面使用,一般情况下,username、password、email都会设置为Mask,可以直接在gitlab_ci.yaml中调用此脚本,可以正常实现registry login -
实现原理
-
拿到传入的4个参数,调用 exec 进行 执行 子进程的
shell命令 -
在执行过程中设置
stdio为[0, 1, 2]。- 0:表示子进程的
stdin继承自父进程的stdin - 1: 表示继承子进程的
stdout - 2: 继承自父进程的
stderr
- 0:表示子进程的
-
拿到
nodejs给的stdout,切割准备好的参数进入填入 stdout 的输入
-
#!/usr/bin/env node
const { exec } = require("child_process");
const [registry, ...otherArgvList] = process.argv.slice(2);
const inputArray = otherArgvList.reduce((result, item) => {
result.push(item + "\n");
return result;
}, []);
const result = exec(
`npm adduser --registry ${registry}`,
{
shell: true,
async: true,
stdio: [0, 1, 2],
timeout: 600000,
},
(err, stdout) => {
console.log(err, "err", stdout, "stdout");
if (err) {
process.exit(1);
}
},
);
result.stdout.on("data", (chunk) => {
console.log(chunk, "接收到的输入: -> ", chunk.toString());
if (chunk.toString()?.trim?.()) {
const cmd = inputArray.shift();
result.stdin.write(String(cmd));
}
});
process.on("error", () => {
process.exit(1);
});