@middy/core 7.1.2 → 7.1.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/README.md CHANGED
@@ -42,7 +42,7 @@ npm install --save @middy/core
42
42
 
43
43
  ## Documentation and examples
44
44
 
45
- For documentation and examples, refers to the main [Middy monorepo on GitHub](https://github.com/middyjs/middy) or [Middy official website](https://middy.js.org).
45
+ For documentation and examples, refer to the main [Middy monorepo on GitHub](https://github.com/middyjs/middy) or [Middy official website](https://middy.js.org).
46
46
 
47
47
 
48
48
  ## Contributing
@@ -13,7 +13,7 @@ export const executionModeDurableContext = (
13
13
  ) => {
14
14
  const middy = withDurableExecution(async (event, context) => {
15
15
  const request = middyRequest(event, context);
16
- plugin.requestStart?.(request);
16
+ plugin.requestStart(request);
17
17
 
18
18
  // normalize context with executionModeStandard
19
19
  // https://docs.aws.amazon.com/lambda/latest/dg/typescript-context.html
@@ -33,7 +33,7 @@ export const executionModeDurableContext = (
33
33
  onErrorMiddlewares,
34
34
  plugin,
35
35
  );
36
- await plugin.requestEnd?.(request);
36
+ await plugin.requestEnd(request);
37
37
  return response;
38
38
  });
39
39
  middy.handler = (replaceLambdaHandler) => {
@@ -44,7 +44,7 @@ export const executionModeDurableContext = (
44
44
  };
45
45
 
46
46
  const copyKeys = (to, from, keys) => {
47
- keys.forEach((key) => {
48
- to[key] = from[key];
49
- });
47
+ for (let i = 0, len = keys.length; i < len; i++) {
48
+ to[keys[i]] = from[keys[i]];
49
+ }
50
50
  };
@@ -10,7 +10,7 @@ export const executionModeStandard = (
10
10
  ) => {
11
11
  const middy = async (event, context) => {
12
12
  const request = middyRequest(event, context);
13
- plugin.requestStart?.(request);
13
+ plugin.requestStart(request);
14
14
 
15
15
  const response = await runRequest(
16
16
  request,
@@ -20,7 +20,7 @@ export const executionModeStandard = (
20
20
  onErrorMiddlewares,
21
21
  plugin,
22
22
  );
23
- await plugin.requestEnd?.(request);
23
+ await plugin.requestEnd(request);
24
24
  return response;
25
25
  };
26
26
  middy.handler = (replaceLambdaHandler) => {
@@ -16,7 +16,7 @@ export const executionModeStreamifyResponse = (
16
16
  const middy = awslambda.streamifyResponse(
17
17
  async (event, lambdaResponseStream, context) => {
18
18
  const request = middyRequest(event, context);
19
- plugin.requestStart?.(request);
19
+ plugin.requestStart(request);
20
20
  const handlerResponse = await runRequest(
21
21
  request,
22
22
  beforeMiddlewares,
@@ -55,7 +55,7 @@ export const executionModeStreamifyResponse = (
55
55
  }
56
56
 
57
57
  await pipeline(handlerStream, responseStream);
58
- await plugin.requestEnd?.(request);
58
+ await plugin.requestEnd(request);
59
59
  },
60
60
  );
61
61
 
package/index.d.ts CHANGED
@@ -17,7 +17,7 @@ export declare const executionModeDurableContext: PluginExecutionMode;
17
17
  export declare const executionModeStreamifyResponse: PluginExecutionMode;
18
18
 
19
19
  interface PluginObject {
20
- internal?: any;
20
+ internal?: Record<string, unknown>;
21
21
  beforePrefetch?: PluginHook;
22
22
  requestStart?: PluginHook;
23
23
  beforeMiddleware?: PluginHookWithMiddlewareName;
@@ -31,7 +31,7 @@ interface PluginObject {
31
31
  }
32
32
 
33
33
  export interface Request<
34
- TEvent = any,
34
+ TEvent = unknown,
35
35
  TResult = any,
36
36
  TErr = Error,
37
37
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -39,14 +39,14 @@ export interface Request<
39
39
  > {
40
40
  event: TEvent;
41
41
  context: TContext;
42
- response: TResult | null;
42
+ response: TResult | undefined;
43
43
  earlyResponse?: TResult | null | undefined;
44
- error: TErr | null;
44
+ error: TErr | undefined;
45
45
  internal: TInternal;
46
46
  }
47
47
 
48
48
  declare type MiddlewareFn<
49
- TEvent = any,
49
+ TEvent = unknown,
50
50
  TResult = any,
51
51
  TErr = Error,
52
52
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -91,7 +91,7 @@ type MiddyInputPromiseHandler<
91
91
  > = (event: TEvent, context: TContext) => Promise<TResult>;
92
92
 
93
93
  export interface MiddyfiedHandler<
94
- TEvent = any,
94
+ TEvent = unknown,
95
95
  TResult = any,
96
96
  TErr = Error,
97
97
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -122,7 +122,7 @@ export interface MiddyfiedHandler<
122
122
  }
123
123
 
124
124
  declare type AttachMiddlewareFn<
125
- TEvent = any,
125
+ TEvent = unknown,
126
126
  TResult = any,
127
127
  TErr = Error,
128
128
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -132,7 +132,7 @@ declare type AttachMiddlewareFn<
132
132
  ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>;
133
133
 
134
134
  declare type AttachMiddlewareObj<
135
- TEvent = any,
135
+ TEvent = unknown,
136
136
  TResult = any,
137
137
  TErr = Error,
138
138
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -142,7 +142,7 @@ declare type AttachMiddlewareObj<
142
142
  ) => MiddyfiedHandler<TEvent, TResult, TErr, TContext, TInternal>;
143
143
 
144
144
  declare type UseFn<
145
- TEvent = any,
145
+ TEvent = unknown,
146
146
  TResult = any,
147
147
  TErr = Error,
148
148
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
@@ -187,7 +187,7 @@ declare type MiddlewareHandler<
187
187
  THandler extends LambdaHandler<any, any>,
188
188
  TContext extends LambdaContext | LambdaContextDurable = LambdaContext,
189
189
  TResult = any,
190
- TEvent = any,
190
+ TEvent = unknown,
191
191
  > =
192
192
  THandler extends LambdaHandler<TEvent, TResult> // always true
193
193
  ? MiddyInputHandler<TEvent, TResult, TContext>
package/index.js CHANGED
@@ -4,6 +4,7 @@ import { setTimeout } from "node:timers";
4
4
  import { executionModeStandard } from "./executionModeStandard.js";
5
5
 
6
6
  const defaultLambdaHandler = () => {};
7
+ const noop = () => {};
7
8
  const defaultPluginConfig = {
8
9
  timeoutEarlyInMillis: 5,
9
10
  timeoutEarlyResponse: () => {
@@ -29,6 +30,14 @@ export const middy = (setupLambdaHandler, pluginConfig) => {
29
30
  }
30
31
  plugin.timeoutEarly = plugin.timeoutEarlyInMillis > 0;
31
32
 
33
+ // Pre-compute single-call plugin hooks as noop to avoid optional chaining
34
+ // Note: beforeMiddleware/afterMiddleware kept as optional chaining in runMiddlewares
35
+ // because V8 optimizes ?.() null-checks faster than noop calls in tight loops
36
+ plugin.requestStart ??= noop;
37
+ plugin.requestEnd ??= noop;
38
+ plugin.beforeHandler ??= noop;
39
+ plugin.afterHandler ??= noop;
40
+
32
41
  plugin.beforePrefetch?.();
33
42
  const beforeMiddlewares = [];
34
43
  const afterMiddlewares = [];
@@ -95,6 +104,7 @@ export const middy = (setupLambdaHandler, pluginConfig) => {
95
104
 
96
105
  // shared AbortController, because it's slow
97
106
  let handlerAbort = new AbortController();
107
+ let abortOpts = { signal: handlerAbort.signal };
98
108
  const runRequest = async (
99
109
  request,
100
110
  beforeMiddlewares,
@@ -114,23 +124,24 @@ const runRequest = async (
114
124
  await runMiddlewares(request, beforeMiddlewares, plugin);
115
125
 
116
126
  // Check if before stack hasn't exit early
117
- if (!Object.hasOwn(request, "earlyResponse")) {
118
- plugin.beforeHandler?.();
127
+ if (!("earlyResponse" in request)) {
128
+ plugin.beforeHandler();
119
129
 
120
130
  // Can't manually abort and timeout with same AbortSignal
121
131
  // https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static
122
132
  if (handlerAbort.signal.aborted) {
123
133
  handlerAbort = new AbortController();
134
+ abortOpts = { signal: handlerAbort.signal };
124
135
  }
125
- const promises = [
126
- lambdaHandler(request.event, request.context, {
127
- signal: handlerAbort.signal,
128
- }),
129
- ];
130
136
 
131
137
  // clearTimeout pattern is 10x faster than using AbortController
132
138
  // Note: signal.abort is slow ~6_000ns
133
139
  // Required --test-force-exit to ignore unresolved timeoutPromise
140
+ const handlerResult = lambdaHandler(
141
+ request.event,
142
+ request.context,
143
+ abortOpts,
144
+ );
134
145
  if (timeoutEarly) {
135
146
  let timeoutResolve;
136
147
  const timeoutPromise = new Promise((resolve, reject) => {
@@ -138,8 +149,8 @@ const runRequest = async (
138
149
  handlerAbort.abort();
139
150
  try {
140
151
  resolve(plugin.timeoutEarlyResponse());
141
- } catch (e) {
142
- reject(e);
152
+ } catch (err) {
153
+ reject(err);
143
154
  }
144
155
  };
145
156
  });
@@ -147,18 +158,19 @@ const runRequest = async (
147
158
  timeoutResolve,
148
159
  getRemainingTimeInMillis() - plugin.timeoutEarlyInMillis,
149
160
  );
150
- promises.push(timeoutPromise);
161
+ request.response = await Promise.race([handlerResult, timeoutPromise]);
162
+ } else {
163
+ request.response = await handlerResult;
151
164
  }
152
- request.response = await Promise.race(promises);
153
165
 
154
166
  if (timeoutID) {
155
167
  clearTimeout(timeoutID);
156
168
  }
157
169
 
158
- plugin.afterHandler?.();
170
+ plugin.afterHandler();
159
171
  await runMiddlewares(request, afterMiddlewares, plugin);
160
172
  }
161
- } catch (e) {
173
+ } catch (err) {
162
174
  // timeout should be aborted when errors happen in handler
163
175
  if (timeoutID) {
164
176
  clearTimeout(timeoutID);
@@ -166,13 +178,13 @@ const runRequest = async (
166
178
 
167
179
  // Reset response changes made by after stack before error thrown
168
180
  request.response = undefined;
169
- request.error = e;
181
+ request.error = err;
170
182
  try {
171
183
  await runMiddlewares(request, onErrorMiddlewares, plugin);
172
- } catch (e) {
184
+ } catch (err) {
173
185
  // Save error that wasn't handled
174
- e.originalError = request.error;
175
- request.error = e;
186
+ err.originalError = request.error;
187
+ request.error = err;
176
188
 
177
189
  throw request.error;
178
190
  }
@@ -183,17 +195,17 @@ const runRequest = async (
183
195
  return request.response;
184
196
  };
185
197
 
186
- const runMiddlewares = async (request, middlewares, pluginConfig) => {
198
+ const runMiddlewares = async (request, middlewares, plugin) => {
187
199
  for (const nextMiddleware of middlewares) {
188
- pluginConfig.beforeMiddleware?.(nextMiddleware.name);
200
+ plugin.beforeMiddleware?.(nextMiddleware.name);
189
201
  const res = await nextMiddleware(request);
190
- pluginConfig.afterMiddleware?.(nextMiddleware.name);
202
+ plugin.afterMiddleware?.(nextMiddleware.name);
191
203
  // short circuit chaining and respond early
192
204
  if (typeof res !== "undefined") {
193
205
  request.earlyResponse = res;
194
206
  }
195
207
  // earlyResponse pattern added in 6.0.0 to handle undefined values
196
- if (Object.hasOwn(request, "earlyResponse")) {
208
+ if ("earlyResponse" in request) {
197
209
  request.response = request.earlyResponse;
198
210
  return;
199
211
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middy/core",
3
- "version": "7.1.2",
3
+ "version": "7.1.3",
4
4
  "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)",
5
5
  "type": "module",
6
6
  "engines": {
@@ -96,6 +96,9 @@
96
96
  "type": "github",
97
97
  "url": "https://github.com/sponsors/willfarrell"
98
98
  },
99
+ "dependencies": {
100
+ "@middy/util": "7.1.3"
101
+ },
99
102
  "peerDependencies": {
100
103
  "@aws/durable-execution-sdk-js": "^1.0.0"
101
104
  },
@@ -110,6 +113,5 @@
110
113
  "@datastream/core": "0.0.42",
111
114
  "@types/aws-lambda": "^8.0.0",
112
115
  "@types/node": "^22.0.0"
113
- },
114
- "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
116
+ }
115
117
  }