1. 'use strict';
    
  2. 
    
  3. const chalk = require('chalk');
    
  4. const {exec} = require('child-process-promise');
    
  5. const {existsSync, mkdirSync} = require('fs');
    
  6. const {readJsonSync, writeJsonSync} = require('fs-extra');
    
  7. const inquirer = require('inquirer');
    
  8. const {join} = require('path');
    
  9. const createLogger = require('progress-estimator');
    
  10. const {
    
  11.   BUILD_METADATA_TEMP_DIRECTORY,
    
  12.   NPM_PACKAGES,
    
  13. } = require('./configuration');
    
  14. 
    
  15. const logger = createLogger({
    
  16.   storagePath: join(__dirname, '.progress-estimator'),
    
  17. });
    
  18. 
    
  19. async function checkNPMPermissions() {
    
  20.   const currentUser = await execRead('npm whoami');
    
  21.   const failedProjects = [];
    
  22. 
    
  23.   const checkProject = async project => {
    
  24.     const owners = (await execRead(`npm owner ls ${project}`))
    
  25.       .split('\n')
    
  26.       .filter(owner => owner)
    
  27.       .map(owner => owner.split(' ')[0]);
    
  28. 
    
  29.     if (!owners.includes(currentUser)) {
    
  30.       failedProjects.push(project);
    
  31.     }
    
  32.   };
    
  33. 
    
  34.   await logger(
    
  35.     Promise.all(NPM_PACKAGES.map(checkProject)),
    
  36.     `Checking NPM permissions for ${chalk.bold(currentUser)}.`,
    
  37.     {estimate: 2500}
    
  38.   );
    
  39. 
    
  40.   console.log('');
    
  41. 
    
  42.   if (failedProjects.length) {
    
  43.     console.error(chalk.red.bold('Insufficient NPM permissions'));
    
  44.     console.error('');
    
  45.     console.error(
    
  46.       chalk.red(
    
  47.         `NPM user {underline ${currentUser}} is not an owner for: ${chalk.bold(
    
  48.           failedProjects.join(', ')
    
  49.         )}`
    
  50.       )
    
  51.     );
    
  52.     console.error(
    
  53.       chalk.red(
    
  54.         'Please contact a React team member to be added to the above project(s).'
    
  55.       )
    
  56.     );
    
  57.     process.exit(1);
    
  58.   }
    
  59. }
    
  60. 
    
  61. function clear() {
    
  62.   console.clear();
    
  63. }
    
  64. 
    
  65. async function confirm(message, exitFunction) {
    
  66.   console.log('');
    
  67. 
    
  68.   const {confirmation} = await inquirer.prompt({
    
  69.     name: 'confirmation',
    
  70.     type: 'confirm',
    
  71.     message,
    
  72.   });
    
  73. 
    
  74.   console.log('');
    
  75. 
    
  76.   if (!confirmation) {
    
  77.     if (typeof exitFunction === 'function') {
    
  78.       exitFunction();
    
  79.     }
    
  80. 
    
  81.     process.exit(0);
    
  82.   }
    
  83. }
    
  84. 
    
  85. async function confirmContinue(exitFunction) {
    
  86.   await confirm('Continue the release?', exitFunction);
    
  87. }
    
  88. 
    
  89. async function execRead(command, options) {
    
  90.   const {stdout} = await exec(command, options);
    
  91. 
    
  92.   return stdout.trim();
    
  93. }
    
  94. 
    
  95. function readSavedBuildMetadata() {
    
  96.   const path = join(BUILD_METADATA_TEMP_DIRECTORY, 'metadata');
    
  97. 
    
  98.   if (!existsSync(path)) {
    
  99.     console.error(chalk.red('Expected to find build metadata at:'));
    
  100.     console.error(chalk.dim(`  ${path}`));
    
  101.     process.exit(1);
    
  102.   }
    
  103. 
    
  104.   const {archivePath, buildID} = readJsonSync(path);
    
  105. 
    
  106.   return {archivePath, buildID};
    
  107. }
    
  108. 
    
  109. function saveBuildMetadata({archivePath, buildID}) {
    
  110.   const path = join(BUILD_METADATA_TEMP_DIRECTORY, 'metadata');
    
  111. 
    
  112.   if (!existsSync(BUILD_METADATA_TEMP_DIRECTORY)) {
    
  113.     mkdirSync(BUILD_METADATA_TEMP_DIRECTORY);
    
  114.   }
    
  115. 
    
  116.   writeJsonSync(path, {archivePath, buildID}, {spaces: 2});
    
  117. }
    
  118. 
    
  119. module.exports = {
    
  120.   checkNPMPermissions,
    
  121.   clear,
    
  122.   confirm,
    
  123.   confirmContinue,
    
  124.   execRead,
    
  125.   logger,
    
  126.   readSavedBuildMetadata,
    
  127.   saveBuildMetadata,
    
  128. };