@middy/core 6.1.6 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +157 -147
- package/index.js +245 -236
- package/package.json +64 -67
package/index.d.ts
CHANGED
|
@@ -1,169 +1,174 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
|
+
Context as LambdaContext,
|
|
3
|
+
Handler as LambdaHandler,
|
|
4
|
+
} from "aws-lambda";
|
|
2
5
|
|
|
3
|
-
declare type PluginHook = () =>
|
|
4
|
-
declare type PluginHookWithMiddlewareName = (
|
|
6
|
+
declare type PluginHook = () => undefined;
|
|
7
|
+
declare type PluginHookWithMiddlewareName = (
|
|
8
|
+
middlewareName: string,
|
|
9
|
+
) => undefined;
|
|
5
10
|
declare type PluginHookPromise = (
|
|
6
|
-
|
|
7
|
-
) => Promise<unknown> | unknown
|
|
11
|
+
request: Request,
|
|
12
|
+
) => Promise<unknown> | unknown;
|
|
8
13
|
|
|
9
14
|
interface PluginObject {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
internal?: any;
|
|
16
|
+
beforePrefetch?: PluginHook;
|
|
17
|
+
requestStart?: PluginHook;
|
|
18
|
+
beforeMiddleware?: PluginHookWithMiddlewareName;
|
|
19
|
+
afterMiddleware?: PluginHookWithMiddlewareName;
|
|
20
|
+
beforeHandler?: PluginHook;
|
|
21
|
+
timeoutEarlyInMillis?: number;
|
|
22
|
+
timeoutEarlyResponse?: PluginHook;
|
|
23
|
+
afterHandler?: PluginHook;
|
|
24
|
+
requestEnd?: PluginHookPromise;
|
|
25
|
+
streamifyResponse?: boolean;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export interface Request<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
TEvent = any,
|
|
30
|
+
TResult = any,
|
|
31
|
+
TErr = Error,
|
|
32
|
+
TContext extends LambdaContext = LambdaContext,
|
|
33
|
+
TInternal extends Record<string, unknown> = {},
|
|
29
34
|
> {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
event: TEvent;
|
|
36
|
+
context: TContext;
|
|
37
|
+
response: TResult | null;
|
|
38
|
+
earlyResponse?: TResult | null | undefined;
|
|
39
|
+
error: TErr | null;
|
|
40
|
+
internal: TInternal;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
declare type MiddlewareFn<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
> = (request: Request<TEvent, TResult, TErr, TContext, TInternal>) => any
|
|
44
|
+
TEvent = any,
|
|
45
|
+
TResult = any,
|
|
46
|
+
TErr = Error,
|
|
47
|
+
TContext extends LambdaContext = LambdaContext,
|
|
48
|
+
TInternal extends Record<string, unknown> = {},
|
|
49
|
+
> = (request: Request<TEvent, TResult, TErr, TContext, TInternal>) => any;
|
|
45
50
|
|
|
46
51
|
export interface MiddlewareObj<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
TEvent = unknown,
|
|
53
|
+
TResult = any,
|
|
54
|
+
TErr = Error,
|
|
55
|
+
TContext extends LambdaContext = LambdaContext,
|
|
56
|
+
TInternal extends Record<string, unknown> = {},
|
|
52
57
|
> {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
before?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
59
|
+
after?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
60
|
+
onError?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
61
|
+
name?: string;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
export interface MiddyHandlerObject {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
/**
|
|
66
|
+
* An abort signal that will be canceled just before the lambda times out.
|
|
67
|
+
* @see timeoutEarlyInMillis
|
|
68
|
+
*/
|
|
69
|
+
signal: AbortSignal;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
// The AWS provided Handler type uses void | Promise<TResult> so we have no choice but to follow and suppress the linter warning
|
|
68
73
|
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
69
74
|
type MiddyInputHandler<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
TEvent,
|
|
76
|
+
TResult,
|
|
77
|
+
TContext extends LambdaContext = LambdaContext,
|
|
73
78
|
> = (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
) => // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
78
|
-
void | Promise<TResult> | TResult
|
|
79
|
+
event: TEvent,
|
|
80
|
+
context: TContext,
|
|
81
|
+
opts: MiddyHandlerObject,
|
|
82
|
+
) => undefined | Promise<TResult> | TResult; // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
79
83
|
type MiddyInputPromiseHandler<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
> = (event: TEvent, context: TContext) => Promise<TResult
|
|
84
|
+
TEvent,
|
|
85
|
+
TResult,
|
|
86
|
+
TContext extends LambdaContext = LambdaContext,
|
|
87
|
+
> = (event: TEvent, context: TContext) => Promise<TResult>;
|
|
84
88
|
|
|
85
89
|
export interface MiddyfiedHandler<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
TEvent = any,
|
|
91
|
+
TResult = any,
|
|
92
|
+
TErr = Error,
|
|
93
|
+
TContext extends LambdaContext = LambdaContext,
|
|
94
|
+
TInternal extends Record<string, unknown> = {},
|
|
91
95
|
> extends MiddyInputHandler<TEvent, TResult, TContext>,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
MiddyInputPromiseHandler<TEvent, TResult, TContext> {
|
|
97
|
+
use: UseFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
98
|
+
before: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
99
|
+
after: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
100
|
+
onError: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>;
|
|
101
|
+
handler: <
|
|
102
|
+
TInputHandlerEventProps = TEvent,
|
|
103
|
+
TInputHandlerResultProps = TResult,
|
|
104
|
+
>(
|
|
105
|
+
handler: MiddlewareHandler<
|
|
106
|
+
LambdaHandler<TInputHandlerEventProps, TInputHandlerResultProps>,
|
|
107
|
+
TContext,
|
|
108
|
+
TResult,
|
|
109
|
+
TEvent
|
|
110
|
+
>,
|
|
111
|
+
) => MiddyfiedHandler<
|
|
112
|
+
TInputHandlerEventProps,
|
|
113
|
+
TInputHandlerResultProps,
|
|
114
|
+
TErr,
|
|
115
|
+
TContext,
|
|
116
|
+
TInternal
|
|
117
|
+
>;
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
declare type AttachMiddlewareFn<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
TEvent = any,
|
|
122
|
+
TResult = any,
|
|
123
|
+
TErr = Error,
|
|
124
|
+
TContext extends LambdaContext = LambdaContext,
|
|
125
|
+
TInternal extends Record<string, unknown> = {},
|
|
121
126
|
> = (
|
|
122
|
-
|
|
123
|
-
) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal
|
|
127
|
+
middleware: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>,
|
|
128
|
+
) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>;
|
|
124
129
|
|
|
125
130
|
declare type AttachMiddlewareObj<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
TEvent = any,
|
|
132
|
+
TResult = any,
|
|
133
|
+
TErr = Error,
|
|
134
|
+
TContext extends LambdaContext = LambdaContext,
|
|
135
|
+
TInternal extends Record<string, unknown> = {},
|
|
131
136
|
> = (
|
|
132
|
-
|
|
133
|
-
) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal
|
|
137
|
+
middleware: MiddlewareObj<TEvent, TResult, TErr, TContext, TInternal>,
|
|
138
|
+
) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>;
|
|
134
139
|
|
|
135
140
|
declare type UseFn<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
TEvent = any,
|
|
142
|
+
TResult = any,
|
|
143
|
+
TErr = Error,
|
|
144
|
+
TContext extends LambdaContext = LambdaContext,
|
|
145
|
+
TInternal extends Record<string, unknown> = {},
|
|
141
146
|
> = <TMiddleware extends MiddlewareObj<any, any, Error, any, any>>(
|
|
142
|
-
|
|
147
|
+
middlewares: TMiddleware | TMiddleware[],
|
|
143
148
|
) => TMiddleware extends MiddlewareObj<
|
|
144
|
-
infer TMiddlewareEvent,
|
|
145
|
-
any,
|
|
146
|
-
Error,
|
|
147
|
-
infer TMiddlewareContext,
|
|
148
|
-
infer TMiddlewareInternal
|
|
149
|
+
infer TMiddlewareEvent,
|
|
150
|
+
any,
|
|
151
|
+
Error,
|
|
152
|
+
infer TMiddlewareContext,
|
|
153
|
+
infer TMiddlewareInternal
|
|
149
154
|
>
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
? MiddyfiedHandler<
|
|
156
|
+
TMiddlewareEvent & TEvent,
|
|
157
|
+
TResult,
|
|
158
|
+
TErr,
|
|
159
|
+
TMiddlewareContext & TContext,
|
|
160
|
+
TMiddlewareInternal & TInternal
|
|
161
|
+
> // always true
|
|
162
|
+
: never;
|
|
158
163
|
|
|
159
164
|
declare type MiddlewareHandler<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
THandler extends LambdaHandler<any, any>,
|
|
166
|
+
TContext extends LambdaContext = LambdaContext,
|
|
167
|
+
TResult = any,
|
|
168
|
+
TEvent = any,
|
|
169
|
+
> = THandler extends LambdaHandler<TEvent, TResult> // always true
|
|
170
|
+
? MiddyInputHandler<TEvent, TResult, TContext>
|
|
171
|
+
: never;
|
|
167
172
|
|
|
168
173
|
/**
|
|
169
174
|
* Middy factory function. Use it to wrap your existing handler to enable middlewares on it.
|
|
@@ -171,29 +176,34 @@ declare type MiddlewareHandler<
|
|
|
171
176
|
* @param plugin wraps around each middleware and handler to add custom lifecycle behaviours (e.g. to profile performance)
|
|
172
177
|
*/
|
|
173
178
|
declare function middy<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
TEvent = unknown,
|
|
180
|
+
TResult = any,
|
|
181
|
+
TErr = Error,
|
|
182
|
+
TContext extends LambdaContext = LambdaContext,
|
|
183
|
+
TInternal extends Record<string, unknown> = {},
|
|
184
|
+
>(
|
|
185
|
+
handler?:
|
|
186
|
+
| LambdaHandler<TEvent, TResult>
|
|
187
|
+
| MiddlewareHandler<
|
|
188
|
+
LambdaHandler<TEvent, TResult>,
|
|
189
|
+
TContext,
|
|
190
|
+
TResult,
|
|
191
|
+
TEvent
|
|
192
|
+
>
|
|
193
|
+
| PluginObject,
|
|
194
|
+
plugin?: PluginObject,
|
|
195
|
+
): MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>;
|
|
186
196
|
|
|
187
197
|
declare namespace middy {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
198
|
+
export type {
|
|
199
|
+
Request,
|
|
200
|
+
PluginHook,
|
|
201
|
+
PluginHookWithMiddlewareName,
|
|
202
|
+
PluginObject,
|
|
203
|
+
MiddlewareFn,
|
|
204
|
+
MiddlewareObj,
|
|
205
|
+
MiddyfiedHandler,
|
|
206
|
+
};
|
|
197
207
|
}
|
|
198
208
|
|
|
199
|
-
export default middy
|
|
209
|
+
export default middy;
|
package/index.js
CHANGED
|
@@ -1,244 +1,253 @@
|
|
|
1
1
|
/* global awslambda */
|
|
2
|
-
import { Readable } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { setTimeout } from
|
|
6
|
-
|
|
7
|
-
const defaultLambdaHandler = () => {}
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const middy = (
|
|
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
|
-
|
|
2
|
+
import { Readable } from "node:stream";
|
|
3
|
+
import { pipeline } from "node:stream/promises";
|
|
4
|
+
import { ReadableStream } from "node:stream/web";
|
|
5
|
+
import { setTimeout } from "node:timers";
|
|
6
|
+
|
|
7
|
+
const defaultLambdaHandler = () => {};
|
|
8
|
+
const defaultPluginConfig = {
|
|
9
|
+
timeoutEarlyInMillis: 5,
|
|
10
|
+
timeoutEarlyResponse: () => {
|
|
11
|
+
const err = new Error("[AbortError]: The operation was aborted.", {
|
|
12
|
+
cause: { package: "@middy/core" },
|
|
13
|
+
});
|
|
14
|
+
err.name = "TimeoutError";
|
|
15
|
+
throw err;
|
|
16
|
+
},
|
|
17
|
+
streamifyResponse: false, // Deprecate need for this when AWS provides a flag for when it's looking for it
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const middy = (setupLambdaHandler, pluginConfig) => {
|
|
21
|
+
let lambdaHandler;
|
|
22
|
+
let plugin;
|
|
23
|
+
// Allow base handler to be set using .handler()
|
|
24
|
+
if (typeof setupLambdaHandler === "function") {
|
|
25
|
+
lambdaHandler = setupLambdaHandler;
|
|
26
|
+
plugin = { ...defaultPluginConfig, ...pluginConfig };
|
|
27
|
+
} else {
|
|
28
|
+
lambdaHandler = defaultLambdaHandler;
|
|
29
|
+
plugin = { ...defaultPluginConfig, ...setupLambdaHandler };
|
|
30
|
+
}
|
|
31
|
+
plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0;
|
|
32
|
+
|
|
33
|
+
plugin.beforePrefetch?.();
|
|
34
|
+
const beforeMiddlewares = [];
|
|
35
|
+
const afterMiddlewares = [];
|
|
36
|
+
const onErrorMiddlewares = [];
|
|
37
|
+
|
|
38
|
+
const middyHandler = (event = {}, context = {}) => {
|
|
39
|
+
plugin.requestStart?.();
|
|
40
|
+
const request = {
|
|
41
|
+
event,
|
|
42
|
+
context,
|
|
43
|
+
response: undefined,
|
|
44
|
+
error: undefined,
|
|
45
|
+
internal: plugin.internal ?? {},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return runRequest(
|
|
49
|
+
request,
|
|
50
|
+
beforeMiddlewares,
|
|
51
|
+
lambdaHandler,
|
|
52
|
+
afterMiddlewares,
|
|
53
|
+
onErrorMiddlewares,
|
|
54
|
+
plugin,
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
const middy = plugin.streamifyResponse
|
|
58
|
+
? awslambda.streamifyResponse(
|
|
59
|
+
async (event, lambdaResponseStream, context) => {
|
|
60
|
+
const handlerResponse = await middyHandler(event, context);
|
|
61
|
+
let responseStream = lambdaResponseStream;
|
|
62
|
+
let handlerBody = handlerResponse;
|
|
63
|
+
if (handlerResponse.statusCode) {
|
|
64
|
+
const { body, ...restResponse } = handlerResponse;
|
|
65
|
+
handlerBody = body ?? ""; // #1137
|
|
66
|
+
responseStream = awslambda.HttpResponseStream.from(
|
|
67
|
+
responseStream,
|
|
68
|
+
restResponse,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let handlerStream;
|
|
73
|
+
if (
|
|
74
|
+
handlerBody._readableState ||
|
|
75
|
+
handlerBody instanceof ReadableStream
|
|
76
|
+
) {
|
|
77
|
+
handlerStream = handlerBody;
|
|
78
|
+
} else if (typeof handlerBody === "string") {
|
|
79
|
+
// #1189
|
|
80
|
+
handlerStream = Readable.from(
|
|
81
|
+
handlerBody.length < stringIteratorSize
|
|
82
|
+
? handlerBody
|
|
83
|
+
: stringIterator(handlerBody),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!handlerStream) {
|
|
88
|
+
throw new Error("handler response not a ReadableStream");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await pipeline(handlerStream, responseStream);
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
: middyHandler;
|
|
95
|
+
|
|
96
|
+
middy.use = (inputMiddleware) => {
|
|
97
|
+
const middlewares = Array.isArray(inputMiddleware)
|
|
98
|
+
? inputMiddleware
|
|
99
|
+
: [inputMiddleware];
|
|
100
|
+
for (const middleware of middlewares) {
|
|
101
|
+
const { before, after, onError } = middleware;
|
|
102
|
+
|
|
103
|
+
if (before || after || onError) {
|
|
104
|
+
if (before) middy.before(before);
|
|
105
|
+
if (after) middy.after(after);
|
|
106
|
+
if (onError) middy.onError(onError);
|
|
107
|
+
} else {
|
|
108
|
+
throw new Error(
|
|
109
|
+
'Middleware must be an object containing at least one key among "before", "after", "onError"',
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return middy;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Inline Middlewares
|
|
117
|
+
middy.before = (beforeMiddleware) => {
|
|
118
|
+
beforeMiddlewares.push(beforeMiddleware);
|
|
119
|
+
return middy;
|
|
120
|
+
};
|
|
121
|
+
middy.after = (afterMiddleware) => {
|
|
122
|
+
afterMiddlewares.unshift(afterMiddleware);
|
|
123
|
+
return middy;
|
|
124
|
+
};
|
|
125
|
+
middy.onError = (onErrorMiddleware) => {
|
|
126
|
+
onErrorMiddlewares.unshift(onErrorMiddleware);
|
|
127
|
+
return middy;
|
|
128
|
+
};
|
|
129
|
+
middy.handler = (replaceLambdaHandler) => {
|
|
130
|
+
lambdaHandler = replaceLambdaHandler;
|
|
131
|
+
return middy;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return middy;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const stringIteratorSize = 16384; // 16 * 1024 // Node.js default
|
|
138
|
+
function* stringIterator(input) {
|
|
139
|
+
let position = 0;
|
|
140
|
+
const length = input.length;
|
|
141
|
+
while (position < length) {
|
|
142
|
+
yield input.substring(position, position + stringIteratorSize);
|
|
143
|
+
position += stringIteratorSize;
|
|
144
|
+
}
|
|
136
145
|
}
|
|
137
146
|
|
|
138
147
|
// shared AbortController, because it's slow
|
|
139
|
-
let handlerAbort = new AbortController()
|
|
148
|
+
let handlerAbort = new AbortController();
|
|
140
149
|
const runRequest = async (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
request,
|
|
151
|
+
beforeMiddlewares,
|
|
152
|
+
lambdaHandler,
|
|
153
|
+
afterMiddlewares,
|
|
154
|
+
onErrorMiddlewares,
|
|
155
|
+
plugin,
|
|
147
156
|
) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
157
|
+
let timeoutID;
|
|
158
|
+
// context.getRemainingTimeInMillis checked for when AWS context missing (tests, containers)
|
|
159
|
+
const timeoutEarly =
|
|
160
|
+
plugin.timeoutEarly && request.context.getRemainingTimeInMillis;
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
await runMiddlewares(request, beforeMiddlewares, plugin);
|
|
164
|
+
|
|
165
|
+
// Check if before stack hasn't exit early
|
|
166
|
+
if (!Object.prototype.hasOwnProperty.call(request, "earlyResponse")) {
|
|
167
|
+
plugin.beforeHandler?.();
|
|
168
|
+
|
|
169
|
+
// Can't manually abort and timeout with same AbortSignal
|
|
170
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static
|
|
171
|
+
if (handlerAbort.signal.aborted) {
|
|
172
|
+
handlerAbort = new AbortController();
|
|
173
|
+
}
|
|
174
|
+
const promises = [
|
|
175
|
+
lambdaHandler(request.event, request.context, {
|
|
176
|
+
signal: handlerAbort.signal,
|
|
177
|
+
}),
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
// clearTimeout pattern is 10x faster than using AbortController
|
|
181
|
+
// Note: signal.abort is slow ~6000ns
|
|
182
|
+
if (timeoutEarly) {
|
|
183
|
+
let timeoutResolve;
|
|
184
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
185
|
+
timeoutResolve = () => {
|
|
186
|
+
handlerAbort.abort();
|
|
187
|
+
try {
|
|
188
|
+
resolve(plugin.timeoutEarlyResponse());
|
|
189
|
+
} catch (e) {
|
|
190
|
+
reject(e);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
timeoutID = setTimeout(
|
|
195
|
+
timeoutResolve,
|
|
196
|
+
request.context.getRemainingTimeInMillis() -
|
|
197
|
+
plugin.timeoutEarlyInMillis,
|
|
198
|
+
);
|
|
199
|
+
promises.push(timeoutPromise);
|
|
200
|
+
}
|
|
201
|
+
request.response = await Promise.race(promises);
|
|
202
|
+
if (timeoutID) {
|
|
203
|
+
clearTimeout(timeoutID);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
plugin.afterHandler?.();
|
|
207
|
+
await runMiddlewares(request, afterMiddlewares, plugin);
|
|
208
|
+
}
|
|
209
|
+
} catch (e) {
|
|
210
|
+
// timeout should be aborted when errors happen in handler
|
|
211
|
+
if (timeoutID) {
|
|
212
|
+
clearTimeout(timeoutID);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Reset response changes made by after stack before error thrown
|
|
216
|
+
request.response = undefined;
|
|
217
|
+
request.error = e;
|
|
218
|
+
try {
|
|
219
|
+
await runMiddlewares(request, onErrorMiddlewares, plugin);
|
|
220
|
+
} catch (e) {
|
|
221
|
+
// Save error that wasn't handled
|
|
222
|
+
e.originalError = request.error;
|
|
223
|
+
request.error = e;
|
|
224
|
+
|
|
225
|
+
throw request.error;
|
|
226
|
+
}
|
|
227
|
+
// Catch if onError stack hasn't handled the error
|
|
228
|
+
if (typeof request.response === "undefined") throw request.error;
|
|
229
|
+
} finally {
|
|
230
|
+
await plugin.requestEnd?.(request);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return request.response;
|
|
234
|
+
};
|
|
226
235
|
|
|
227
236
|
const runMiddlewares = async (request, middlewares, plugin) => {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export default middy
|
|
237
|
+
for (const nextMiddleware of middlewares) {
|
|
238
|
+
plugin.beforeMiddleware?.(nextMiddleware.name);
|
|
239
|
+
const res = await nextMiddleware(request);
|
|
240
|
+
plugin.afterMiddleware?.(nextMiddleware.name);
|
|
241
|
+
// short circuit chaining and respond early
|
|
242
|
+
if (typeof res !== "undefined") {
|
|
243
|
+
request.earlyResponse = res;
|
|
244
|
+
}
|
|
245
|
+
// earlyResponse pattern added in 6.0.0 to handle undefined values
|
|
246
|
+
if (Object.prototype.hasOwnProperty.call(request, "earlyResponse")) {
|
|
247
|
+
request.response = request.earlyResponse;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export default middy;
|
package/package.json
CHANGED
|
@@ -1,69 +1,66 @@
|
|
|
1
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
|
-
"@types/node": "^20.0.0"
|
|
67
|
-
},
|
|
68
|
-
"gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
|
|
2
|
+
"name": "@middy/core",
|
|
3
|
+
"version": "6.2.0",
|
|
4
|
+
"description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"engineStrict": true,
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"module": "./index.js",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"default": "./index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"default": "./index.js"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"types": "index.d.ts",
|
|
26
|
+
"files": ["index.js", "index.d.ts"],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "npm run test:unit && npm run test:fuzz",
|
|
29
|
+
"test:unit": "node --test",
|
|
30
|
+
"test:fuzz": "node --test index.fuzz.js",
|
|
31
|
+
"test:perf": "node --test index.perf.js",
|
|
32
|
+
"test:profile": "node --prof __benchmarks__/index.js && node --prof-process --preprocess -j isolate*.log | speedscope -"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"keywords": [
|
|
36
|
+
"Lambda",
|
|
37
|
+
"Middleware",
|
|
38
|
+
"Serverless",
|
|
39
|
+
"Framework",
|
|
40
|
+
"AWS",
|
|
41
|
+
"AWS Lambda"
|
|
42
|
+
],
|
|
43
|
+
"author": {
|
|
44
|
+
"name": "Middy contributors",
|
|
45
|
+
"url": "https://github.com/middyjs/middy/graphs/contributors"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/middyjs/middy.git",
|
|
50
|
+
"directory": "packages/core"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/middyjs/middy/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://middy.js.org",
|
|
56
|
+
"funding": {
|
|
57
|
+
"type": "github",
|
|
58
|
+
"url": "https://github.com/sponsors/willfarrell"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@datastream/core": "0.0.40",
|
|
62
|
+
"@types/aws-lambda": "^8.10.76",
|
|
63
|
+
"@types/node": "^20.0.0"
|
|
64
|
+
},
|
|
65
|
+
"gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
|
|
69
66
|
}
|