Skip to content

Commit

Permalink
chore: decentralize AmplifyErrorTypes (aws-amplify#1019)
Browse files Browse the repository at this point in the history
* chore: decentralize AmplifyErrorTypes

* add types

* update changeset

* adding default to AmplifyError

* update api.md
  • Loading branch information
bombguy authored Feb 13, 2024
1 parent f2c5c47 commit 74cbda0
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 88 deletions.
7 changes: 7 additions & 0 deletions .changeset/eighty-rings-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@aws-amplify/backend-deployer': patch
'@aws-amplify/backend-data': patch
'@aws-amplify/platform-core': minor
---

decentralize AmplifyErrorType
8 changes: 4 additions & 4 deletions packages/backend-data/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { AmplifyData } from '@aws-amplify/data-construct';
import { GraphqlOutput } from '@aws-amplify/backend-output-schemas';
import * as path from 'path';
import { DataProps } from './types.js';
import { AmplifyDataError, DataProps } from './types.js';
import { convertSchemaToCDK } from './convert_schema.js';
import {
FunctionInstanceProvider,
Expand Down Expand Up @@ -90,7 +90,7 @@ class DataGenerator implements ConstructContainerEntryGenerator {
this.props.authorizationModes
);
} catch (error) {
throw new AmplifyUserError(
throw new AmplifyUserError<AmplifyDataError>(
'InvalidSchemaAuthError',
{
message:
Expand All @@ -108,7 +108,7 @@ class DataGenerator implements ConstructContainerEntryGenerator {
authorizationModes
);
} catch (error) {
throw new AmplifyUserError(
throw new AmplifyUserError<AmplifyDataError>(
'InvalidSchemaAuthError',
{
message:
Expand All @@ -134,7 +134,7 @@ class DataGenerator implements ConstructContainerEntryGenerator {
try {
amplifyGraphqlDefinition = convertSchemaToCDK(this.props.schema);
} catch (error) {
throw new AmplifyUserError(
throw new AmplifyUserError<AmplifyDataError>(
'InvalidSchemaError',
{
message:
Expand Down
2 changes: 2 additions & 0 deletions packages/backend-data/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,5 @@ export type DataProps = {
*/
functions?: Record<string, ConstructFactory<AmplifyFunction>>;
};

export type AmplifyDataError = 'InvalidSchemaAuthError' | 'InvalidSchemaError';
4 changes: 2 additions & 2 deletions packages/backend-deployer/src/cdk_deployer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CDKDeployer } from './cdk_deployer.js';
import assert from 'node:assert';
import { AmplifyError, BackendLocator } from '@aws-amplify/platform-core';
import { DeployProps } from './cdk_deployer_singleton_factory.js';
import { CdkErrorMapper } from './cdk_error_mapper.js';
import { CDKDeploymentError, CdkErrorMapper } from './cdk_error_mapper.js';
import {
BackendIdentifier,
PackageManagerController,
Expand Down Expand Up @@ -284,7 +284,7 @@ void describe('invokeCDKCommand', () => {

await assert.rejects(
() => invoker.deploy(branchBackendId, sandboxDeployProps),
(err: AmplifyError) => {
(err: AmplifyError<CDKDeploymentError>) => {
assert.equal(
err.message,
'The deployment role does not have sufficient permissions to perform this deployment.'
Expand Down
4 changes: 2 additions & 2 deletions packages/backend-deployer/src/cdk_deployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
DeployResult,
DestroyResult,
} from './cdk_deployer_singleton_factory.js';
import { CdkErrorMapper } from './cdk_error_mapper.js';
import { CDKDeploymentError, CdkErrorMapper } from './cdk_error_mapper.js';
import {
BackendIdentifier,
type PackageManagerController,
Expand Down Expand Up @@ -153,7 +153,7 @@ export class CDKDeployer implements BackendDeployer {
dirname(this.backendLocator.locate()),
]);
} catch (err) {
throw new AmplifyUserError(
throw new AmplifyUserError<CDKDeploymentError>(
'SyntaxError',
{
message:
Expand Down
26 changes: 18 additions & 8 deletions packages/backend-deployer/src/cdk_error_mapper.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import {
AmplifyError,
AmplifyErrorClassification,
AmplifyErrorType,
AmplifyFault,
AmplifyLibraryFaultType,
AmplifyUserError,
AmplifyUserErrorType,
} from '@aws-amplify/platform-core';

/**
* Transforms CDK error messages to human readable ones
*/
export class CdkErrorMapper {
private knownErrors: Array<{
errorRegex: RegExp;
humanReadableErrorMessage: string;
errorName: AmplifyErrorType;
errorName: CDKDeploymentError;
classification: AmplifyErrorClassification;
}> = [
{
Expand Down Expand Up @@ -96,7 +92,9 @@ export class CdkErrorMapper {
},
];

getAmplifyError = (error: Error): AmplifyError => {
getAmplifyError = (
error: Error
): AmplifyError<CDKDeploymentError | string> => {
// Check if there was an Amplify error thrown during child process execution
const amplifyError = AmplifyError.fromStderr(error.message);
if (amplifyError) {
Expand All @@ -117,16 +115,28 @@ export class CdkErrorMapper {

return matchingError.classification === 'ERROR'
? new AmplifyUserError(
matchingError.errorName as AmplifyUserErrorType,
matchingError.errorName,
{ message: matchingError.humanReadableErrorMessage },
error
)
: new AmplifyFault(
matchingError.errorName as AmplifyLibraryFaultType,
matchingError.errorName,
{ message: matchingError.humanReadableErrorMessage },
error
);
}
return AmplifyError.fromError(error);
};
}

export type CDKDeploymentError =
| 'ExpiredTokenError'
| 'AccessDeniedError'
| 'BootstrapNotDetectedError'
| 'SyntaxError'
| 'FileConventionError'
| 'FileConventionError'
| 'BackendBuildError'
| 'CFNUpdateNotSupportedError'
| 'CFNUpdateNotSupportedError'
| 'CloudFormationDeploymentError';
25 changes: 8 additions & 17 deletions packages/platform-core/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { BackendIdentifier } from '@aws-amplify/plugin-types';
import z from 'zod';

// @public
export abstract class AmplifyError extends Error {
constructor(name: AmplifyErrorType, classification: AmplifyErrorClassification, options: AmplifyErrorOptions, cause?: Error | undefined);
export abstract class AmplifyError<T extends string = string> extends Error {
constructor(name: T, classification: AmplifyErrorClassification, options: AmplifyErrorOptions, cause?: Error | undefined);
// (undocumented)
readonly cause?: Error | undefined;
// (undocumented)
Expand All @@ -20,15 +20,15 @@ export abstract class AmplifyError extends Error {
// (undocumented)
readonly details?: string;
// (undocumented)
static fromError: (error: unknown) => AmplifyError;
static fromError: (error: unknown) => AmplifyError<'UnknownFault'>;
// (undocumented)
static fromStderr: (_stderr: string) => AmplifyError | undefined;
// (undocumented)
readonly link?: string;
// (undocumented)
readonly message: string;
// (undocumented)
readonly name: AmplifyErrorType;
readonly name: T;
// (undocumented)
readonly resolution?: string;
// (undocumented)
Expand All @@ -48,24 +48,15 @@ export type AmplifyErrorOptions = {
};

// @public
export type AmplifyErrorType = AmplifyUserErrorType | AmplifyLibraryFaultType;

// @public
export class AmplifyFault extends AmplifyError {
constructor(name: AmplifyLibraryFaultType, options: AmplifyErrorOptions, cause?: Error);
export class AmplifyFault<T extends string = string> extends AmplifyError<T> {
constructor(name: T, options: AmplifyErrorOptions, cause?: Error);
}

// @public
export type AmplifyLibraryFaultType = 'UnknownFault';

// @public
export class AmplifyUserError extends AmplifyError {
constructor(name: AmplifyUserErrorType, options: AmplifyErrorOptions, cause?: Error);
export class AmplifyUserError<T extends string = string> extends AmplifyError<T> {
constructor(name: T, options: AmplifyErrorOptions, cause?: Error);
}

// @public
export type AmplifyUserErrorType = 'InvalidPackageJsonError' | 'InvalidSchemaAuthError' | 'InvalidSchemaError' | 'ExpiredTokenError' | 'CloudFormationDeploymentError' | 'CFNUpdateNotSupportedError' | 'SyntaxError' | 'BackendBuildError' | 'BootstrapNotDetectedError' | 'AccessDeniedError' | 'FileConventionError' | 'OutputEntryAlreadyExistsError' | 'InvalidResourceNameError';

// @public
export class BackendIdentifierConversions {
static fromStackName(stackName?: string): BackendIdentifier | undefined;
Expand Down
38 changes: 5 additions & 33 deletions packages/platform-core/src/errors/amplify_error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AmplifyFault, AmplifyUserError } from '.';
/**
* Base class for all Amplify errors or faults
*/
export abstract class AmplifyError extends Error {
export abstract class AmplifyError<T extends string = string> extends Error {
public serializedError?: string;
public readonly message: string;
public readonly resolution?: string;
Expand All @@ -26,7 +26,7 @@ export abstract class AmplifyError extends Error {
* }
*/
constructor(
public readonly name: AmplifyErrorType,
public readonly name: T,
public readonly classification: AmplifyErrorClassification,
private readonly options: AmplifyErrorOptions,
public readonly cause?: Error
Expand Down Expand Up @@ -64,8 +64,8 @@ export abstract class AmplifyError extends Error {
serialized[1]
);
return classification === 'ERROR'
? new AmplifyUserError(name as AmplifyUserErrorType, options, cause)
: new AmplifyFault(name as AmplifyLibraryFaultType, options, cause);
? new AmplifyUserError(name, options, cause)
: new AmplifyFault(name, options, cause);
} catch (error) {
// cannot deserialize
return undefined;
Expand All @@ -74,7 +74,7 @@ export abstract class AmplifyError extends Error {
return undefined;
};

static fromError = (error: unknown): AmplifyError => {
static fromError = (error: unknown): AmplifyError<'UnknownFault'> => {
const errorMessage =
error instanceof Error
? `${error.name}: ${error.message}`
Expand Down Expand Up @@ -107,31 +107,3 @@ export type AmplifyErrorOptions = {
// CloudFormation or NodeJS error codes
code?: string;
};

/**
* Amplify error types
*/
export type AmplifyErrorType = AmplifyUserErrorType | AmplifyLibraryFaultType;

/**
* Amplify error types
*/
export type AmplifyUserErrorType =
| 'InvalidPackageJsonError'
| 'InvalidSchemaAuthError'
| 'InvalidSchemaError'
| 'ExpiredTokenError'
| 'CloudFormationDeploymentError'
| 'CFNUpdateNotSupportedError'
| 'SyntaxError'
| 'BackendBuildError'
| 'BootstrapNotDetectedError'
| 'AccessDeniedError'
| 'FileConventionError'
| 'OutputEntryAlreadyExistsError'
| 'InvalidResourceNameError';

/**
* Amplify library fault types
*/
export type AmplifyLibraryFaultType = 'UnknownFault';
14 changes: 3 additions & 11 deletions packages/platform-core/src/errors/amplify_library_fault.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import {
AmplifyError,
AmplifyErrorOptions,
AmplifyLibraryFaultType,
} from './amplify_error';
import { AmplifyError, AmplifyErrorOptions } from './amplify_error';

/**
* Base class for all Amplify library faults
*/
export class AmplifyFault extends AmplifyError {
export class AmplifyFault<T extends string = string> extends AmplifyError<T> {
/**
* Create a new Amplify Library Fault
* @param name - a user friendly name for the exception
Expand All @@ -21,11 +17,7 @@ export class AmplifyFault extends AmplifyError {
* throw new AmplifyLibraryFault(error,...,...);
* }
*/
constructor(
name: AmplifyLibraryFaultType,
options: AmplifyErrorOptions,
cause?: Error
) {
constructor(name: T, options: AmplifyErrorOptions, cause?: Error) {
super(name, 'FAULT', options, cause);
}
}
16 changes: 5 additions & 11 deletions packages/platform-core/src/errors/amplify_user_error.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import {
AmplifyError,
AmplifyErrorOptions,
AmplifyUserErrorType,
} from './amplify_error';
import { AmplifyError, AmplifyErrorOptions } from './amplify_error';

/**
* Base class for all Amplify user errors
*/
export class AmplifyUserError extends AmplifyError {
export class AmplifyUserError<
T extends string = string
> extends AmplifyError<T> {
/**
* Create a new Amplify Error.
* @param name - a user friendly name for the user error
Expand All @@ -21,11 +19,7 @@ export class AmplifyUserError extends AmplifyError {
* throw new AmplifyError(...,...,error);
* }
*/
constructor(
name: AmplifyUserErrorType,
options: AmplifyErrorOptions,
cause?: Error
) {
constructor(name: T, options: AmplifyErrorOptions, cause?: Error) {
super(name, 'ERROR', options, cause);
}
}

0 comments on commit 74cbda0

Please sign in to comment.