Skip to content

Commit 6a23634

Browse files
authored
feat(smithy-client): implement SdkException class (#3261)
* feat(smithy-client): add utils to inject unmodeled error members * feat(smithy-client): rename SdkException to ServiceException * docs(smithy-client): document SmithyException
1 parent 669d802 commit 6a23634

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

Diff for: packages/smithy-client/src/exceptions.spec.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { decorateServiceException, ServiceException } from "./exceptions";
2+
3+
it("ServiceException extends from Error", () => {
4+
expect(
5+
new ServiceException({
6+
name: "Error",
7+
message: "",
8+
$fault: "client",
9+
$metadata: {},
10+
})
11+
).toBeInstanceOf(Error);
12+
});
13+
14+
describe("decorateServiceException", () => {
15+
const exception = new ServiceException({
16+
name: "Error",
17+
message: "Error",
18+
$fault: "client",
19+
$metadata: {},
20+
});
21+
22+
it("should inject unmodeled members to the exception", () => {
23+
const decorated = decorateServiceException(exception, { foo: "foo" });
24+
expect((decorated as any).foo).toBe("foo");
25+
});
26+
27+
it("should not inject unmodeled members to the undefined", () => {
28+
const decorated = decorateServiceException(exception, { message: undefined });
29+
expect(decorated.message).toBe("Error");
30+
});
31+
32+
it("should replace Message with message", () => {
33+
const decorated = decorateServiceException({
34+
name: "Error",
35+
Message: "message",
36+
} as any);
37+
expect(decorated.message).toBe("message");
38+
});
39+
});

Diff for: packages/smithy-client/src/exceptions.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { HttpResponse, MetadataBearer, ResponseMetadata, RetryableTrait, SmithyException } from "@aws-sdk/types";
2+
3+
export interface ServiceExceptionOptions extends SmithyException, MetadataBearer {
4+
message?: string;
5+
}
6+
7+
/**
8+
* Base exception class for the exceptions from the server-side.
9+
*/
10+
export class ServiceException extends Error implements SmithyException, MetadataBearer {
11+
readonly $fault: "client" | "server";
12+
13+
$response?: HttpResponse;
14+
$retryable?: RetryableTrait;
15+
$metadata: ResponseMetadata;
16+
17+
constructor(options: ServiceExceptionOptions) {
18+
super(options.message);
19+
Object.setPrototypeOf(this, ServiceException.prototype);
20+
this.name = options.name;
21+
this.$fault = options.$fault;
22+
this.$metadata = options.$metadata;
23+
}
24+
}
25+
26+
/**
27+
* This method inject unmodeled member to a deserialized SDK exception,
28+
* and load the error message from different possible keys('message',
29+
* 'Message').
30+
*
31+
* @internal
32+
*/
33+
export const decorateServiceException = <E extends ServiceException>(
34+
exception: E,
35+
additions: { [key: string]: any } = {}
36+
): E => {
37+
// apply additional properties to deserialized ServiceException object
38+
Object.entries(additions)
39+
.filter(([, v]) => v !== undefined)
40+
.forEach(([k, v]) => {
41+
// @ts-ignore assign unmodeled keys
42+
exception[k] = v;
43+
});
44+
// load error message from possible locations
45+
// @ts-expect-error message could exist in Message key.
46+
const message = exception.message || exception.Message || "UnknownError";
47+
exception.message = message;
48+
// @ts-expect-error
49+
delete exception.Message;
50+
return exception;
51+
};

Diff for: packages/smithy-client/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from "./constants";
44
export * from "./date-utils";
55
export * from "./defaults-mode";
66
export * from "./emitWarningIfUnsupportedVersion";
7+
export * from "./exceptions";
78
export * from "./extended-encode-uri-component";
89
export * from "./get-array-if-single-item";
910
export * from "./get-value-from-text-node";

Diff for: packages/types/src/shapes.ts

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface RetryableTrait {
2525
/**
2626
* Type that is implemented by all Smithy shapes marked with the
2727
* error trait.
28+
* @deprecated
2829
*/
2930
export interface SmithyException {
3031
/**
@@ -53,4 +54,7 @@ export interface SmithyException {
5354
readonly $response?: HttpResponse;
5455
}
5556

57+
/**
58+
* @deprecated
59+
*/
5660
export type SdkError = Error & Partial<SmithyException> & Partial<MetadataBearer>;

0 commit comments

Comments
 (0)