@middy/util 7.1.1 → 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 +17 -0
- package/index.d.ts +25 -19
- package/index.js +55 -20
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -30,6 +30,23 @@
|
|
|
30
30
|
<p>You can read the documentation at: <a href="https://middy.js.org/docs/intro/utilities">https://middy.js.org/docs/intro/utilities</a></p>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install --save @middy/util
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Documentation and examples
|
|
41
|
+
|
|
42
|
+
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/docs/intro/utilities).
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Contributing
|
|
46
|
+
|
|
47
|
+
Everyone is very welcome to contribute to this repository. Feel free to [raise issues](https://github.com/middyjs/middy/issues) or to [submit Pull Requests](https://github.com/middyjs/middy/pulls).
|
|
48
|
+
|
|
49
|
+
|
|
33
50
|
## License
|
|
34
51
|
|
|
35
52
|
Licensed under [MIT License](LICENSE). Copyright (c) 2017-2026 [will Farrell](https://github.com/willfarrell), [Luciano Mammino](https://github.com/lmammino), and [Middy contributors](https://github.com/middyjs/middy/graphs/contributors).
|
package/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
} from "./type-utils.d.ts";
|
|
13
13
|
|
|
14
14
|
export interface Options<Client, ClientOptions> {
|
|
15
|
-
AwsClient?: new (
|
|
15
|
+
AwsClient?: new (config: ClientOptions) => Client;
|
|
16
16
|
awsClientOptions?: Partial<ClientOptions>;
|
|
17
17
|
awsClientAssumeRole?: string;
|
|
18
18
|
awsClientCapture?: (service: Client) => Client;
|
|
@@ -20,6 +20,7 @@ export interface Options<Client, ClientOptions> {
|
|
|
20
20
|
disablePrefetch?: boolean;
|
|
21
21
|
cacheKey?: string;
|
|
22
22
|
cacheExpiry?: number;
|
|
23
|
+
cacheKeyExpiry?: Record<string, number>;
|
|
23
24
|
setToContext?: boolean;
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -27,8 +28,8 @@ export declare class HttpError extends Error {
|
|
|
27
28
|
status: number;
|
|
28
29
|
statusCode: number;
|
|
29
30
|
expose: boolean;
|
|
30
|
-
[key: string]:
|
|
31
|
-
[key: number]:
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
[key: number]: unknown;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
declare function createPrefetchClient<Client, ClientOptions>(
|
|
@@ -118,43 +119,48 @@ declare function sanitizeKey<T extends string>(key: T): SanitizeKey<T>;
|
|
|
118
119
|
|
|
119
120
|
declare function processCache<Client, ClientOptions>(
|
|
120
121
|
options: Options<Client, ClientOptions>,
|
|
121
|
-
fetch: (request: middy.Request, cachedValues:
|
|
122
|
+
fetch: (request: middy.Request, cachedValues: unknown) => unknown,
|
|
122
123
|
request?: middy.Request,
|
|
123
|
-
): { value:
|
|
124
|
+
): { value: unknown; expiry: number };
|
|
124
125
|
|
|
125
|
-
declare function getCache(keys: string):
|
|
126
|
+
declare function getCache(keys: string): unknown;
|
|
126
127
|
|
|
127
128
|
declare function clearCache(keys?: string | string[] | null): void;
|
|
128
129
|
|
|
129
130
|
declare function jsonSafeParse(
|
|
130
131
|
string: string,
|
|
131
|
-
reviver?: (key: string, value:
|
|
132
|
-
):
|
|
132
|
+
reviver?: (key: string, value: unknown) => unknown,
|
|
133
|
+
): unknown;
|
|
133
134
|
|
|
134
135
|
declare function normalizeHttpResponse(
|
|
135
|
-
request:
|
|
136
|
-
fallbackResponse?:
|
|
137
|
-
):
|
|
136
|
+
request: middy.Request,
|
|
137
|
+
fallbackResponse?: Record<string, unknown>,
|
|
138
|
+
): Record<string, unknown>;
|
|
138
139
|
|
|
139
140
|
declare function createError(
|
|
140
141
|
code: number,
|
|
141
142
|
message: string,
|
|
142
|
-
properties?: Record<string,
|
|
143
|
+
properties?: Record<string, unknown>,
|
|
143
144
|
): HttpError;
|
|
144
145
|
|
|
145
|
-
declare function modifyCache(cacheKey: string, value:
|
|
146
|
+
declare function modifyCache(cacheKey: string, value: unknown): void;
|
|
146
147
|
|
|
147
148
|
declare function catchInvalidSignatureException<Client, Command>(
|
|
148
149
|
e: Error & { __type?: string },
|
|
149
150
|
client: Client,
|
|
150
151
|
command: Command,
|
|
151
|
-
): Promise<
|
|
152
|
+
): Promise<unknown>;
|
|
152
153
|
|
|
153
154
|
declare function jsonSafeStringify(
|
|
154
|
-
value:
|
|
155
|
-
replacer?: (key: string, value:
|
|
155
|
+
value: unknown,
|
|
156
|
+
replacer?: (key: string, value: unknown) => unknown,
|
|
156
157
|
space?: string | number,
|
|
157
|
-
): string |
|
|
158
|
+
): string | unknown;
|
|
159
|
+
|
|
160
|
+
declare function decodeBody(event: {
|
|
161
|
+
body?: string | null;
|
|
162
|
+
isBase64Encoded?: boolean;
|
|
163
|
+
}): string | null | undefined;
|
|
158
164
|
|
|
159
165
|
declare const lambdaContextKeys: string[];
|
|
160
166
|
|
|
@@ -166,12 +172,12 @@ declare function executionContext(
|
|
|
166
172
|
request: middy.Request,
|
|
167
173
|
key: string,
|
|
168
174
|
context: LambdaContext,
|
|
169
|
-
):
|
|
175
|
+
): unknown;
|
|
170
176
|
|
|
171
177
|
declare function lambdaContext(
|
|
172
178
|
request: middy.Request,
|
|
173
179
|
key: string,
|
|
174
180
|
context: LambdaContext,
|
|
175
|
-
):
|
|
181
|
+
): unknown;
|
|
176
182
|
|
|
177
183
|
declare const httpErrorCodes: Record<number, string>;
|
package/index.js
CHANGED
|
@@ -61,6 +61,36 @@ export const getInternal = async (variables, request) => {
|
|
|
61
61
|
keys = Object.keys(variables);
|
|
62
62
|
values = Object.values(variables);
|
|
63
63
|
}
|
|
64
|
+
// Fast synchronous path: when all internal values are already resolved
|
|
65
|
+
// (warm/cached invocations), skip all Promise machinery entirely
|
|
66
|
+
let allSync = true;
|
|
67
|
+
const syncResults = new Array(values.length);
|
|
68
|
+
for (let i = 0; i < values.length; i++) {
|
|
69
|
+
const internalKey = values[i];
|
|
70
|
+
const dotIndex = internalKey.indexOf(".");
|
|
71
|
+
const rootKey =
|
|
72
|
+
dotIndex === -1 ? internalKey : internalKey.substring(0, dotIndex);
|
|
73
|
+
let value = request.internal[rootKey];
|
|
74
|
+
if (isPromise(value)) {
|
|
75
|
+
allSync = false;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
if (dotIndex !== -1) {
|
|
79
|
+
for (const part of internalKey.substring(dotIndex + 1).split(".")) {
|
|
80
|
+
value = value?.[part];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
syncResults[i] = value;
|
|
84
|
+
}
|
|
85
|
+
if (allSync) {
|
|
86
|
+
const obj = {};
|
|
87
|
+
for (let i = 0; i < keys.length; i++) {
|
|
88
|
+
obj[sanitizeKey(keys[i])] = syncResults[i];
|
|
89
|
+
}
|
|
90
|
+
return obj;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Async fallback: for cold/first invocations with pending promises
|
|
64
94
|
const promises = [];
|
|
65
95
|
for (const internalKey of values) {
|
|
66
96
|
// 'internal.key.sub_value' -> { [key]: internal.key.sub_value }
|
|
@@ -79,18 +109,21 @@ export const getInternal = async (variables, request) => {
|
|
|
79
109
|
// ensure promise has resolved by the time it's needed
|
|
80
110
|
// If one of the promises throws it will bubble up to @middy/core
|
|
81
111
|
values = await Promise.allSettled(promises);
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
112
|
+
const obj = {};
|
|
113
|
+
let errors;
|
|
114
|
+
for (let i = 0; i < keys.length; i++) {
|
|
115
|
+
if (values[i].status === "rejected") {
|
|
116
|
+
errors ??= [];
|
|
117
|
+
errors.push(values[i].reason);
|
|
118
|
+
} else {
|
|
119
|
+
obj[sanitizeKey(keys[i])] = values[i].value;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (errors) {
|
|
86
123
|
throw new Error("Failed to resolve internal values", {
|
|
87
124
|
cause: { package: "@middy/util", data: errors },
|
|
88
125
|
});
|
|
89
126
|
}
|
|
90
|
-
const obj = {};
|
|
91
|
-
for (let i = keys.length; i--; ) {
|
|
92
|
-
obj[sanitizeKey(keys[i])] = values[i].value;
|
|
93
|
-
}
|
|
94
127
|
return obj;
|
|
95
128
|
};
|
|
96
129
|
|
|
@@ -125,7 +158,8 @@ export const processCache = (
|
|
|
125
158
|
cache[cacheKey] = { value: cached.value, expiry: cached.expiry };
|
|
126
159
|
return cache[cacheKey];
|
|
127
160
|
}
|
|
128
|
-
|
|
161
|
+
cached.cache = true;
|
|
162
|
+
return cached;
|
|
129
163
|
}
|
|
130
164
|
}
|
|
131
165
|
const value = middlewareFetch(middlewareFetchRequest);
|
|
@@ -161,8 +195,9 @@ export const getCache = (key) => {
|
|
|
161
195
|
// Used to remove parts of a cache
|
|
162
196
|
export const modifyCache = (cacheKey, value) => {
|
|
163
197
|
if (!cache[cacheKey]) return;
|
|
164
|
-
clearTimeout(cache[cacheKey]
|
|
165
|
-
cache[cacheKey] =
|
|
198
|
+
clearTimeout(cache[cacheKey].refresh);
|
|
199
|
+
cache[cacheKey].value = value;
|
|
200
|
+
cache[cacheKey].modified = true;
|
|
166
201
|
};
|
|
167
202
|
|
|
168
203
|
export const clearCache = (inputKeys = null) => {
|
|
@@ -192,18 +227,12 @@ export const lambdaContextKeys = [
|
|
|
192
227
|
"callbackWaitsForEmptyEventLoop",
|
|
193
228
|
];
|
|
194
229
|
|
|
195
|
-
export const executionContextKeys = [
|
|
196
|
-
//'requestId',
|
|
197
|
-
"tenantId",
|
|
198
|
-
];
|
|
230
|
+
export const executionContextKeys = ["tenantId"];
|
|
199
231
|
|
|
200
232
|
export const isExecutionModeDurable = (context) => {
|
|
201
233
|
// using `context instanceof DurableContextImpl` would be better
|
|
202
234
|
// but would require an extra dependency
|
|
203
|
-
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
return false;
|
|
235
|
+
return context.constructor.name === "DurableContextImpl";
|
|
207
236
|
};
|
|
208
237
|
|
|
209
238
|
export const executionContext = (request, key, context) => {
|
|
@@ -239,6 +268,12 @@ export const jsonSafeStringify = (value, replacer, space) => {
|
|
|
239
268
|
}
|
|
240
269
|
};
|
|
241
270
|
|
|
271
|
+
export const decodeBody = (event) => {
|
|
272
|
+
const { body, isBase64Encoded } = event;
|
|
273
|
+
if (typeof body === "undefined" || body === null) return body;
|
|
274
|
+
return isBase64Encoded ? Buffer.from(body, "base64").toString() : body;
|
|
275
|
+
};
|
|
276
|
+
|
|
242
277
|
export const normalizeHttpResponse = (request) => {
|
|
243
278
|
let { response } = request;
|
|
244
279
|
if (typeof response === "undefined") {
|
|
@@ -280,7 +315,7 @@ export const createError = (code, message, properties = {}) => {
|
|
|
280
315
|
return new HttpError(code, message, properties);
|
|
281
316
|
};
|
|
282
317
|
|
|
283
|
-
const httpErrorCodes = {
|
|
318
|
+
export const httpErrorCodes = {
|
|
284
319
|
100: "Continue",
|
|
285
320
|
101: "Switching Protocols",
|
|
286
321
|
102: "Processing",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@middy/util",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.3",
|
|
4
4
|
"description": "🛵 The stylish Node.js middleware engine for AWS Lambda (util package)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@aws-sdk/client-ssm": "^3.0.0",
|
|
63
|
-
"@middy/core": "7.1.
|
|
63
|
+
"@middy/core": "7.1.3",
|
|
64
64
|
"@types/aws-lambda": "^8.0.0",
|
|
65
65
|
"@types/node": "^22.0.0",
|
|
66
66
|
"aws-xray-sdk": "^3.3.3"
|
|
@@ -69,6 +69,5 @@
|
|
|
69
69
|
"funding": {
|
|
70
70
|
"type": "github",
|
|
71
71
|
"url": "https://github.com/sponsors/willfarrell"
|
|
72
|
-
}
|
|
73
|
-
"gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
|
|
72
|
+
}
|
|
74
73
|
}
|