@middy/core 4.6.5 → 5.0.0-alpha.1

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 (4) hide show
  1. package/index.d.ts +39 -29
  2. package/index.js +201 -162
  3. package/package.json +6 -10
  4. package/index.cjs +0 -180
package/index.d.ts CHANGED
@@ -28,33 +28,34 @@ export interface Request<
28
28
  TEvent = any,
29
29
  TResult = any,
30
30
  TErr = Error,
31
- TContext extends LambdaContext = LambdaContext
31
+ TContext extends LambdaContext = LambdaContext,
32
+ TInternal extends Record<string, unknown> = {}
32
33
  > {
33
34
  event: TEvent
34
35
  context: TContext
35
36
  response: TResult | null
36
37
  error: TErr | null
37
- internal: {
38
- [key: string]: any
39
- }
38
+ internal: TInternal
40
39
  }
41
40
 
42
41
  declare type MiddlewareFn<
43
42
  TEvent = any,
44
43
  TResult = any,
45
44
  TErr = Error,
46
- TContext extends LambdaContext = LambdaContext
47
- > = (request: Request<TEvent, TResult, TErr, TContext>) => any
45
+ TContext extends LambdaContext = LambdaContext,
46
+ TInternal extends Record<string, unknown> = {}
47
+ > = (request: Request<TEvent, TResult, TErr, TContext, TInternal>) => any
48
48
 
49
49
  export interface MiddlewareObj<
50
50
  TEvent = unknown,
51
51
  TResult = any,
52
52
  TErr = Error,
53
- TContext extends LambdaContext = LambdaContext
53
+ TContext extends LambdaContext = LambdaContext,
54
+ TInternal extends Record<string, unknown> = {}
54
55
  > {
55
- before?: MiddlewareFn<TEvent, TResult, TErr, TContext>
56
- after?: MiddlewareFn<TEvent, TResult, TErr, TContext>
57
- onError?: MiddlewareFn<TEvent, TResult, TErr, TContext>
56
+ before?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
57
+ after?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
58
+ onError?: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
58
59
  }
59
60
 
60
61
  // The AWS provided Handler type uses void | Promise<TResult> so we have no choice but to follow and suppress the linter warning
@@ -79,57 +80,63 @@ export interface MiddyfiedHandler<
79
80
  TEvent = any,
80
81
  TResult = any,
81
82
  TErr = Error,
82
- TContext extends LambdaContext = LambdaContext
83
+ TContext extends LambdaContext = LambdaContext,
84
+ TInternal extends Record<string, unknown> = {}
83
85
  > extends MiddyInputHandler<TEvent, TResult, TContext>,
