@middy/core 5.0.0-alpha.1 → 5.0.0-rc.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.
Files changed (2) hide show
  1. package/index.js +168 -201
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -1,209 +1,176 @@
1
- /* global awslambda */
2
- import { Readable } from 'node:stream'
3
- import { pipeline } from 'node:stream/promises'
4
- import { setTimeout } from 'node:timers/promises'
5
-
6
- const defaultLambdaHandler = () => {}
1
+ /* global awslambda */ import { Readable } from 'node:stream';
2
+ import { pipeline } from 'node:stream/promises';
3
+ import { setTimeout } from 'node:timers/promises';
4
+ const defaultLambdaHandler = ()=>{};
7
5
  const defaultPlugin = {
8
- timeoutEarlyInMillis: 5,
9
- timeoutEarlyResponse: () => {
10
- const err = new Error('[AbortError]: The operation was aborted.', {
11
- cause: { package: '@middy/core' }
12
- })
13
- err.name = 'TimeoutError'
14
- throw err
15
- },
16
- streamifyResponse: false // Deprecate need for this when AWS provides a flag for when it's looking for it
17
- }
18
-
19
- const middy = (lambdaHandler = defaultLambdaHandler, plugin = {}) => {
20
- // Allow base handler to be set using .handler()
21
- if (typeof lambdaHandler !== 'function') {
22
- plugin = lambdaHandler
23
- lambdaHandler = defaultLambdaHandler
24
- }
25
- plugin = { ...defaultPlugin, ...plugin }
26
- plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0
27
-
28
- plugin.beforePrefetch?.()
29
- const beforeMiddlewares = []
30
- const afterMiddlewares = []
31
- const onErrorMiddlewares = []
32
-
33
- const middyHandler = (event = {}, context = {}) => {
34
- plugin.requestStart?.()
35
- const request = {
36
- event,
37
- context,
38
- response: undefined,
39
- error: undefined,
40
- internal: plugin.internal ?? {}
6
+ timeoutEarlyInMillis: 5,
7
+ timeoutEarlyResponse: ()=>{
8
+ const err = new Error('[AbortError]: The operation was aborted.', {
9
+ cause: {
10
+ package: '@middy/core'
11
+ }
12
+ });
13
+ err.name = 'TimeoutError';
14
+ throw err;
15
+ },
16
+ streamifyResponse: false // Deprecate need for this when AWS provides a flag for when it's looking for it
17
+ };
18
+ const middy = (lambdaHandler = defaultLambdaHandler, plugin = {})=>{
19
+ // Allow base handler to be set using .handler()
20
+ if (typeof lambdaHandler !== 'function') {
21
+ plugin = lambdaHandler;
22
+ lambdaHandler = defaultLambdaHandler;
41
23
  }
42
-
43
- return runRequest(
44
- request,
45
- [...beforeMiddlewares],
46
- lambdaHandler,
47
- [...afterMiddlewares],
48
- [...onErrorMiddlewares],
49
- plugin
50
- )
51
- }
52
- const middy = plugin.streamifyResponse
53
- ? awslambda.streamifyResponse(async (event, responseStream, context) => {
54
- const handlerResponse = await middyHandler(event, context)
55
-
56
- let handlerBody = handlerResponse
57
- if (handlerResponse.statusCode) {
58
- handlerBody = handlerResponse.body ?? ''
59
- responseStream = awslambda.HttpResponseStream.from(
60
- responseStream,
61
- handlerResponse
62
- )
63
- }
64
-
65
- // Source @datastream/core (MIT)
66
- let handlerStream
67
- if (handlerBody._readableState) {
68
- handlerStream = handlerBody
69
- } else if (typeof handlerBody === 'string') {
70
- function * iterator (input) {
71
- const size = 16384 // 16 * 1024 // Node.js default
72
- let position = 0
73
- const length = input.length
74
- while (position < length) {
75
- yield input.substring(position, position + size)
76
- position += size
77
- }
24
+ plugin = {
25
+ ...defaultPlugin,
26
+ ...plugin
27
+ };
28
+ plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0;
29
+ plugin.beforePrefetch?.();
30
+ const beforeMiddlewares = [];
31
+ const afterMiddlewares = [];
32
+ const onErrorMiddlewares = [];
33
+ const middyHandler = (event = {}, context = {})=>{
34
+ plugin.requestStart?.();
35
+ const request = {
36
+ event,
37
+ context,
38
+ response: undefined,
39
+ error: undefined,
40
+ internal: plugin.internal ?? {}
41
+ };
42
+ return runRequest(request, [
43
+ ...beforeMiddlewares
44
+ ], lambdaHandler, [
45
+ ...afterMiddlewares
46
+ ], [
47
+ ...onErrorMiddlewares
48
+ ], plugin);
49
+ };
50
+ const middy = plugin.streamifyResponse ? awslambda.streamifyResponse(async (event, responseStream, context)=>{
51
+ const handlerResponse = await middyHandler(event, context);
52
+ let handlerBody = handlerResponse;
53
+ if (handlerResponse.statusCode) {
54
+ handlerBody = handlerResponse.body ?? '';
55
+ responseStream = awslambda.HttpResponseStream.from(responseStream, handlerResponse);
78
56
  }
79
- handlerStream = Readable.from(iterator(handlerBody))
80
- }
81
-
82
- if (!handlerStream) {
83
- throw new Error('handler response not a ReadableStream')
84
- }
85
-
86
- await pipeline(handlerStream, responseStream)
87
- })
88
- : middyHandler
89
-
90
- middy.use = (middlewares) => {
91
- if (!Array.isArray(middlewares)) {
92
- middlewares = [middlewares]
93
- }
94
- for (const middleware of middlewares) {
95
- const { before, after, onError } = middleware
96
-
97
- if (!before && !after && !onError) {
98
- throw new Error(
99
- 'Middleware must be an object containing at least one key among "before", "after", "onError"'
100
- )
101
- }
102
-
103
- if (before) middy.before(before)
104
- if (after) middy.after(after)
105
- if (onError) middy.onError(onError)
106
- }
107
- return middy
108
- }
109
-
110
- // Inline Middlewares
111
- middy.before = (beforeMiddleware) => {
112
- beforeMiddlewares.push(beforeMiddleware)
113
- return middy
114
- }
115
- middy.after = (afterMiddleware) => {
116
- afterMiddlewares.unshift(afterMiddleware)
117
- return middy
118
- }
119
- middy.onError = (onErrorMiddleware) => {
120
- onErrorMiddlewares.unshift(onErrorMiddleware)
121
- return middy
122
- }
123
- middy.handler = (replaceLambdaHandler) => {
124
- lambdaHandler = replaceLambdaHandler
125
- return middy
126
- }
127
-
128
- return middy
129
- }
130
-
131
- const runRequest = async (
132
- request,
133
- beforeMiddlewares,
134
- lambdaHandler,
135
- afterMiddlewares,
136
- onErrorMiddlewares,
137
- plugin
138
- ) => {
139
- let timeoutAbort
140
- const timeoutEarly =
141
- plugin.timeoutEarly && request.context.getRemainingTimeInMillis // disable when AWS context missing (tests, containers)
142
- try {
143
- await runMiddlewares(request, beforeMiddlewares, plugin)
144
- // Check if before stack hasn't exit early
145
- if (typeof request.response === 'undefined') {
146
- plugin.beforeHandler?.()
147
-
148
- const handlerAbort = new AbortController()
149
-
150
- if (timeoutEarly) timeoutAbort = new AbortController()
151
- request.response = await Promise.race([
152
- lambdaHandler(request.event, request.context, {
153
- signal: handlerAbort.signal
154
- }),
155
- timeoutEarly
156
- ? setTimeout(
157
- request.context.getRemainingTimeInMillis() -
158
- plugin.timeoutEarlyInMillis,
159
- undefined,
160
- { signal: timeoutAbort.signal }
161
- ).then(() => {
162
- handlerAbort.abort()
163
- return plugin.timeoutEarlyResponse()
164
- })
165
- : Promise.race([])
166
- ])
167
- timeoutAbort?.abort() // lambdaHandler may not be a promise
168
-
169
- plugin.afterHandler?.()
170
- await runMiddlewares(request, afterMiddlewares, plugin)
171
- }
172
- } catch (e) {
173
- timeoutAbort?.abort() // timeout should be aborted on errors
174
-
175
- // Reset response changes made by after stack before error thrown
176
- request.response = undefined
177
- request.error = e
57
+ // Source @datastream/core (MIT)
58
+ let handlerStream;
59
+ if (handlerBody._readableState) {
60
+ handlerStream = handlerBody;
61
+ } else if (typeof handlerBody === 'string') {
62
+ function* iterator(input) {
63
+ const size = 16384 // 16 * 1024 // Node.js default
64
+ ;
65
+ let position = 0;
66
+ const length = input.length;
67
+ while(position < length){
68
+ yield input.substring(position, position + size);
69
+ position += size;
70
+ }
71
+ }
72
+ handlerStream = Readable.from(iterator(handlerBody));
73
+ }
74
+ if (!handlerStream) {
75
+ throw new Error('handler response not a ReadableStream');
76
+ }
77
+ await pipeline(handlerStream, responseStream);
78
+ }) : middyHandler;
79
+ middy.use = (middlewares)=>{
80
+ if (!Array.isArray(middlewares)) {
81
+ middlewares = [
82
+ middlewares
83
+ ];
84
+ }
85
+ for (const middleware of middlewares){
86
+ const { before, after, onError } = middleware;
87
+ if (!before && !after && !onError) {
88
+ throw new Error('Middleware must be an object containing at least one key among "before", "after", "onError"');
89
+ }
90
+ if (before) middy.before(before);
91
+ if (after) middy.after(after);
92
+ if (onError) middy.onError(onError);
93
+ }
94
+ return middy;
95
+ };
96
+ // Inline Middlewares
97
+ middy.before = (beforeMiddleware)=>{
98
+ beforeMiddlewares.push(beforeMiddleware);
99
+ return middy;
100
+ };
101
+ middy.after = (afterMiddleware)=>{
102
+ afterMiddlewares.unshift(afterMiddleware);
103
+ return middy;
104
+ };
105
+ middy.onError = (onErrorMiddleware)=>{
106
+ onErrorMiddlewares.unshift(onErrorMiddleware);
107
+ return middy;
108
+ };
109
+ middy.handler = (replaceLambdaHandler)=>{
110
+ lambdaHandler = replaceLambdaHandler;
111
+ return middy;
112
+ };
113
+ return middy;
114
+ };
115
+ const runRequest = async (request, beforeMiddlewares, lambdaHandler, afterMiddlewares, onErrorMiddlewares, plugin)=>{
116
+ let timeoutAbort;
117
+ const timeoutEarly = plugin.timeoutEarly && request.context.getRemainingTimeInMillis // disable when AWS context missing (tests, containers)
118
+ ;
178
119
  try {
179
- await runMiddlewares(request, onErrorMiddlewares, plugin)
120
+ await runMiddlewares(request, beforeMiddlewares, plugin);
121
+ // Check if before stack hasn't exit early
122
+ if (typeof request.response === 'undefined') {
123
+ plugin.beforeHandler?.();
124
+ const handlerAbort = new AbortController();
125
+ if (timeoutEarly) timeoutAbort = new AbortController();
126
+ request.response = await Promise.race([
127
+ lambdaHandler(request.event, request.context, {
128
+ signal: handlerAbort.signal
129
+ }),
130
+ timeoutEarly ? setTimeout(request.context.getRemainingTimeInMillis() - plugin.timeoutEarlyInMillis, undefined, {
131
+ signal: timeoutAbort.signal
132
+ }).then(()=>{
133
+ handlerAbort.abort();
134
+ return plugin.timeoutEarlyResponse();
135
+ }) : Promise.race([])
136
+ ]);
137
+ timeoutAbort?.abort() // lambdaHandler may not be a promise
138
+ ;
139
+ plugin.afterHandler?.();
140
+ await runMiddlewares(request, afterMiddlewares, plugin);
141
+ }
180
142
  } catch (e) {
181
- // Save error that wasn't handled
182
- e.originalError = request.error
183
- request.error = e
184
-
185
- throw request.error
143
+ timeoutAbort?.abort() // timeout should be aborted on errors
144
+ ;
145
+ // Reset response changes made by after stack before error thrown
146
+ request.response = undefined;
147
+ request.error = e;
148
+ try {
149
+ await runMiddlewares(request, onErrorMiddlewares, plugin);
150
+ } catch (e) {
151
+ // Save error that wasn't handled
152
+ e.originalError = request.error;
153
+ request.error = e;
154
+ throw request.error;
155
+ }
156
+ // Catch if onError stack hasn't handled the error
157
+ if (typeof request.response === 'undefined') throw request.error;
158
+ } finally{
159
+ await plugin.requestEnd?.(request);
186
160
  }
187
- // Catch if onError stack hasn't handled the error
188
- if (typeof request.response === 'undefined') throw request.error
189
- } finally {
190
- await plugin.requestEnd?.(request)
191
- }
192
-
193
- return request.response
194
- }
195
-
196
- const runMiddlewares = async (request, middlewares, plugin) => {
197
- for (const nextMiddleware of middlewares) {
198
- plugin.beforeMiddleware?.(nextMiddleware.name)
199
- const res = await nextMiddleware(request)
200
- plugin.afterMiddleware?.(nextMiddleware.name)
201
- // short circuit chaining and respond early
202
- if (typeof res !== 'undefined') {
203
- request.response = res
204
- return
161
+ return request.response;
162
+ };
163
+ const runMiddlewares = async (request, middlewares, plugin)=>{
164
+ for (const nextMiddleware of middlewares){
165
+ plugin.beforeMiddleware?.(nextMiddleware.name);
166
+ const res = await nextMiddleware(request);
167
+ plugin.afterMiddleware?.(nextMiddleware.name);
168
+ // short circuit chaining and respond early
169
+ if (typeof res !== 'undefined') {
170
+ request.response = res;
171
+ return;
172
+ }
205
173
  }
206
- }
207
- }
174
+ };
175
+ export default middy;
208
176
 
209
- export default middy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middy/core",
3
- "version": "5.0.0-alpha.1",
3
+ "version": "5.0.0-rc.0",
4
4
  "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)",
5
5
  "type": "module",
6
6
  "engines": {
@@ -59,7 +59,7 @@
59
59
  "@types/aws-lambda": "^8.10.76",
60
60
  "@types/node": "^20.0.0"
61
61
  },
62
- "gitHead": "ebce8d5df8783077fa49ba62ee9be20e8486a7f1",
62
+ "gitHead": "403c54ba9f05e038d1ee7541f9e4a7a6d46e9916",
63
63
  "dependencies": {
64
64
  "@datastream/core": "0.0.35"
65
65
  }