当前命令完成后如何等待下一个npm命令运行?

问题描述 投票:0回答:1

我知道,听起来很简单。但请继续阅读以了解我面临的挑战。

我正在尝试创建一个'init'命令,以帮助建立用于开发的克隆存储库。我们利用远程程序包管理器,要求开发人员在处理程序包时在存储库中有一个.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文件并运行所有内容,except writeNpmRcFile.js,它就可以正常运行。只有当我链接此命令时,它们才会失败。

我知道我想念什么,我只是不知道什么?我等待fs.writeFile成功完成(可能只需要使用writeFileSync ...)。就像文件系统没有及时释放下一个命令的.npmrc文件。我什至在某一时刻设置了一个自定义的异步wait()方法,该方法在退出该过程之前会暂停一秒钟,但这没有帮助。有什么想法吗?

javascript node.js npm npm-scripts
1个回答
0
投票

因此,@ 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"
  }
© www.soinside.com 2019 - 2024. All rights reserved.