javascript - 当前命令完成后如何等待运行下一个 npm 命令?
问题描述
我知道,这听起来很简单。但请继续阅读以了解我面临的挑战。
我正在尝试创建一个“init”命令,以帮助设置克隆的 repo 以进行开发。我们使用远程包管理器,要求开发人员.npmrc
在处理包时在存储库中有一个文件(我们不想通过使用全局.npmrc
文件来限制用户)。该过程应该像这样工作:
- 在终端提示用户输入他们的用户名
- 将
.npmrc
文件写入他们的系统 - 跑
npm i
- 跑
npm run build
我script
在我的package.json
:
"init": "node ./scripts/writeNpmRc.js && npm i && npm run build && node ./scripts/init.js"
我的writeNpmRc.js
文件用于readline
获取用户输入,然后写入文件(请记住,此时我们还没有运行npm i
,所以我们正在处理节点安装的内容)。
const readline = require('readline');
const fs = require('fs');
const path = require('path');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const writeFile = function(dest, data) {
return new Promise((resolve, reject) => {
fs.writeFile(dest, data, 'utf-8', function(err) {
if (err) {
reject(err);
}
resolve();
});
});
};
const getUsername = () => {
const promise = new Promise((resolve, reject) => {
try {
rl.question(
'What is your username (typically firstname.lastname)? ',
result => {
if (!result) {
console.error('You must provide your username.');
return getUsername();
}
resolve(result);
}
);
} catch (err) {
reject(err);
}
});
return promise
.catch(err => {
console.error('[getUsername] ', err);
})
.finally(() => {
rl.close();
});
};
(async () => {
const userName = await getUsername();
const fileData = `registry=http://my.remote.repo/url/
email=${userName}@email.com`;
await writeFile(path.resolve(__dirname, '../.npmrc'), fileData).catch(err => {
console.err('[writeFile Error]', err);
});
console.log('[END writeNpmRcFile]');
process.exit(0);
})();
这部分似乎运行良好,只是后续命令 ( npm i
) 没有使用新.npmrc
文件和安装炸弹。我可以(失败后)运行npm i
得很好,所以文件内容本身似乎是正确的。事实上,如果我手动放置一个.npmrc
文件并运行所有内容,除了,writeNpmRcFile.js
它运行得很好。只有当我链接此命令时,它们才会失败。
我知道我错过了什么,我只是不知道是什么?我等待fs.writeFile
成功完成(可能只是使用writeFileSync
...)。这就像文件系统没有及时释放.npmrc
文件以执行下一个命令。我什至设置了一个自定义异步wait()
方法,在退出进程之前暂停了一秒钟,但它没有帮助。有任何想法吗?
解决方案
所以,@RobC 在他的评论中很有意义,我在编写文件后测试了我关于使用child_process
运行步骤的后续理论。测试表明我认为正确,它在单独的上下文中运行命令,并且该上下文将使用新文件。对于那些好奇的人,这是我的更新,包括安装。npm i
.npmrc
writeNpmRcFile.js
const readline = require('readline');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
let rl;
let spinnerInterval;
const getInterface = () =>
readline.createInterface({
input: process.stdin,
output: process.stdout
});
const writeFile = function(dest, data) {
return new Promise((resolve, reject) => {
fs.writeFile(dest, data, 'utf-8', function(err) {
if (err) {
reject(err);
}
resolve();
});
});
};
const runInstall = () => {
console.log('Running npm install (This may take a few, so be patient)');
spinnerInterval = twirlTimer();
const promise = new Promise((resolve, reject) => {
exec(
'npm i',
{ cwd: path.resolve(__dirname, '../') },
(err, stdout, stderr) => {
clearInterval(spinnerInterval);
if (err) {
reject(err);
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
resolve();
}
);
});
return promise.catch(err => {
clearInterval(spinnerInterval));
return Promise.reject(err);
}
};
const twirlTimer = function() {
var P = ['\\', '|', '/', '-'];
var x = 0;
return setInterval(function() {
process.stdout.write('\r' + P[x++]);
x &= 3;
}, 250);
};
const getUsername = () => {
if (!rl) rl = getInterface();
const promise = new Promise((resolve, reject) => {
try {
rl.question(
'What is your username (typically firstname.lastname)? ',
result => {
if (!result) {
console.error('You must provide your username.');
return getUsername();
}
resolve(result);
}
);
} catch (err) {
reject(err);
}
});
return promise
.catch(err => {
console.error('[getUsername] ', err);
})
.finally(() => {
rl.close();
});
};
(async () => {
const userName = await getUsername();
// prettier-ignore
const fileData = `registry=http://my.remote.repo/url/
email=${userName}@email.com`;
console.log(`Writing your '.npmrc' file to the directory`);
await writeFile(path.resolve(__dirname, '../.npmrc'), fileData).catch(err => {
console.error('[writeFile Error] ', err);
});
await runInstall().catch(err => {
console.log('[runInstall Error] ', err);
});
console.log('[END writeNpmRcFile]');
process.exit(0);
})();
进行此更改后,我对此进行了package.json
scripts
更改:
"scripts": {
"lint": "eslint ./scripts",
"start": "node ./dist/index.js",
"release": "standard-version",
"write-npmrc": "node ./scripts/writeNpmRcFile.js",
"init": "npm run write-npmrc && npm run build && node ./scripts/init.js",
"build": "node ./scripts/build.js"
}
推荐阅读
- sql-server - “getDate”可以作为 SQL Server 存储过程名称吗?
- javascript - 将字符串转换为javascript中的对象,如正则表达式
- html - 如何将图片推送到文本下方并在图片旁边写上标题?
- hibernate - Hibernate Envers 禁用 RevisionListener
- kubernetes - 恢复 Rancher 时出错:此集群当前不可用;在 API 准备好之前,与它直接交互的区域将不可用
- php - 一般错误:1364 字段 'kategori_artikel_id' 没有默认值
- html - 如何突出显示角度 6 中的活动选项卡
- php - 搜索 laravel 分页结果
- python - 时间序列的标准差
- angular - 基于 Bootstrap 的电子商务主题未正确集成到 angular8 项目中?