forked from aws/aws-lambda-nodejs-runtime-interface-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
137 lines (125 loc) · 3.57 KB
/
index.ts
File metadata and controls
137 lines (125 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Defines custom error types throwable by the runtime.
*/
"use strict";
import util from "util";
export function isError(obj: any): obj is Error {
return (
obj &&
obj.name &&
obj.message &&
obj.stack &&
typeof obj.name === "string" &&
typeof obj.message === "string" &&
typeof obj.stack === "string"
);
}
interface RuntimeErrorResponse {
errorType: string;
errorMessage: string;
trace: string[];
}
/**
* Attempt to convert an object into a response object.
* This method accounts for failures when serializing the error object.
*/
export function toRuntimeResponse(error: unknown): RuntimeErrorResponse {
try {
if (util.types.isNativeError(error) || isError(error)) {
if (!error.stack) {
throw new Error("Error stack is missing.");
}
return {
errorType: error.name,
errorMessage: error.message,
trace: error.stack.split("\n") || [],
};
} else {
return {
errorType: typeof error,
errorMessage: (error as any).toString(),
trace: [],
};
}
} catch (_err) {
return {
errorType: "handled",
errorMessage:
"callback called with Error argument, but there was a problem while retrieving one or more of its message, name, and stack",
trace: [],
};
}
}
/**
* Format an error with the expected properties.
* For compatability, the error string always starts with a tab.
*/
export const toFormatted = (error: unknown): string => {
try {
return (
"\t" + JSON.stringify(error, (_k, v) => _withEnumerableProperties(v))
);
} catch (err) {
return "\t" + JSON.stringify(toRuntimeResponse(error));
}
};
/**
* Error name, message, code, and stack are all members of the superclass, which
* means they aren't enumerable and don't normally show up in JSON.stringify.
* This method ensures those interesting properties are available along with any
* user-provided enumerable properties.
*/
function _withEnumerableProperties(error: any) {
if (error instanceof Error) {
const extendedError: ExtendedError = <ExtendedError>(<any>error);
const ret: any = Object.assign(
{
errorType: extendedError.name,
errorMessage: extendedError.message,
code: extendedError.code,
},
extendedError
);
if (typeof extendedError.stack == "string") {
ret.stack = extendedError.stack.split("\n");
}
return ret;
} else {
return error;
}
}
export class ExtendedError extends Error {
code?: number;
custom?: string;
reason?: string;
promise?: Promise<any>;
constructor(reason?: string) {
super(reason); // 'Error' breaks prototype chain here
Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
}
}
export class ImportModuleError extends ExtendedError {}
export class HandlerNotFound extends ExtendedError {}
export class MalformedHandlerName extends ExtendedError {}
export class UserCodeSyntaxError extends ExtendedError {}
export class UnhandledPromiseRejection extends ExtendedError {
constructor(reason?: string, promise?: Promise<any>) {
super(reason);
this.reason = reason;
this.promise = promise;
}
}
const errorClasses = [
ImportModuleError,
HandlerNotFound,
MalformedHandlerName,
UserCodeSyntaxError,
UnhandledPromiseRejection,
];
errorClasses.forEach((e) => {
e.prototype.name = `Runtime.${e.name}`;
});