Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/eighty-spoons-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'create-amplify': patch
'@aws-amplify/cli-core': patch
'@aws-amplify/backend-cli': patch
---

Handle uncaught exception in create-amplify and refactor the error handler to cli-core
23 changes: 17 additions & 6 deletions packages/cli-core/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
```ts

import { AmplifyIOHost } from '@aws-amplify/plugin-types';
import { Argv } from 'yargs';
import { PackageManagerController } from '@aws-amplify/plugin-types';
import { UsageDataEmitter } from '@aws-amplify/platform-core';
import { WriteStream } from 'node:tty';
import z from 'zod';

Expand Down Expand Up @@ -33,12 +35,18 @@ export class AmplifyPrompter {
}) => Promise<boolean>;
}

// @public
export const attachUnhandledExceptionListeners: (usageDataEmitter?: UsageDataEmitter) => void;

// @public (undocumented)
export type ColorName = (typeof colorNames)[number];

// @public (undocumented)
export const colorNames: readonly ["Green", "Yellow", "Blue", "Magenta", "Cyan", "Red"];

// @public
export const extractSubCommands: (yargs: Argv) => string | undefined;

// @public
export class Format {
constructor(packageManagerRunnerName?: string);
Expand Down Expand Up @@ -75,6 +83,9 @@ export class Format {
// @public (undocumented)
export const format: Format;

// @public
export const generateCommandFailureHandler: (parser?: Argv, usageDataEmitter?: UsageDataEmitter) => ((message: string, error: Error) => Promise<void>);

// @public (undocumented)
export enum LogLevel {
// (undocumented)
Expand Down Expand Up @@ -185,7 +196,7 @@ export const noticeSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}, {
Expand Down Expand Up @@ -213,7 +224,7 @@ export const noticeSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}>;
Expand Down Expand Up @@ -314,7 +325,7 @@ export const noticesManifestSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}, {
Expand Down Expand Up @@ -342,7 +353,7 @@ export const noticesManifestSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}>, "many">;
Expand Down Expand Up @@ -372,7 +383,7 @@ export const noticesManifestSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}[];
Expand Down Expand Up @@ -402,7 +413,7 @@ export const noticesManifestSchema: z.ZodObject<{
errorMessage: string;
})[];
link?: string | undefined;
frequency?: "once" | "command" | "deployment" | "daily" | undefined;
frequency?: "command" | "once" | "deployment" | "daily" | undefined;
validFrom?: number | undefined;
validTo?: number | undefined;
}[];
Expand Down
3 changes: 2 additions & 1 deletion packages/cli-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"strip-ansi": "^7.1.0",
"wrap-ansi": "^9.0.0",
"semver": "^7.6.3",
"zod": "3.25.17"
"zod": "3.25.17",
"yargs": "^17.7.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
generateCommandFailureHandler,
} from './error_handler.js';
import { Argv } from 'yargs';
import { LogLevel, format, printer } from '@aws-amplify/cli-core';
import { format } from './format/format.js';
import { LogLevel } from './printer/printer.js';
import { printer } from './printer.js';
import assert from 'node:assert';
import { AmplifyUserError, UsageDataEmitter } from '@aws-amplify/platform-core';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { LogLevel, format, printer } from '@aws-amplify/cli-core';
import { format } from './format/format.js';
import { LogLevel } from './printer/printer.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';
Expand All @@ -17,7 +19,7 @@ type HandleErrorProps = {
* Attaches process listeners to handle unhandled exceptions and rejections
*/
export const attachUnhandledExceptionListeners = (
usageDataEmitter: UsageDataEmitter,
usageDataEmitter?: UsageDataEmitter,
): void => {
if (hasAttachUnhandledExceptionListenersBeenCalled) {
return;
Expand Down Expand Up @@ -54,7 +56,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<void>) => {
/**
Expand All @@ -63,19 +65,29 @@ 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));
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;
};
Expand Down
2 changes: 2 additions & 0 deletions packages/cli-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export * from './package-manager-controller/package_manager_controller_factory.j
export * from './loggers/amplify_io_events_bridge_singleton_factory.js';
export * from './notices/notices.js';
export * from './notices/notices_manifest_validator.js';
export * from './error_handler.js';
export * from './extract_sub_commands.js';
13 changes: 7 additions & 6 deletions packages/cli/src/ampx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ import {
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';
import { createMainParser } from './main_parser_factory.js';
import {
attachUnhandledExceptionListeners,
generateCommandFailureHandler,
} from './error_handler.js';
import { extractSubCommands } from './extract_sub_commands.js';
import {
AmplifyFault,
PackageJsonReader,
Expand All @@ -25,7 +20,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';
import { NoticesRenderer } from './notices/notices_renderer.js';
import { extractCommandInfo } from './extract_command_info.js';
import { DeepPartial } from '@aws-amplify/plugin-types';
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/test-utils/command_runner.ts
Original file line number Diff line number Diff line change
@@ -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 = '';
Expand Down
40 changes: 22 additions & 18 deletions packages/create-amplify/src/create_amplify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,41 @@
*/

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';
import { getProjectRoot } from './get_project_root.js';
import { GitIgnoreInitializer } from './gitignore_initializer.js';
import { InitialProjectFileGenerator } from './initial_project_file_generator.js';

const projectRoot = await getProjectRoot();
attachUnhandledExceptionListeners();
const errorHandler = generateCommandFailureHandler();

const packageManagerControllerFactory = new PackageManagerControllerFactory(
projectRoot,
);
try {
const projectRoot = await getProjectRoot();

const packageManagerController =
packageManagerControllerFactory.getPackageManagerController();
const packageManagerControllerFactory = new PackageManagerControllerFactory(
projectRoot,
);

const amplifyProjectCreator = new AmplifyProjectCreator(
projectRoot,
packageManagerController,
new ProjectRootValidator(projectRoot),
new GitIgnoreInitializer(projectRoot),
new InitialProjectFileGenerator(projectRoot, packageManagerController),
);
const packageManagerController =
packageManagerControllerFactory.getPackageManagerController();

const amplifyProjectCreator = new AmplifyProjectCreator(
projectRoot,
packageManagerController,
new ProjectRootValidator(projectRoot),
new GitIgnoreInitializer(projectRoot),
new InitialProjectFileGenerator(projectRoot, packageManagerController),
);

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);
}
}
Loading