UNPKG

3.23 kBJavaScriptView Raw
1const middy = (baseHandler = () => {}, plugin) => {
2 plugin?.beforePrefetch?.()
3 const beforeMiddlewares = []
4 const afterMiddlewares = []
5 const onErrorMiddlewares = []
6
7 const instance = (event = {}, context = {}) => {
8 plugin?.requestStart?.()
9 const request = {
10 event,
11 context,
12 response: undefined,
13 error: undefined,
14 internal: {}
15 }
16
17 return runRequest(
18 request,
19 [...beforeMiddlewares],
20 baseHandler,
21 [...afterMiddlewares],
22 [...onErrorMiddlewares],
23 plugin
24 )
25 }
26
27 instance.use = (middlewares) => {
28 if (Array.isArray(middlewares)) {
29 for (const middleware of middlewares) {
30 instance.applyMiddleware(middleware)
31 }
32 return instance
33 }
34 return instance.applyMiddleware(middlewares)
35 }
36
37 instance.applyMiddleware = (middleware) => {
38 const { before, after, onError } = middleware
39
40 if (!before && !after && !onError) {
41 throw new Error(
42 'Middleware must be an object containing at least one key among "before", "after", "onError"'
43 )
44 }
45
46 if (before) instance.before(before)
47 if (after) instance.after(after)
48 if (onError) instance.onError(onError)
49
50 return instance
51 }
52
53 // Inline Middlewares
54 instance.before = (beforeMiddleware) => {
55 beforeMiddlewares.push(beforeMiddleware)
56 return instance
57 }
58 instance.after = (afterMiddleware) => {
59 afterMiddlewares.unshift(afterMiddleware)
60 return instance
61 }
62 instance.onError = (onErrorMiddleware) => {
63 onErrorMiddlewares.push(onErrorMiddleware)
64 return instance
65 }
66
67 instance.__middlewares = {
68 before: beforeMiddlewares,
69 after: afterMiddlewares,
70 onError: onErrorMiddlewares
71 }
72
73 return instance
74}
75
76const runRequest = async (
77 request,
78 beforeMiddlewares,
79 baseHandler,
80 afterMiddlewares,
81 onErrorMiddlewares,
82 plugin
83) => {
84 try {
85 await runMiddlewares(request, beforeMiddlewares, plugin)
86 // Check if before stack hasn't exit early
87 if (request.response === undefined) {
88 plugin?.beforeHandler?.()
89 request.response = await baseHandler(request.event, request.context)
90 plugin?.afterHandler?.()
91 await runMiddlewares(request, afterMiddlewares, plugin)
92 }
93 } catch (e) {
94 // Reset response changes made by after stack before error thrown
95 request.response = undefined
96 request.error = e
97 try {
98 await runMiddlewares(request, onErrorMiddlewares, plugin)
99 } catch (e) {
100 // Save error that wasn't handled
101 e.originalError = request.error
102 request.error = e
103
104 throw request.error
105 }
106 // Catch if onError stack hasn't handled the error
107 if (request.response === undefined) throw request.error
108 } finally {
109 await plugin?.requestEnd?.(request)
110 }
111
112 return request.response
113}
114
115const runMiddlewares = async (request, middlewares, plugin) => {
116 for (const nextMiddleware of middlewares) {
117 plugin?.beforeMiddleware?.(nextMiddleware?.name)
118 const res = await nextMiddleware?.(request)
119 plugin?.afterMiddleware?.(nextMiddleware?.name)
120 // short circuit chaining and respond early
121 if (res !== undefined) {
122 request.response = res
123 return
124 }
125 }
126}
127
128module.exports = middy