1'use strict' 2 3/** 4 * Usage: 5 * 6 * node scripts/update-dist-tags.js --otp <one-time password> 7 * node scripts/update-dist-tags.js --otp=<one-time password> 8 * node scripts/update-dist-tags.js --otp<one-time password> 9 */ 10 11const usage = ` 12Usage: 13 14node scripts/update-dist-tags.js --otp <one-time password> 15node scripts/update-dist-tags.js --otp=<one-time password> 16node scripts/update-dist-tags.js --otp<one-time password> 17` 18 19const { execSync } = require('child_process') 20const semver = require('semver') 21const path = require('path') 22 23const getMajorVersion = (input) => semver.parse(input).major 24const getMinorVersion = (input) => semver.parse(input).minor 25 26// INFO: String templates to generate the tags to update 27const LATEST_TAG = (strings, major) => `latest-${major}` 28const NEXT_TAG = (strings, major) => `next-${major}` 29const TAG_LIST = ['lts', 'next', 'latest'] 30const REMOVE_TAG = (strings, major, minor) => `v${major}.${minor}-next` 31 32// INFO: Finds `--otp` and subsequently otp value (if present) 33const PARSE_OTP_FLAG = new RegExp(/(--otp)(=|\s)?([0-9]{6})?/, 'gm') 34// INFO: Used to validate otp value (if not found by other regexp) 35const PARSE_OTP_VALUE = new RegExp(/^[0-9]{6}$/, 'g') 36 37const args = process.argv.slice(2) 38const versionPath = path.resolve(__dirname, '..', 'package.json') 39const { version } = require(versionPath) 40 41// Run Script 42main() 43 44function main () { 45 const otp = parseOTP(args) 46 if (version) { 47 const major = getMajorVersion(version) 48 const minor = getMinorVersion(version) 49 const latestTag = LATEST_TAG`${major}` 50 const nextTag = NEXT_TAG`${major}` 51 const removeTag = REMOVE_TAG`${major}${minor}` 52 const updateList = [].concat(TAG_LIST, latestTag, nextTag) 53 54 updateList.forEach((tag) => { 55 setDistTag(tag, version, otp) 56 }) 57 removeDistTag(removeTag, version, otp) 58 } else { 59 console.error('Invalid semver.') 60 process.exit(1) 61 } 62} 63 64function parseOTP (args) { 65 // NOTE: making assumption first _thing_ is a string with "--otp" in it 66 const parsedArgs = PARSE_OTP_FLAG.exec(args[0]) 67 if (!parsedArgs) { 68 console.error('Invalid arguments supplied. Must supply --otp flag.') 69 console.error(usage) 70 process.exit(1) 71 } 72 // INFO: From the regexp, third group is the OTP code 73 const otp = parsedArgs[3] 74 switch (args.length) { 75 case 0: { 76 console.error('No arguments supplied.') 77 console.error(usage) 78 process.exit(1) 79 } 80 case 1: { 81 // --otp=123456 or --otp123456 82 if (otp) { 83 return otp 84 } 85 console.error('Invalid otp value supplied. [CASE 1]') 86 process.exit(1) 87 } 88 case 2: { 89 // --otp 123456 90 // INFO: validating the second argument is an otp code 91 const isValidOtp = PARSE_OTP_VALUE.test(args[1]) 92 if (isValidOtp) { 93 return args[1] 94 } 95 console.error('Invalid otp value supplied. [CASE 2]') 96 process.exit(1) 97 } 98 default: { 99 console.error('Invalid arguments supplied.') 100 process.exit(1) 101 } 102 } 103} 104 105function setDistTag (tag, version, otp) { 106 try { 107 const result = execSync(`npm dist-tag set npm@${version} ${tag} --otp=${otp}`, { encoding: 'utf-8' }) 108 console.log('Result:', result) 109 } catch (err) { 110 console.error('Bad dist-tag command.') 111 process.exit(1) 112 } 113} 114 115function removeDistTag (tag, version, otp) { 116 try { 117 const result = execSync(`npm dist-tag rm npm ${tag} --otp=${otp}`, { encoding: 'utf-8' }) 118 console.log('Result:', result) 119 } catch (err) { 120 console.error('Bad dist-tag command.') 121 process.exit(1) 122 } 123} 124