84
86
  MiddyInputPromiseHandler<TEvent, TResult, TContext> {
85
- use: UseFn<TEvent, TResult, TErr, TContext>
86
- before: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
87
- after: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
88
- onError: AttachMiddlewareFn<TEvent, TResult, TErr, TContext>
87
+ use: UseFn<TEvent, TResult, TErr, TContext, TInternal>
88
+ before: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
89
+ after: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
90
+ onError: AttachMiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
89
91
  handler: <TAdditional>(
90
92
  handler: MiddlewareHandler<
91
93
  LambdaHandler<TEvent & TAdditional, TResult>,
92
94
  TContext
93
95
  >
94
- ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext>
96
+ ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>
95
97
  }
96
98
 
97
99
  declare type AttachMiddlewareFn<
98
100
  TEvent = any,
99
101
  TResult = any,
100
102
  TErr = Error,
101
- TContext extends LambdaContext = LambdaContext
103
+ TContext extends LambdaContext = LambdaContext,
104
+ TInternal extends Record<string, unknown> = {}
102
105
  > = (
103
- middleware: MiddlewareFn<TEvent, TResult, TErr, TContext>
104
- ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext>
106
+ middleware: MiddlewareFn<TEvent, TResult, TErr, TContext, TInternal>
107
+ ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>
105
108
 
106
109
  declare type AttachMiddlewareObj<
107
110
  TEvent = any,
108
111
  TResult = any,
109
112
  TErr = Error,
110
- TContext extends LambdaContext = LambdaContext
113
+ TContext extends LambdaContext = LambdaContext,
114
+ TInternal extends Record<string, unknown> = {}
111
115
  > = (
112
- middleware: MiddlewareObj<TEvent, TResult, TErr, TContext>
113
- ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext>
116
+ middleware: MiddlewareObj<TEvent, TResult, TErr, TContext, TInternal>
117
+ ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>
114
118
 
115
119
  declare type UseFn<
116
120
  TEvent = any,
117
121
  TResult = any,
118
122
  TErr = Error,
119
- TContext extends LambdaContext = LambdaContext
120
- > = <TMiddleware extends MiddlewareObj<any, any, Error, any>>(
123
+ TContext extends LambdaContext = LambdaContext,
124
+ TInternal extends Record<string, unknown> = {}
125
+ > = <TMiddleware extends MiddlewareObj<any, any, Error, any, any>>(
121
126
  middlewares: TMiddleware | TMiddleware[]
122
127
  ) => TMiddleware extends MiddlewareObj<
123
128
  infer TMiddlewareEvent,
124
129
  any,
125
130
  Error,
126
- infer TMiddlewareContext
131
+ infer TMiddlewareContext,
132
+ infer TMiddlewareInternal
127
133
  >
128
134
  ? MiddyfiedHandler<
129
135
  TMiddlewareEvent & TEvent,
130
136
  TResult,
131
137
  TErr,
132
- TMiddlewareContext & TContext
138
+ TMiddlewareContext & TContext,
139
+ TMiddlewareInternal & TInternal
133
140
  > // always true
134
141
  : never
135
142
 
@@ -149,11 +156,14 @@ declare function middy<
149
156
  TEvent = unknown,
150
157
  TResult = any,
151
158
  TErr = Error,
152
- TContext extends LambdaContext = LambdaContext
159
+ TContext extends LambdaContext = LambdaContext,
160
+ TInternal extends Record<string, unknown> = {}
153
161
  > (
154
- handler?: MiddlewareHandler<LambdaHandler<TEvent, TResult>, TContext> | PluginObject,
162
+ handler?:
163
+ | MiddlewareHandler<LambdaHandler<TEvent, TResult>, TContext>
164
+ | PluginObject,
155
165
  plugin?: PluginObject
156
- ): MiddyfiedHandler<TEvent, TResult, TErr, TContext>
166
+ ): MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>
157
167
 
158
168
  declare namespace middy {
159
169
  export {
package/index.js CHANGED
@@ -1,170 +1,209 @@
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 = ()=>{};
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 = () => {}
5
7
  const defaultPlugin = {
6
- timeoutEarlyInMillis: 5,
7
- timeoutEarlyResponse: ()=>{
8
- throw new Error('Timeout');
9
- },
10
- streamifyResponse: false // Deprecate need for this when AWS provides a flag for when it's looking for it
11
- };
12
- const middy = (lambdaHandler = defaultLambdaHandler, plugin = {})=>{
13
- // Allow base handler to be set using .handler()
14
- if (typeof lambdaHandler !== 'function') {
15
- plugin = lambdaHandler;
16
- lambdaHandler = defaultLambdaHandler;
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 ?? {}
17
41
  }
18
- plugin = {
19
- ...defaultPlugin,
20
- ...plugin
21
- };
22
- plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0;
23
- plugin.beforePrefetch?.();
24
- const beforeMiddlewares = [];
25
- const afterMiddlewares = [];
26
- const onErrorMiddlewares = [];
27
- const middyHandler = (event = {}, context = {})=>{
28
- plugin.requestStart?.();
29
- const request = {
30
- event,
31
- context,
32
- response: undefined,
33
- error: undefined,
34
- internal: plugin.internal ?? {}
35
- };
36
- return runRequest(request, [
37
- ...beforeMiddlewares
38
- ], lambdaHandler, [
39
- ...afterMiddlewares
40
- ], [
41
- ...onErrorMiddlewares
42
- ], plugin);
43
- };
44
- const middy = plugin.streamifyResponse ? awslambda.streamifyResponse(async (event, responseStream, context)=>{
45
- const handlerResponse = await middyHandler(event, context);
46
- let handlerBody = handlerResponse;
47
- if (handlerResponse.statusCode) {
48
- handlerBody = handlerResponse.body ?? '';
49
- responseStream = awslambda.HttpResponseStream.from(responseStream, handlerResponse);
50
- }
51
- // Source @datastream/core (MIT)
52
- let handlerStream;
53
- if (handlerBody._readableState) {
54
- handlerStream = handlerBody;
55
- } else if (typeof handlerBody === 'string') {
56
- function* iterator(input) {
57
- const size = 16384 // 16 * 1024 // Node.js default
58
- ;
59
- let position = 0;
60
- const length = input.length;
61
- while(position < length){
62
- yield input.substring(position, position + size);
63
- position += size;
64
- }
65
- }
66
- handlerStream = Readable.from(iterator(handlerBody));
67
- }
68
- if (!handlerStream) {
69
- throw new Error('handler response not a ReadableStream');
70
- }
71
- await pipeline(handlerStream, responseStream);
72
- }) : middyHandler;
73
- middy.use = (middlewares)=>{
74
- if (!Array.isArray(middlewares)) {
75
- middlewares = [
76
- middlewares
77
- ];
78
- }
79
- for (const middleware of middlewares){
80
- const { before, after, onError } = middleware;
81
- if (!before && !after && !onError) {
82
- throw new Error('Middleware must be an object containing at least one key among "before", "after", "onError"');
83
- }
84
- if (before) middy.before(before);
85
- if (after) middy.after(after);
86
- if (onError) middy.onError(onError);
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
+ }
87
78
  }
88
- return middy;
89
- };
90
- // Inline Middlewares
91
- middy.before = (beforeMiddleware)=>{
92
- beforeMiddlewares.push(beforeMiddleware);
93
- return middy;
94
- };
95
- middy.after = (afterMiddleware)=>{
96
- afterMiddlewares.unshift(afterMiddleware);
97
- return middy;
98
- };
99
- middy.onError = (onErrorMiddleware)=>{
100
- onErrorMiddlewares.unshift(onErrorMiddleware);
101
- return middy;
102
- };
103
- middy.handler = (replaceLambdaHandler)=>{
104
- lambdaHandler = replaceLambdaHandler;
105
- return middy;
106
- };
107
- return middy;
108
- };
109
- const runRequest = async (request, beforeMiddlewares, lambdaHandler, afterMiddlewares, onErrorMiddlewares, plugin)=>{
110
- let timeoutAbort;
111
- const timeoutEarly = plugin.timeoutEarly && request.context.getRemainingTimeInMillis // disable when AWS context missing (tests, containers)
112
- ;
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
113
178
  try {
114
- await runMiddlewares(request, beforeMiddlewares, plugin);
115
- // Check if before stack hasn't exit early
116
- if (typeof request.response === 'undefined') {
117
- plugin.beforeHandler?.();
118
- const handlerAbort = new AbortController();
119
- if (timeoutEarly) timeoutAbort = new AbortController();
120
- request.response = await Promise.race([
121
- lambdaHandler(request.event, request.context, {
122
- signal: handlerAbort.signal
123
- }),
124
- timeoutEarly ? setTimeout(request.context.getRemainingTimeInMillis() - plugin.timeoutEarlyInMillis, undefined, {
125
- signal: timeoutAbort.signal
126
- }).then(()=>{
127
- handlerAbort.abort();
128
- return plugin.timeoutEarlyResponse();
129
- }) : Promise.race([])
130
- ]);
131
- timeoutAbort?.abort() // lambdaHandler may not be a promise
132
- ;
133
- plugin.afterHandler?.();
134
- await runMiddlewares(request, afterMiddlewares, plugin);
135
- }
179
+ await runMiddlewares(request, onErrorMiddlewares, plugin)
136
180
  } catch (e) {
137
- timeoutAbort?.abort() // timeout should be aborted on errors
138
- ;
139
- // Reset response changes made by after stack before error thrown
140
- request.response = undefined;
141
- request.error = e;
142
- try {
143
- await runMiddlewares(request, onErrorMiddlewares, plugin);
144
- } catch (e) {
145
- // Save error that wasn't handled
146
- e.originalError = request.error;
147
- request.error = e;
148
- throw request.error;
149
- }
150
- // Catch if onError stack hasn't handled the error
151
- if (typeof request.response === 'undefined') throw request.error;
152
- } finally{
153
- await plugin.requestEnd?.(request);
181
+ // Save error that wasn't handled
182
+ e.originalError = request.error
183
+ request.error = e
184
+
185
+ throw request.error
154
186
  }
155
- return request.response;
156
- };
157
- const runMiddlewares = async (request, middlewares, plugin)=>{
158
- for (const nextMiddleware of middlewares){
159
- plugin.beforeMiddleware?.(nextMiddleware.name);
160
- const res = await nextMiddleware(request);
161
- plugin.afterMiddleware?.(nextMiddleware.name);
162
- // short circuit chaining and respond early
163
- if (typeof res !== 'undefined') {
164
- request.response = res;
165
- return;
166
- }
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
167
205
  }
168
- };
169
- export default middy;
206
+ }
207
+ }
170
208
 
209
+ export default middy
package/package.json CHANGED
@@ -1,33 +1,27 @@
1
1
  {
2
2
  "name": "@middy/core",
3
- "version": "4.6.5",
3
+ "version": "5.0.0-alpha.1",
4
4
  "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)",
5
5
  "type": "module",
6
6
  "engines": {
7
- "node": ">=16"
7
+ "node": ">=18"
8
8
  },
9
9
  "engineStrict": true,
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "main": "./index.cjs",
14
13
  "module": "./index.js",
15
14
  "exports": {
16
15
  ".": {
17
16
  "import": {
18
17
  "types": "./index.d.ts",
19
18
  "default": "./index.js"
20
- },
21
- "require": {
22
- "types": "./index.d.ts",
23
- "default": "./index.cjs"
24
19
  }
25
20
  }
26
21
  },
27
22
  "types": "index.d.ts",
28
23
  "files": [
29
24
  "index.js",
30
- "index.cjs",
31
25
  "index.d.ts"
32
26
  ],
33
27
  "scripts": {
@@ -62,9 +56,11 @@
62
56
  "url": "https://github.com/sponsors/willfarrell"
63
57
  },
64
58
  "devDependencies": {
65
- "@datastream/core": "0.0.35",
66
59
  "@types/aws-lambda": "^8.10.76",
67
60
  "@types/node": "^20.0.0"
68
61
  },
69
- "gitHead": "573d7b0bb243d8c5a9bcb00cf29d031aa7a0c606"
62
+ "gitHead": "ebce8d5df8783077fa49ba62ee9be20e8486a7f1",
63
+ "dependencies": {
64
+ "@datastream/core": "0.0.35"
65
+ }
70
66
  }
package/index.cjs DELETED
@@ -1,180 +0,0 @@
1
- /* global awslambda */ "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(module, "exports", {
6
- enumerable: true,
7
- get: function() {
8
- return _default;
9
- }
10
- });
11
- const _nodestream = require("node:stream");
12
- const _promises = require("node:stream/promises");
13
- const _promises1 = require("node:timers/promises");
14
- const defaultLambdaHandler = ()=>{};
15
- const defaultPlugin = {
16
- timeoutEarlyInMillis: 5,
17
- timeoutEarlyResponse: ()=>{
18
- throw new Error('Timeout');
19
- },
20
- streamifyResponse: false // Deprecate need for this when AWS provides a flag for when it's looking for it
21
- };
22
- const middy = (lambdaHandler = defaultLambdaHandler, plugin = {})=>{
23
- // Allow base handler to be set using .handler()
24
- if (typeof lambdaHandler !== 'function') {
25
- plugin = lambdaHandler;
26
- lambdaHandler = defaultLambdaHandler;
27
- }
28
- plugin = {
29
- ...defaultPlugin,
30
- ...plugin
31
- };
32
- plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0;
33
- plugin.beforePrefetch?.();
34
- const beforeMiddlewares = [];
35
- const afterMiddlewares = [];
36
- const onErrorMiddlewares = [];
37
- const middyHandler = (event = {}, context = {})=>{
38
- plugin.requestStart?.();
39
- const request = {
40
- event,
41
- context,
42
- response: undefined,
43
- error: undefined,
44
- internal: plugin.internal ?? {}
45
- };
46
- return runRequest(request, [
47
- ...beforeMiddlewares
48
- ], lambdaHandler, [
49
- ...afterMiddlewares
50
- ], [
51
- ...onErrorMiddlewares
52
- ], plugin);
53
- };
54
- const middy = plugin.streamifyResponse ? awslambda.streamifyResponse(async (event, responseStream, context)=>{
55
- const handlerResponse = await middyHandler(event, context);
56
- let handlerBody = handlerResponse;
57
- if (handlerResponse.statusCode) {
58
- handlerBody = handlerResponse.body ?? '';
59
- responseStream = awslambda.HttpResponseStream.from(responseStream, handlerResponse);
60
- }
61
- // Source @datastream/core (MIT)
62
- let handlerStream;
63
- if (handlerBody._readableState) {
64
- handlerStream = handlerBody;
65
- } else if (typeof handlerBody === 'string') {
66
- function* iterator(input) {
67
- const size = 16384 // 16 * 1024 // Node.js default
68
- ;
69
- let position = 0;
70
- const length = input.length;
71
- while(position < length){
72
- yield input.substring(position, position + size);
73
- position += size;
74
- }
75
- }
76
- handlerStream = _nodestream.Readable.from(iterator(handlerBody));
77
- }
78
- if (!handlerStream) {
79
- throw new Error('handler response not a ReadableStream');
80
- }
81
- await (0, _promises.pipeline)(handlerStream, responseStream);
82
- }) : middyHandler;
83
- middy.use = (middlewares)=>{
84
- if (!Array.isArray(middlewares)) {
85
- middlewares = [
86
- middlewares
87
- ];
88
- }
89
- for (const middleware of middlewares){
90
- const { before, after, onError } = middleware;
91
- if (!before && !after && !onError) {
92
- throw new Error('Middleware must be an object containing at least one key among "before", "after", "onError"');
93
- }
94
- if (before) middy.before(before);
95
- if (after) middy.after(after);
96
- if (onError) middy.onError(onError);
97
- }
98
- return middy;
99
- };
100
- // Inline Middlewares
101
- middy.before = (beforeMiddleware)=>{
102
- beforeMiddlewares.push(beforeMiddleware);
103
- return middy;
104
- };
105
- middy.after = (afterMiddleware)=>{
106
- afterMiddlewares.unshift(afterMiddleware);
107
- return middy;
108
- };
109
- middy.onError = (onErrorMiddleware)=>{
110
- onErrorMiddlewares.unshift(onErrorMiddleware);
111
- return middy;
112
- };
113
- middy.handler = (replaceLambdaHandler)=>{
114
- lambdaHandler = replaceLambdaHandler;
115
- return middy;
116
- };
117
- return middy;
118
- };
119
- const runRequest = async (request, beforeMiddlewares, lambdaHandler, afterMiddlewares, onErrorMiddlewares, plugin)=>{
120
- let timeoutAbort;
121
- const timeoutEarly = plugin.timeoutEarly && request.context.getRemainingTimeInMillis // disable when AWS context missing (tests, containers)
122
- ;
123
- try {
124
- await runMiddlewares(request, beforeMiddlewares, plugin);
125
- // Check if before stack hasn't exit early
126
- if (typeof request.response === 'undefined') {
127
- plugin.beforeHandler?.();
128
- const handlerAbort = new AbortController();
129
- if (timeoutEarly) timeoutAbort = new AbortController();
130
- request.response = await Promise.race([
131
- lambdaHandler(request.event, request.context, {
132
- signal: handlerAbort.signal
133
- }),
134
- timeoutEarly ? (0, _promises1.setTimeout)(request.context.getRemainingTimeInMillis() - plugin.timeoutEarlyInMillis, undefined, {
135
- signal: timeoutAbort.signal
136
- }).then(()=>{
137
- handlerAbort.abort();
138
- return plugin.timeoutEarlyResponse();
139
- }) : Promise.race([])
140
- ]);
141
- timeoutAbort?.abort() // lambdaHandler may not be a promise
142
- ;
143
- plugin.afterHandler?.();
144
- await runMiddlewares(request, afterMiddlewares, plugin);
145
- }
146
- } catch (e) {
147
- timeoutAbort?.abort() // timeout should be aborted on errors
148
- ;
149
- // Reset response changes made by after stack before error thrown
150
- request.response = undefined;
151
- request.error = e;
152
- try {
153
- await runMiddlewares(request, onErrorMiddlewares, plugin);
154
- } catch (e) {
155
- // Save error that wasn't handled
156
- e.originalError = request.error;
157
- request.error = e;
158
- throw request.error;
159
- }
160
- // Catch if onError stack hasn't handled the error
161
- if (typeof request.response === 'undefined') throw request.error;
162
- } finally{
163
- await plugin.requestEnd?.(request);
164
- }
165
- return request.response;
166
- };
167
- const runMiddlewares = async (request, middlewares, plugin)=>{
168
- for (const nextMiddleware of middlewares){
169
- plugin.beforeMiddleware?.(nextMiddleware.name);
170
- const res = await nextMiddleware(request);
171
- plugin.afterMiddleware?.(nextMiddleware.name);
172
- // short circuit chaining and respond early
173
- if (typeof res !== 'undefined') {
174
- request.response = res;
175
- return;
176
- }
177
- }
178
- };
179
- const _default = middy;
180
-