diff --git a/ng-dev/auth/shared/ng-dev-token.ts b/ng-dev/auth/shared/ng-dev-token.ts index 0958af13c..a72cc96ce 100644 --- a/ng-dev/auth/shared/ng-dev-token.ts +++ b/ng-dev/auth/shared/ng-dev-token.ts @@ -7,6 +7,7 @@ import {randomBytes, createCipheriv, createDecipheriv, createHash} from 'crypto' import {RawData, WebSocket} from 'ws'; import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client.js'; import {assertValidGithubConfig, getConfig} from '../../utils/config.js'; +import {registerCompletedFunction} from '../../utils/yargs.js'; /** Algorithm to use for encryption. */ const algorithm = 'aes-256-ctr'; @@ -155,6 +156,9 @@ export function configureAuthorizedGitClientWithTemporaryToken() { }, }); + // Close the socket whenever the command which established it is complete. + registerCompletedFunction(() => socket.close()); + // When the token is provided via the websocket message, use the token to set up // the AuthenticatedGitClient. The token is valid as long as the socket remains open, // with the server emposing a limit of 1 hour. diff --git a/ng-dev/cli.ts b/ng-dev/cli.ts index 10a16a143..ce1ed983c 100644 --- a/ng-dev/cli.ts +++ b/ng-dev/cli.ts @@ -7,7 +7,7 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import yargs from 'yargs'; +import {runParserWithCompletedFunctions} from './utils/yargs.js'; import {buildCaretakerParser} from './caretaker/cli.js'; import {buildCiParser} from './ci/cli.js'; @@ -21,23 +21,25 @@ import {buildReleaseParser} from './release/cli.js'; import {tsCircularDependenciesBuilder} from './ts-circular-dependencies/index.js'; import {captureLogOutputForCommand} from './utils/logging.js'; import {buildAuthParser} from './auth/cli.js'; +import {Argv} from 'yargs'; -yargs(process.argv.slice(2)) - .scriptName('ng-dev') - .middleware(captureLogOutputForCommand) - .demandCommand() - .recommendCommands() - .command('auth ', false, buildAuthParser) - .command('commit-message ', '', buildCommitMessageParser) - .command('format ', '', buildFormatParser) - .command('pr ', '', buildPrParser) - .command('pullapprove ', '', buildPullapproveParser) - .command('release ', '', buildReleaseParser) - .command('ts-circular-deps ', '', tsCircularDependenciesBuilder) - .command('caretaker ', '', buildCaretakerParser) - .command('misc ', '', buildMiscParser) - .command('ngbot ', false, buildNgbotParser) - .command('ci ', false, buildCiParser) - .wrap(120) - .strict() - .parse(); +runParserWithCompletedFunctions((yargs: Argv) => { + return yargs + .scriptName('ng-dev') + .middleware(captureLogOutputForCommand) + .demandCommand() + .recommendCommands() + .command('auth ', false, buildAuthParser) + .command('commit-message ', '', buildCommitMessageParser) + .command('format ', '', buildFormatParser) + .command('pr ', '', buildPrParser) + .command('pullapprove ', '', buildPullapproveParser) + .command('release ', '', buildReleaseParser) + .command('ts-circular-deps ', '', tsCircularDependenciesBuilder) + .command('caretaker ', '', buildCaretakerParser) + .command('misc ', '', buildMiscParser) + .command('ngbot ', false, buildNgbotParser) + .command('ci ', false, buildCiParser) + .wrap(120) + .strict(); +}); diff --git a/ng-dev/utils/yargs.ts b/ng-dev/utils/yargs.ts new file mode 100644 index 000000000..13a5fd32f --- /dev/null +++ b/ng-dev/utils/yargs.ts @@ -0,0 +1,26 @@ +import yargs, {Argv} from 'yargs'; + +// A function to be called when the command completes. +type CompletedFn = (err: Error | null) => Promise | void; + +/** List of functions to be called upon command completion. */ +const completedFunctions: CompletedFn[] = []; + +/** Register a function to be called when the command completes. */ +export function registerCompletedFunction(fn: CompletedFn) { + completedFunctions.push(fn); +} + +/** + * Run the yargs process, as configured by the supplied function, calling a set of completion + * functions after the command completes. + */ +export function runParserWithCompletedFunctions(applyConfiguration: (argv: Argv) => Argv) { + applyConfiguration(yargs(process.argv.slice(2))) + .exitProcess(false) + .parse(process.argv.slice(2), async (err: Error | null) => { + for (const completedFunc of completedFunctions) { + await completedFunc(err); + } + }); +}