@middy/core 2.5.6 → 3.0.0-alpha.3
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/LICENSE +1 -1
- package/README.md +1 -1
- package/index.d.ts +4 -7
- package/index.js +170 -48
- package/package.json +9 -7
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2017-
|
|
3
|
+
Copyright (c) 2017-2022 Luciano Mammino, will Farrell and the [Middy team](https://github.com/middyjs/middy/graphs/contributors)
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Everyone is very welcome to contribute to this repository. Feel free to [raise i
|
|
|
47
47
|
|
|
48
48
|
## License
|
|
49
49
|
|
|
50
|
-
Licensed under [MIT License](LICENSE). Copyright (c) 2017-
|
|
50
|
+
Licensed under [MIT License](LICENSE). Copyright (c) 2017-2022 Luciano Mammino, will Farrell, and the [Middy team](https://github.com/middyjs/middy/graphs/contributors).
|
|
51
51
|
|
|
52
52
|
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fmiddyjs%2Fmiddy?ref=badge_large">
|
|
53
53
|
<img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmiddyjs%2Fmiddy.svg?type=large" alt="FOSSA Status" style="max-width:100%;">
|
package/index.d.ts
CHANGED
|
@@ -9,11 +9,14 @@ declare type PluginHookWithMiddlewareName = (middlewareName: string) => void
|
|
|
9
9
|
declare type PluginHookPromise = (request: Request) => Promise<unknown> | unknown
|
|
10
10
|
|
|
11
11
|
interface PluginObject {
|
|
12
|
+
internal?: any
|
|
12
13
|
beforePrefetch?: PluginHook
|
|
13
14
|
requestStart?: PluginHook
|
|
14
15
|
beforeMiddleware?: PluginHookWithMiddlewareName
|
|
15
16
|
afterMiddleware?: PluginHookWithMiddlewareName
|
|
16
17
|
beforeHandler?: PluginHook
|
|
18
|
+
timeoutEarlyInMillis?: number
|
|
19
|
+
timeoutEarlyResponse?: PluginHook
|
|
17
20
|
afterHandler?: PluginHook
|
|
18
21
|
requestEnd?: PluginHookPromise
|
|
19
22
|
}
|
|
@@ -39,20 +42,14 @@ export interface MiddlewareObj<TEvent = any, TResult = any, TErr = Error, TConte
|
|
|
39
42
|
// The AWS provided Handler type uses void | Promise<TResult> so we have no choice but to follow and suppress the linter warning
|
|
40
43
|
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
41
44
|
type MiddyInputHandler<TEvent, TResult, TContext extends LambdaContext = LambdaContext> = (event: TEvent, context: TContext, callback: LambdaCallback<TResult>) => void | Promise<TResult>
|
|
42
|
-
type MiddyInputPromiseHandler<TEvent, TResult, TContext extends LambdaContext = LambdaContext> = (event: TEvent, context: TContext,) => Promise<TResult
|
|
45
|
+
type MiddyInputPromiseHandler<TEvent, TResult, TContext extends LambdaContext = LambdaContext> = ( event: TEvent, context: TContext, ) => Promise<TResult>;
|
|
43
46
|
|
|
44
47
|
export interface MiddyfiedHandler<TEvent = any, TResult = any, TErr = Error, TContext extends LambdaContext = LambdaContext> extends MiddyInputHandler<TEvent, TResult, TContext>,
|
|
45
48
|
MiddyInputPromiseHandler<TEvent, TResult, TContext> {
|
|
46
49
|
use: UseFn<TEvent, TResult, TErr, TContext>
|
|
47
|
-
applyMiddleware: AttachMiddlewareObj<TEvent, TResult, TErr, TContext>
|
|
48
50
|
before: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
|
|
49
51
|
after: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
|
|
50
52
|
onError: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
|
|
51
|
-
__middlewares: {
|
|
52
|
-
before: Array<MiddlewareFn<TEvent, TResult, TErr, TContext>>
|
|
53
|
-
after: Array<MiddlewareFn<TEvent, TResult, TErr, TContext>>
|
|
54
|
-
onError: Array<MiddlewareFn<TEvent, TResult, TErr, TContext>>
|
|
55
|
-
}
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
declare type AttachMiddlewareFn<TEvent = any, TResult = any, TErr = Error, TContext extends LambdaContext = LambdaContext> = (middleware: MiddlewareFn) => MiddyfiedHandler<TEvent, TResult, TErr, TContext>
|
package/index.js
CHANGED
|
@@ -1,93 +1,114 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const defaultLambdaHandler = () => {}
|
|
2
|
+
const defaultPlugin = {
|
|
3
|
+
timeoutEarlyInMillis: 5,
|
|
4
|
+
timeoutEarlyResponse: () => { throw new Error('Timeout') }
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const middy = (lambdaHandler = defaultLambdaHandler, plugin = {}) => {
|
|
8
|
+
// Allow base handler to be set using .handler()
|
|
9
|
+
if (typeof lambdaHandler !== 'function') {
|
|
10
|
+
plugin = lambdaHandler
|
|
11
|
+
lambdaHandler = defaultLambdaHandler
|
|
12
|
+
}
|
|
13
|
+
plugin = { ...defaultPlugin, ...plugin }
|
|
14
|
+
plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0
|
|
15
|
+
|
|
16
|
+
plugin.beforePrefetch?.()
|
|
3
17
|
const beforeMiddlewares = []
|
|
4
18
|
const afterMiddlewares = []
|
|
5
19
|
const onErrorMiddlewares = []
|
|
6
20
|
|
|
7
|
-
const
|
|
8
|
-
plugin
|
|
21
|
+
const middy = (event = {}, context = {}) => {
|
|
22
|
+
plugin.requestStart?.()
|
|
9
23
|
const request = {
|
|
10
24
|
event,
|
|
11
25
|
context,
|
|
12
26
|
response: undefined,
|
|
13
27
|
error: undefined,
|
|
14
|
-
internal: {}
|
|
28
|
+
internal: plugin.internal ?? {}
|
|
15
29
|
}
|
|
16
30
|
|
|
17
31
|
return runRequest(
|
|
18
32
|
request,
|
|
19
33
|
[...beforeMiddlewares],
|
|
20
|
-
|
|
34
|
+
lambdaHandler,
|
|
21
35
|
[...afterMiddlewares],
|
|
22
36
|
[...onErrorMiddlewares],
|
|
23
37
|
plugin
|
|
24
38
|
)
|
|
25
39
|
}
|
|
26
40
|
|
|
27
|
-
|
|
28
|
-
if (Array.isArray(middlewares)) {
|
|
29
|
-
|
|
30
|
-
instance.applyMiddleware(middleware)
|
|
31
|
-
}
|
|
32
|
-
return instance
|
|
41
|
+
middy.use = (middlewares) => {
|
|
42
|
+
if (!Array.isArray(middlewares)) {
|
|
43
|
+
middlewares = [middlewares]
|
|
33
44
|
}
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
for (const middleware of middlewares) {
|
|
46
|
+
const { before, after, onError } = middleware
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
if (!before && !after && !onError) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
'Middleware must be an object containing at least one key among "before", "after", "onError"'
|
|
51
|
+
)
|
|
52
|
+
}
|
|
39
53
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
54
|
+
if (before) middy.before(before)
|
|
55
|
+
if (after) middy.after(after)
|
|
56
|
+
if (onError) middy.onError(onError)
|
|
44
57
|
}
|
|
45
|
-
|
|
46
|
-
if (before) instance.before(before)
|
|
47
|
-
if (after) instance.after(after)
|
|
48
|
-
if (onError) instance.onError(onError)
|
|
49
|
-
|
|
50
|
-
return instance
|
|
58
|
+
return middy
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
// Inline Middlewares
|
|
54
|
-
|
|
62
|
+
middy.before = (beforeMiddleware) => {
|
|
55
63
|
beforeMiddlewares.push(beforeMiddleware)
|
|
56
|
-
return
|
|
64
|
+
return middy
|
|
57
65
|
}
|
|
58
|
-
|
|
66
|
+
middy.after = (afterMiddleware) => {
|
|
59
67
|
afterMiddlewares.unshift(afterMiddleware)
|
|
60
|
-
return
|
|
68
|
+
return middy
|
|
61
69
|
}
|
|
62
|
-
|
|
63
|
-
onErrorMiddlewares.
|
|
64
|
-
return
|
|
70
|
+
middy.onError = (onErrorMiddleware) => {
|
|
71
|
+
onErrorMiddlewares.unshift(onErrorMiddleware)
|
|
72
|
+
return middy
|
|
65
73
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
before: beforeMiddlewares,
|
|
69
|
-
after: afterMiddlewares,
|
|
70
|
-
onError: onErrorMiddlewares
|
|
74
|
+
middy.handler = (replaceLambdaHandler) => {
|
|
75
|
+
lambdaHandler = replaceLambdaHandler
|
|
71
76
|
}
|
|
72
77
|
|
|
73
|
-
return
|
|
78
|
+
return middy
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
const runRequest = async (
|
|
77
82
|
request,
|
|
78
83
|
beforeMiddlewares,
|
|
79
|
-
|
|
84
|
+
lambdaHandler,
|
|
80
85
|
afterMiddlewares,
|
|
81
86
|
onErrorMiddlewares,
|
|
82
87
|
plugin
|
|
83
88
|
) => {
|
|
89
|
+
const { timeoutEarly } = plugin
|
|
84
90
|
try {
|
|
85
91
|
await runMiddlewares(request, beforeMiddlewares, plugin)
|
|
86
92
|
// Check if before stack hasn't exit early
|
|
87
93
|
if (request.response === undefined) {
|
|
88
|
-
plugin
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
plugin.beforeHandler?.()
|
|
95
|
+
|
|
96
|
+
const handlerAbort = new AbortController()
|
|
97
|
+
let timeoutAbort
|
|
98
|
+
if (timeoutEarly) timeoutAbort = new AbortController()
|
|
99
|
+
request.response = await Promise.race([
|
|
100
|
+
lambdaHandler(request.event, request.context, { signal: handlerAbort.signal }),
|
|
101
|
+
timeoutEarly
|
|
102
|
+
? setTimeoutPromise(request.context.getRemainingTimeInMillis() - plugin.timeoutEarlyInMillis, { signal: timeoutAbort.signal })
|
|
103
|
+
.then(() => {
|
|
104
|
+
handlerAbort.abort()
|
|
105
|
+
return plugin.timeoutEarlyResponse()
|
|
106
|
+
})
|
|
107
|
+
: Promise.race([])
|
|
108
|
+
])
|
|
109
|
+
if (timeoutEarly) timeoutAbort.abort() // lambdaHandler may not be a promise
|
|
110
|
+
|
|
111
|
+
plugin.afterHandler?.()
|
|
91
112
|
await runMiddlewares(request, afterMiddlewares, plugin)
|
|
92
113
|
}
|
|
93
114
|
} catch (e) {
|
|
@@ -106,7 +127,7 @@ const runRequest = async (
|
|
|
106
127
|
// Catch if onError stack hasn't handled the error
|
|
107
128
|
if (request.response === undefined) throw request.error
|
|
108
129
|
} finally {
|
|
109
|
-
await plugin
|
|
130
|
+
await plugin.requestEnd?.(request)
|
|
110
131
|
}
|
|
111
132
|
|
|
112
133
|
return request.response
|
|
@@ -114,9 +135,9 @@ const runRequest = async (
|
|
|
114
135
|
|
|
115
136
|
const runMiddlewares = async (request, middlewares, plugin) => {
|
|
116
137
|
for (const nextMiddleware of middlewares) {
|
|
117
|
-
plugin
|
|
118
|
-
const res = await nextMiddleware
|
|
119
|
-
plugin
|
|
138
|
+
plugin.beforeMiddleware?.(nextMiddleware.name)
|
|
139
|
+
const res = await nextMiddleware(request)
|
|
140
|
+
plugin.afterMiddleware?.(nextMiddleware.name)
|
|
120
141
|
// short circuit chaining and respond early
|
|
121
142
|
if (res !== undefined) {
|
|
122
143
|
request.response = res
|
|
@@ -125,4 +146,105 @@ const runMiddlewares = async (request, middlewares, plugin) => {
|
|
|
125
146
|
}
|
|
126
147
|
}
|
|
127
148
|
|
|
128
|
-
|
|
149
|
+
// Start Polyfill (Nodejs v14)
|
|
150
|
+
/*
|
|
151
|
+
MIT License
|
|
152
|
+
|
|
153
|
+
Copyright (c) 2019 Steve Faulkner
|
|
154
|
+
|
|
155
|
+
node-abort-controller
|
|
156
|
+
*/
|
|
157
|
+
const polyfillAbortController = async () => {
|
|
158
|
+
if (process.version < 'v15.0.0') {
|
|
159
|
+
const events = await import('events')
|
|
160
|
+
const { EventEmitter } = events
|
|
161
|
+
|
|
162
|
+
class AbortSignal {
|
|
163
|
+
constructor () {
|
|
164
|
+
this.eventEmitter = new EventEmitter()
|
|
165
|
+
this.onabort = null
|
|
166
|
+
this.aborted = false
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
toString () {
|
|
170
|
+
return '[object AbortSignal]'
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
get [Symbol.toStringTag] () {
|
|
174
|
+
return 'AbortSignal'
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
removeEventListener (name, handler) {
|
|
178
|
+
this.eventEmitter.removeListener(name, handler)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
addEventListener (name, handler) {
|
|
182
|
+
this.eventEmitter.on(name, handler)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
dispatchEvent (type) {
|
|
186
|
+
const event = { type, target: this }
|
|
187
|
+
const handlerName = `on${type}`
|
|
188
|
+
|
|
189
|
+
if (typeof this[handlerName] === 'function') this[handlerName](event)
|
|
190
|
+
|
|
191
|
+
this.eventEmitter.emit(type, event)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return class AbortController {
|
|
196
|
+
constructor () {
|
|
197
|
+
this.signal = new AbortSignal()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
abort () {
|
|
201
|
+
if (this.signal.aborted) return
|
|
202
|
+
|
|
203
|
+
this.signal.aborted = true
|
|
204
|
+
this.signal.dispatchEvent('abort')
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
toString () {
|
|
208
|
+
return '[object AbortController]'
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
get [Symbol.toStringTag] () {
|
|
212
|
+
return 'AbortController'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
return AbortController
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
global.AbortController = await polyfillAbortController()
|
|
220
|
+
|
|
221
|
+
const polyfillSetTimeoutPromise = async () => {
|
|
222
|
+
|
|
223
|
+
if (process.version < 'v15.0.0') {
|
|
224
|
+
return (ms, { signal }) => {
|
|
225
|
+
if (signal.aborted) {
|
|
226
|
+
return Promise.reject(new Error('Aborted', 'AbortError'))
|
|
227
|
+
}
|
|
228
|
+
return new Promise((resolve, reject) => {
|
|
229
|
+
const abortHandler = () => {
|
|
230
|
+
clearTimeout(timeout)
|
|
231
|
+
reject(new Error('Aborted', 'AbortError'))
|
|
232
|
+
}
|
|
233
|
+
// start async operation
|
|
234
|
+
const timeout = setTimeout(() => {
|
|
235
|
+
resolve()
|
|
236
|
+
signal.removeEventListener('abort', abortHandler)
|
|
237
|
+
}, ms)
|
|
238
|
+
signal.addEventListener('abort', abortHandler)
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
const timers = await import('timers/promises')
|
|
243
|
+
return timers.setTimeout
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
global.setTimeoutPromise = await polyfillSetTimeoutPromise()
|
|
247
|
+
// import { setTimeout as setTimeoutPromise } from 'timers/promises'
|
|
248
|
+
// End Polyfill
|
|
249
|
+
|
|
250
|
+
export default middy
|
package/package.json
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@middy/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.3",
|
|
4
4
|
"description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)",
|
|
5
|
-
"type": "
|
|
5
|
+
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
|
-
"node": ">=
|
|
7
|
+
"node": ">=14"
|
|
8
8
|
},
|
|
9
9
|
"engineStrict": true,
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
13
|
-
"
|
|
13
|
+
"exports": "./index.js",
|
|
14
14
|
"types": "index.d.ts",
|
|
15
15
|
"files": [
|
|
16
|
+
"index.js",
|
|
16
17
|
"index.d.ts"
|
|
17
18
|
],
|
|
18
19
|
"scripts": {
|
|
19
20
|
"test": "npm run test:unit",
|
|
20
|
-
"test:unit": "ava"
|
|
21
|
+
"test:unit": "ava",
|
|
22
|
+
"test:benchmark": "node __benchmarks__/index.js"
|
|
21
23
|
},
|
|
22
24
|
"license": "MIT",
|
|
23
25
|
"keywords": [
|
|
@@ -43,7 +45,7 @@
|
|
|
43
45
|
"homepage": "https://github.com/middyjs/middy#readme",
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"@types/aws-lambda": "^8.10.76",
|
|
46
|
-
"@types/node": "^
|
|
48
|
+
"@types/node": "^17.0.0"
|
|
47
49
|
},
|
|
48
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "1441158711580313765e6d156046ef0fade0d156"
|
|
49
51
|
}
|