Ensure all async functions handle errors properly
async function main() {
1#!/usr/bin/env node2/**3 * Copyright (c) Meta Platforms, Inc. and affiliates.4 *5 * This source code is licensed under the MIT license found in the6 * LICENSE file in the root directory of this source tree.7 */89'use strict';1011const ora = require('ora');12const path = require('path');13const yargs = require('yargs');14const {hashElement} = require('folder-hash');15const promptForOTP = require('./prompt-for-otp');16const {PUBLISHABLE_PACKAGES} = require('./shared/packages');17const {18 execHelper,19 getDateStringForCommit,20 spawnHelper,21} = require('./shared/utils');22const {buildPackages} = require('./shared/build-packages');23const {readJson, writeJson} = require('fs-extra');2425/**26 * Script for publishing PUBLISHABLE_PACKAGES to npm. By default, this runs in tarball mode, meaning27 * the script will only print out what the contents of the files included in the npm tarball would28 * be.29 *30 * Please run this first (ie `yarn npm:publish`) and double check the contents of the files that31 * will be pushed to npm.32 *33 * If it looks good, you can run `yarn npm:publish --for-real` to really publish to npm. You must34 * have 2FA enabled first and the script will prompt you to enter a 2FA code before proceeding.35 * There's a small annoying delay before the packages are actually pushed to give you time to panic36 * cancel. In this mode, we will bump the version field of each package's package.json, and git37 * commit it. Then, the packages will be published to npm.38 *39 * Optionally, you can add the `--debug` flag to `yarn npm:publish --debug --for-real` to run all40 * steps, but the final npm publish step will have the `--dry-run` flag added to it. This will make41 * the command only report what it would have done, instead of actually publishing to npm.42 */43async function main() {44 const argv = yargs(process.argv.slice(2))45 .option('packages', {46 description: 'which packages to publish, defaults to all',47 choices: PUBLISHABLE_PACKAGES,48 default: PUBLISHABLE_PACKAGES,49 })50 .option('for-real', {51 alias: 'frfr',52 description:53 'whether to publish to npm (npm publish) or dryrun (npm publish --dry-run)',54 type: 'boolean',55 default: false,56 })57 .option('debug', {58 description:59 'If enabled, will always run npm commands in dry run mode irregardless of the for-real flag',60 type: 'boolean',61 default: false,62 })63 .option('ci', {64 description: 'Publish packages via CI',65 type: 'boolean',66 default: false,67 })68 .option('tag', {69 description: 'Tag to publish to npm',70 type: 'choices',71 choices: ['experimental', 'beta', 'rc', 'latest'],72 default: 'experimental',73 })74 .option('tag-version', {75 description:76 'Optional tag version to append to tag name, eg `1` becomes 0.0.0-rc.1',77 type: 'number',78 default: null,79 })80 .option('version-name', {81 description: 'Version name',82 type: 'string',83 default: '0.0.0',84 })85 .help('help')86 .strict()87 .parseSync();8889 if (argv.debug === false) {90 const currBranchName = await execHelper('git rev-parse --abbrev-ref HEAD');91 const isPristine = (await execHelper('git status --porcelain')) === '';92 if (currBranchName !== 'main' || isPristine === false) {93 throw new Error(94 'This script must be run from the `main` branch with no uncommitted changes'95 );96 }97 }9899 let pkgNames = argv.packages;100 if (Array.isArray(argv.packages) === false) {101 pkgNames = [argv.packages];102 }103 const spinner = ora(104 `Preparing to publish ${argv.versionName}@${argv.tag} ${105 argv.forReal === true ? '(for real)' : '(dry run)'106 } [debug=${argv.debug}]`107 ).info();108109 await buildPackages(pkgNames);110111 if (argv.forReal === false) {112 spinner.info('Dry run: Report tarball contents');113 for (const pkgName of pkgNames) {114 console.log(`\n========== ${pkgName} ==========\n`);115 spinner.start(`Running npm pack --dry-run\n`);116 try {117 await spawnHelper('npm', ['pack', '--dry-run'], {118 cwd: path.resolve(__dirname, `../../packages/${pkgName}`),119 stdio: 'inherit',120 });121 } catch (e) {122 spinner.fail(e.toString());123 throw e;124 }125 spinner.stop(`Successfully packed ${pkgName} (dry run)`);126 }127 spinner.succeed(128 'Please confirm contents of packages before publishing. You can run this command again with --for-real to publish to npm'129 );130 }131132 if (argv.forReal === true) {133 const commit = await execHelper(134 'git show -s --no-show-signature --format=%h',135 {136 cwd: path.resolve(__dirname, '..'),137 }138 );139 const dateString = await getDateStringForCommit(commit);140 const otp =141 argv.ci === false && argv.debug === false ? await promptForOTP() : null;142 const {hash} = await hashElement(path.resolve(__dirname, '../..'), {143 encoding: 'hex',144 folders: {exclude: ['node_modules']},145 files: {exclude: ['.DS_Store']},146 });147 const truncatedHash = hash.slice(0, 7);148 let newVersion;149 if (argv.tag === 'latest') {150 newVersion = argv.versionName;151 } else {152 newVersion =153 argv.tagVersion == null || argv.tagVersion === ''154 ? `${argv.versionName}-${argv.tag}`155 : `${argv.versionName}-${argv.tag}.${argv.tagVersion}`;156 }157 if (argv.tag === 'experimental' || argv.tag === 'beta') {158 newVersion = `${newVersion}-${truncatedHash}-${dateString}`;159 }160161 for (const pkgName of pkgNames) {162 const pkgDir = path.resolve(__dirname, `../../packages/${pkgName}`);163 const pkgJsonPath = path.resolve(164 __dirname,165 `../../packages/${pkgName}/package.json`166 );167168 spinner.start(`Writing package.json for ${pkgName}@${newVersion}`);169 await writeJson(170 pkgJsonPath,171 {172 ...(await readJson(pkgJsonPath)),173 version: newVersion,174 },175 {spaces: 2}176 );177 spinner.succeed(`Wrote package.json for ${pkgName}@${newVersion}`);178179 console.log(`\n========== ${pkgName} ==========\n`);180 spinner.start(`Publishing ${pkgName}@${newVersion} to npm\n`);181182 let opts = [];183 if (argv.debug === true) {184 opts.push('--dry-run');185 }186 if (otp != null) {187 opts.push(`--otp=${otp}`);188 }189190 opts.push(`--tag=${argv.tag}`);191192 try {193 await spawnHelper(194 'npm',195 ['publish', ...opts, '--registry=https://registry.npmjs.org'],196 {197 cwd: pkgDir,198 stdio: 'inherit',199 }200 );201 console.log('\n');202 } catch (e) {203 spinner.fail(e.toString());204 throw e;205 }206 spinner.succeed(`Successfully published ${pkgName} to npm`);207208 spinner.start('Pushing tags to npm');209 if (typeof argv.tag === 'string') {210 try {211 let opts = ['dist-tag', 'add', `${pkgName}@${newVersion}`, argv.tag];212 if (otp != null) {213 opts.push(`--otp=${otp}`);214 }215 if (argv.debug === true) {216 spinner.info(`dry-run: npm ${opts.join(' ')}`);217 } else {218 await spawnHelper('npm', opts, {219 cwd: pkgDir,220 stdio: 'inherit',221 });222 }223 } catch (e) {224 spinner.fail(e.toString());225 throw e;226 }227 spinner.succeed(228 `Successfully pushed dist-tag ${argv.tag} for ${pkgName} to npm`229 );230 }231 }232233 console.log('\n\nā All done');234 }235}236237main();
Same data, no extra tab ā call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.