diff --git a/.changeset/happy-students-stare.md b/.changeset/happy-students-stare.md new file mode 100644 index 0000000000..a61aba1f50 --- /dev/null +++ b/.changeset/happy-students-stare.md @@ -0,0 +1,5 @@ +--- +'create-amplify': patch +--- + +add process handler to gracefully exit when Ctrl + C. See Issue #825. diff --git a/packages/cli-core/package.json b/packages/cli-core/package.json index 266bbd5932..4eee7390c2 100644 --- a/packages/cli-core/package.json +++ b/packages/cli-core/package.json @@ -23,6 +23,7 @@ "@inquirer/prompts": "^3.0.0", "execa": "^9.5.1", "kleur": "^4.1.5", - "zod": "^3.22.2" + "zod": "^3.22.2", + "yargs": "^17.7.2" } } diff --git a/packages/cli/src/error_handler.test.ts b/packages/cli-core/src/error_handler.test.ts similarity index 98% rename from packages/cli/src/error_handler.test.ts rename to packages/cli-core/src/error_handler.test.ts index 2285878283..3548de1622 100644 --- a/packages/cli/src/error_handler.test.ts +++ b/packages/cli-core/src/error_handler.test.ts @@ -4,7 +4,8 @@ import { generateCommandFailureHandler, } from './error_handler.js'; import { Argv } from 'yargs'; -import { LogLevel, printer } from '@aws-amplify/cli-core'; +import { LogLevel } from './printer/printer.js'; +import { printer } from './printer.js'; import assert from 'node:assert'; import { AmplifyUserError, UsageDataEmitter } from '@aws-amplify/platform-core'; diff --git a/packages/cli/src/error_handler.ts b/packages/cli-core/src/error_handler.ts similarity index 87% rename from packages/cli/src/error_handler.ts rename to packages/cli-core/src/error_handler.ts index 806020e986..53b5c5db88 100644 --- a/packages/cli/src/error_handler.ts +++ b/packages/cli-core/src/error_handler.ts @@ -1,4 +1,7 @@ -import { LogLevel, format, printer } from '@aws-amplify/cli-core'; +import { LogLevel } from './printer/printer.js'; +import { format } from './format/format.js'; +import { printer } from './printer.js'; + import { Argv } from 'yargs'; import { AmplifyError, UsageDataEmitter } from '@aws-amplify/platform-core'; import { extractSubCommands } from './extract_sub_commands.js'; @@ -17,7 +20,7 @@ type HandleErrorProps = { * Attaches process listeners to handle unhandled exceptions and rejections */ export const attachUnhandledExceptionListeners = ( - usageDataEmitter: UsageDataEmitter + usageDataEmitter?: UsageDataEmitter ): void => { if (hasAttachUnhandledExceptionListenersBeenCalled) { return; @@ -54,7 +57,7 @@ export const attachUnhandledExceptionListeners = ( * This prevents our top-level error handler from being invoked after the yargs error handler has already been invoked */ export const generateCommandFailureHandler = ( - parser: Argv, + parser?: Argv, usageDataEmitter?: UsageDataEmitter ): ((message: string, error: Error) => Promise) => { /** @@ -63,19 +66,30 @@ export const generateCommandFailureHandler = ( * @param error error thrown by yargs handler */ const handleCommandFailure = async (message: string, error?: Error) => { - const printHelp = () => { - printer.printNewLine(); - parser.showHelp(); - printer.printNewLine(); - }; - await handleErrorSafe({ - command: extractSubCommands(parser), - printMessagePreamble: printHelp, - error, - message, - usageDataEmitter, - }); - parser.exit(1, error || new Error(message)); + // create-amplify command + if (!parser) { + await handleErrorSafe({ + error, + message, + }); + } + + // for ampx commands + if (parser) { + const printHelp = () => { + printer.printNewLine(); + parser.showHelp(); + printer.printNewLine(); + }; + await handleErrorSafe({ + command: extractSubCommands(parser), + printMessagePreamble: printHelp, + error, + message, + usageDataEmitter, + }); + parser.exit(1, error || new Error(message)); + } }; return handleCommandFailure; }; diff --git a/packages/cli/src/extract_sub_commands.ts b/packages/cli-core/src/extract_sub_commands.ts similarity index 100% rename from packages/cli/src/extract_sub_commands.ts rename to packages/cli-core/src/extract_sub_commands.ts diff --git a/packages/cli-core/src/index.ts b/packages/cli-core/src/index.ts index e9057b6ee4..4b04e5abc8 100644 --- a/packages/cli-core/src/index.ts +++ b/packages/cli-core/src/index.ts @@ -3,3 +3,5 @@ export * from './printer/printer.js'; export * from './printer.js'; export { ColorName, colorNames, format, Format } from './format/format.js'; export * from './package-manager-controller/package_manager_controller_factory.js'; +export * from './error_handler.js'; +export * from './extract_sub_commands.js'; diff --git a/packages/cli/src/ampx.ts b/packages/cli/src/ampx.ts index c9448a58d1..773b291b2b 100755 --- a/packages/cli/src/ampx.ts +++ b/packages/cli/src/ampx.ts @@ -1,10 +1,5 @@ #!/usr/bin/env node import { createMainParser } from './main_parser_factory.js'; -import { - attachUnhandledExceptionListeners, - generateCommandFailureHandler, -} from './error_handler.js'; -import { extractSubCommands } from './extract_sub_commands.js'; import { AmplifyFault, PackageJsonReader, @@ -13,7 +8,13 @@ import { import { fileURLToPath } from 'node:url'; import { verifyCommandName } from './verify_command_name.js'; import { hideBin } from 'yargs/helpers'; -import { PackageManagerControllerFactory, format } from '@aws-amplify/cli-core'; +import { + PackageManagerControllerFactory, + attachUnhandledExceptionListeners, + extractSubCommands, + format, + generateCommandFailureHandler, +} from '@aws-amplify/cli-core'; const packageJson = new PackageJsonReader().read( fileURLToPath(new URL('../package.json', import.meta.url)) diff --git a/packages/cli/src/test-utils/command_runner.ts b/packages/cli/src/test-utils/command_runner.ts index 823190bd08..d9cf2fc7fd 100644 --- a/packages/cli/src/test-utils/command_runner.ts +++ b/packages/cli/src/test-utils/command_runner.ts @@ -1,8 +1,10 @@ import { Argv } from 'yargs'; import { AsyncLocalStorage } from 'node:async_hooks'; import { UsageDataEmitter } from '@aws-amplify/platform-core'; -import { generateCommandFailureHandler } from '../error_handler.js'; -import { extractSubCommands } from '../extract_sub_commands.js'; +import { + extractSubCommands, + generateCommandFailureHandler, +} from '@aws-amplify/cli-core'; class OutputInterceptor { private output = ''; diff --git a/packages/client-config/API.md b/packages/client-config/API.md index cccafacd46..9d784bff52 100644 --- a/packages/client-config/API.md +++ b/packages/client-config/API.md @@ -627,7 +627,7 @@ export type CustomClientConfig = { export const DEFAULT_CLIENT_CONFIG_VERSION: ClientConfigVersion; // @public -export const generateClientConfig: (backendIdentifier: DeployedBackendIdentifier, version: T, awsClientProvider?: AWSClientProvider<{ +export const generateClientConfig: (backendIdentifier: DeployedBackendIdentifier, version: T, awsClientProvider?: AWSClientProvider<{ getS3Client: S3Client; getAmplifyClient: AmplifyClient; getCloudFormationClient: CloudFormationClient; diff --git a/packages/create-amplify/src/create_amplify.ts b/packages/create-amplify/src/create_amplify.ts index 3608268be7..5459bf4fcd 100644 --- a/packages/create-amplify/src/create_amplify.ts +++ b/packages/create-amplify/src/create_amplify.ts @@ -8,10 +8,10 @@ */ import { - LogLevel, PackageManagerControllerFactory, + attachUnhandledExceptionListeners, format, - printer, + generateCommandFailureHandler, } from '@aws-amplify/cli-core'; import { ProjectRootValidator } from './project_root_validator.js'; import { AmplifyProjectCreator } from './amplify_project_creator.js'; @@ -19,6 +19,9 @@ import { getProjectRoot } from './get_project_root.js'; import { GitIgnoreInitializer } from './gitignore_initializer.js'; import { InitialProjectFileGenerator } from './initial_project_file_generator.js'; +attachUnhandledExceptionListeners(); +const errorHandler = generateCommandFailureHandler(); + const projectRoot = await getProjectRoot(); const packageManagerControllerFactory = new PackageManagerControllerFactory( @@ -39,6 +42,7 @@ const amplifyProjectCreator = new AmplifyProjectCreator( try { await amplifyProjectCreator.create(); } catch (err) { - printer.log(format.error(err), LogLevel.ERROR); - process.exitCode = 1; + if (err instanceof Error) { + await errorHandler(format.error(err), err); + } }