@middy/util 2.5.6 → 2.5.7
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/index.js +164 -142
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
Agent
|
|
5
|
+
} = require('https'); // const { NodeHttpHandler } = require('@aws-sdk/node-http-handler') // aws-sdk v3
|
|
6
|
+
|
|
3
7
|
|
|
4
8
|
const awsClientDefaultOptions = {
|
|
5
9
|
// AWS SDK v3
|
|
6
10
|
// Docs: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/enforcing-tls.html
|
|
11
|
+
|
|
7
12
|
/* requestHandler: new NodeHttpHandler({
|
|
8
13
|
httpsAgent: new Agent(
|
|
9
14
|
{
|
|
@@ -17,225 +22,242 @@ const awsClientDefaultOptions = {
|
|
|
17
22
|
secureProtocol: 'TLSv1_2_method'
|
|
18
23
|
})
|
|
19
24
|
}
|
|
20
|
-
}
|
|
25
|
+
};
|
|
21
26
|
|
|
22
|
-
const createPrefetchClient =
|
|
23
|
-
const awsClientOptions = {
|
|
24
|
-
...awsClientDefaultOptions,
|
|
27
|
+
const createPrefetchClient = options => {
|
|
28
|
+
const awsClientOptions = { ...awsClientDefaultOptions,
|
|
25
29
|
...options.awsClientOptions
|
|
26
|
-
}
|
|
27
|
-
const client = new options.AwsClient(awsClientOptions)
|
|
30
|
+
};
|
|
31
|
+
const client = new options.AwsClient(awsClientOptions); // AWS XRay
|
|
28
32
|
|
|
29
|
-
// AWS XRay
|
|
30
33
|
if (options.awsClientCapture) {
|
|
31
|
-
return options.awsClientCapture(client)
|
|
34
|
+
return options.awsClientCapture(client);
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
return client
|
|
35
|
-
}
|
|
37
|
+
return client;
|
|
38
|
+
};
|
|
36
39
|
|
|
37
40
|
const createClient = async (options, request) => {
|
|
38
|
-
let awsClientCredentials = {}
|
|
41
|
+
let awsClientCredentials = {}; // Role Credentials
|
|
39
42
|
|
|
40
|
-
// Role Credentials
|
|
41
43
|
if (options.awsClientAssumeRole) {
|
|
42
|
-
if (!request) throw new Error('Request required when assuming role')
|
|
43
|
-
awsClientCredentials = await getInternal(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
44
|
+
if (!request) throw new Error('Request required when assuming role');
|
|
45
|
+
awsClientCredentials = await getInternal({
|
|
46
|
+
credentials: options.awsClientAssumeRole
|
|
47
|
+
}, request);
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
awsClientCredentials = {
|
|
50
|
-
...awsClientCredentials,
|
|
50
|
+
awsClientCredentials = { ...awsClientCredentials,
|
|
51
51
|
...options.awsClientOptions
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return createPrefetchClient({
|
|
55
|
-
...options,
|
|
52
|
+
};
|
|
53
|
+
return createPrefetchClient({ ...options,
|
|
56
54
|
awsClientOptions: awsClientCredentials
|
|
57
|
-
})
|
|
58
|
-
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const canPrefetch = options => {
|
|
59
|
+
return !(options !== null && options !== void 0 && options.awsClientAssumeRole) && !(options !== null && options !== void 0 && options.disablePrefetch);
|
|
60
|
+
}; // Internal Context
|
|
59
61
|
|
|
60
|
-
const canPrefetch = (options) => {
|
|
61
|
-
return !options?.awsClientAssumeRole && !options?.disablePrefetch
|
|
62
|
-
}
|
|
63
62
|
|
|
64
|
-
// Internal Context
|
|
65
63
|
const getInternal = async (variables, request) => {
|
|
66
|
-
if (!variables || !request) return {}
|
|
67
|
-
let keys = []
|
|
68
|
-
let values = []
|
|
64
|
+
if (!variables || !request) return {};
|
|
65
|
+
let keys = [];
|
|
66
|
+
let values = [];
|
|
67
|
+
|
|
69
68
|
if (variables === true) {
|
|
70
|
-
keys = values = Object.keys(request.internal)
|
|
69
|
+
keys = values = Object.keys(request.internal);
|
|
71
70
|
} else if (typeof variables === 'string') {
|
|
72
|
-
keys = values = [variables]
|
|
71
|
+
keys = values = [variables];
|
|
73
72
|
} else if (Array.isArray(variables)) {
|
|
74
|
-
keys = values = variables
|
|
73
|
+
keys = values = variables;
|
|
75
74
|
} else if (typeof variables === 'object') {
|
|
76
|
-
keys = Object.keys(variables)
|
|
77
|
-
values = Object.values(variables)
|
|
75
|
+
keys = Object.keys(variables);
|
|
76
|
+
values = Object.values(variables);
|
|
78
77
|
}
|
|
79
|
-
|
|
78
|
+
|
|
79
|
+
const promises = [];
|
|
80
|
+
|
|
80
81
|
for (const internalKey of values) {
|
|
82
|
+
var _valuePromise;
|
|
83
|
+
|
|
81
84
|
// 'internal.key.sub_value' -> { [key]: internal.key.sub_value }
|
|
82
|
-
const pathOptionKey = internalKey.split('.')
|
|
83
|
-
const rootOptionKey = pathOptionKey.shift()
|
|
84
|
-
let valuePromise = request.internal[rootOptionKey]
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
const pathOptionKey = internalKey.split('.');
|
|
86
|
+
const rootOptionKey = pathOptionKey.shift();
|
|
87
|
+
let valuePromise = request.internal[rootOptionKey];
|
|
88
|
+
|
|
89
|
+
if (typeof ((_valuePromise = valuePromise) === null || _valuePromise === void 0 ? void 0 : _valuePromise.then) !== 'function') {
|
|
90
|
+
valuePromise = Promise.resolve(valuePromise);
|
|
87
91
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
// ensure promise has resolved by the time it's needed
|
|
92
|
+
|
|
93
|
+
promises.push(valuePromise.then(value => pathOptionKey.reduce((p, c) => p === null || p === void 0 ? void 0 : p[c], value)));
|
|
94
|
+
} // ensure promise has resolved by the time it's needed
|
|
95
95
|
// If one of the promises throws it will bubble up to @middy/core
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (errors.length) throw new Error(JSON.stringify(errors))
|
|
101
|
-
return keys.reduce(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const sanitizeKeyPrefixLeadingNumber = /^([0-9])
|
|
107
|
-
const sanitizeKeyRemoveDisallowedChar = /[^a-zA-Z0-9]+/g
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
values = await Promise.allSettled(promises);
|
|
99
|
+
const errors = values.filter(res => res.status === 'rejected').map(res => res.reason.message);
|
|
100
|
+
if (errors.length) throw new Error(JSON.stringify(errors));
|
|
101
|
+
return keys.reduce((obj, key, index) => ({ ...obj,
|
|
102
|
+
[sanitizeKey(key)]: values[index].value
|
|
103
|
+
}), {});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const sanitizeKeyPrefixLeadingNumber = /^([0-9])/;
|
|
107
|
+
const sanitizeKeyRemoveDisallowedChar = /[^a-zA-Z0-9]+/g;
|
|
108
|
+
|
|
109
|
+
const sanitizeKey = key => {
|
|
110
|
+
return key.replace(sanitizeKeyPrefixLeadingNumber, '_$1').replace(sanitizeKeyRemoveDisallowedChar, '_');
|
|
111
|
+
}; // fetch Cache
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const cache = {}; // key: { value:{fetchKey:Promise}, expiry }
|
|
115
|
+
|
|
116
116
|
const processCache = (options, fetch = () => undefined, request) => {
|
|
117
|
-
const {
|
|
117
|
+
const {
|
|
118
|
+
cacheExpiry,
|
|
119
|
+
cacheKey
|
|
120
|
+
} = options;
|
|
121
|
+
|
|
118
122
|
if (cacheExpiry) {
|
|
119
|
-
const cached = getCache(cacheKey)
|
|
120
|
-
const unexpired = cached && (cacheExpiry < 0 || cached.expiry > Date.now())
|
|
123
|
+
const cached = getCache(cacheKey);
|
|
124
|
+
const unexpired = cached && (cacheExpiry < 0 || cached.expiry > Date.now());
|
|
121
125
|
|
|
122
126
|
if (unexpired && cached.modified) {
|
|
123
|
-
const value = fetch(request, cached.value)
|
|
127
|
+
const value = fetch(request, cached.value);
|
|
124
128
|
cache[cacheKey] = {
|
|
125
|
-
value: { ...cached.value,
|
|
129
|
+
value: { ...cached.value,
|
|
130
|
+
...value
|
|
131
|
+
},
|
|
126
132
|
expiry: cached.expiry
|
|
127
|
-
}
|
|
128
|
-
return cache[cacheKey]
|
|
133
|
+
};
|
|
134
|
+
return cache[cacheKey];
|
|
129
135
|
}
|
|
136
|
+
|
|
130
137
|
if (unexpired) {
|
|
131
|
-
return { ...cached,
|
|
138
|
+
return { ...cached,
|
|
139
|
+
cache: true
|
|
140
|
+
};
|
|
132
141
|
}
|
|
133
142
|
}
|
|
134
|
-
const value = fetch(request)
|
|
135
143
|
|
|
136
|
-
const
|
|
144
|
+
const value = fetch(request);
|
|
145
|
+
const expiry = Date.now() + cacheExpiry;
|
|
146
|
+
|
|
137
147
|
if (cacheExpiry) {
|
|
138
|
-
cache[cacheKey] = {
|
|
148
|
+
cache[cacheKey] = {
|
|
149
|
+
value,
|
|
150
|
+
expiry
|
|
151
|
+
};
|
|
139
152
|
}
|
|
140
|
-
return { value, expiry }
|
|
141
|
-
}
|
|
142
153
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
return {
|
|
155
|
+
value,
|
|
156
|
+
expiry
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const getCache = key => {
|
|
161
|
+
return cache[key];
|
|
162
|
+
}; // Used to remove parts of a cache
|
|
163
|
+
|
|
146
164
|
|
|
147
|
-
// Used to remove parts of a cache
|
|
148
165
|
const modifyCache = (cacheKey, value) => {
|
|
149
|
-
if (!cache[cacheKey]) return
|
|
150
|
-
cache[cacheKey] = { ...cache[cacheKey],
|
|
151
|
-
|
|
166
|
+
if (!cache[cacheKey]) return;
|
|
167
|
+
cache[cacheKey] = { ...cache[cacheKey],
|
|
168
|
+
value,
|
|
169
|
+
modified: true
|
|
170
|
+
};
|
|
171
|
+
};
|
|
152
172
|
|
|
153
173
|
const clearCache = (keys = null) => {
|
|
154
|
-
|
|
155
|
-
|
|
174
|
+
var _keys;
|
|
175
|
+
|
|
176
|
+
keys = (_keys = keys) !== null && _keys !== void 0 ? _keys : Object.keys(cache);
|
|
177
|
+
if (!Array.isArray(keys)) keys = [keys];
|
|
178
|
+
|
|
156
179
|
for (const cacheKey of keys) {
|
|
157
|
-
cache[cacheKey] = undefined
|
|
180
|
+
cache[cacheKey] = undefined;
|
|
158
181
|
}
|
|
159
|
-
}
|
|
182
|
+
};
|
|
160
183
|
|
|
161
184
|
const jsonSafeParse = (string, reviver) => {
|
|
162
|
-
if (typeof string !== 'string') return string
|
|
163
|
-
const firstChar = string[0]
|
|
164
|
-
if (firstChar !== '{' && firstChar !== '[' && firstChar !== '"') return string
|
|
185
|
+
if (typeof string !== 'string') return string;
|
|
186
|
+
const firstChar = string[0];
|
|
187
|
+
if (firstChar !== '{' && firstChar !== '[' && firstChar !== '"') return string;
|
|
188
|
+
|
|
165
189
|
try {
|
|
166
|
-
return JSON.parse(string, reviver)
|
|
190
|
+
return JSON.parse(string, reviver);
|
|
167
191
|
} catch (e) {}
|
|
168
192
|
|
|
169
|
-
return string
|
|
170
|
-
}
|
|
193
|
+
return string;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const normalizeHttpResponse = response => {
|
|
197
|
+
var _response$headers, _response;
|
|
171
198
|
|
|
172
|
-
const normalizeHttpResponse = (response) => {
|
|
173
199
|
// May require updating to catch other types
|
|
174
200
|
if (response === undefined) {
|
|
175
|
-
response = {}
|
|
176
|
-
} else if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
) {
|
|
181
|
-
response = { body: response }
|
|
201
|
+
response = {};
|
|
202
|
+
} else if (Array.isArray(response) || typeof response !== 'object' || response === null) {
|
|
203
|
+
response = {
|
|
204
|
+
body: response
|
|
205
|
+
};
|
|
182
206
|
}
|
|
183
|
-
response.headers = response?.headers ?? {}
|
|
184
|
-
return response
|
|
185
|
-
}
|
|
186
207
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
208
|
+
response.headers = (_response$headers = (_response = response) === null || _response === void 0 ? void 0 : _response.headers) !== null && _response$headers !== void 0 ? _response$headers : {};
|
|
209
|
+
return response;
|
|
210
|
+
}; // smaller version of `http-errors`
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
const statuses = require('./codes.json');
|
|
214
|
+
|
|
215
|
+
const {
|
|
216
|
+
inherits
|
|
217
|
+
} = require('util');
|
|
218
|
+
|
|
219
|
+
const createErrorRegexp = /[^a-zA-Z]/g;
|
|
190
220
|
|
|
191
|
-
const createErrorRegexp = /[^a-zA-Z]/g
|
|
192
221
|
const createError = (code, message, properties = {}) => {
|
|
193
|
-
const name = statuses[code].replace(createErrorRegexp, '')
|
|
194
|
-
const className = name.substr(-5) !== 'Error' ? name + 'Error' : name
|
|
222
|
+
const name = statuses[code].replace(createErrorRegexp, '');
|
|
223
|
+
const className = name.substr(-5) !== 'Error' ? name + 'Error' : name;
|
|
195
224
|
|
|
196
|
-
function HttpError
|
|
225
|
+
function HttpError(message) {
|
|
197
226
|
// create the error object
|
|
198
|
-
const msg = message
|
|
199
|
-
const err = new Error(msg)
|
|
227
|
+
const msg = message !== null && message !== void 0 ? message : statuses[code];
|
|
228
|
+
const err = new Error(msg); // capture a stack trace to the construction point
|
|
200
229
|
|
|
201
|
-
|
|
202
|
-
Error.captureStackTrace(err, HttpError)
|
|
230
|
+
Error.captureStackTrace(err, HttpError); // adjust the [[Prototype]]
|
|
203
231
|
|
|
204
|
-
//
|
|
205
|
-
Object.setPrototypeOf(err, HttpError.prototype)
|
|
232
|
+
Object.setPrototypeOf(err, HttpError.prototype); // redefine the error message
|
|
206
233
|
|
|
207
|
-
// redefine the error message
|
|
208
234
|
Object.defineProperty(err, 'message', {
|
|
209
235
|
enumerable: true,
|
|
210
236
|
configurable: true,
|
|
211
237
|
value: msg,
|
|
212
238
|
writable: true
|
|
213
|
-
})
|
|
239
|
+
}); // redefine the error name
|
|
214
240
|
|
|
215
|
-
// redefine the error name
|
|
216
241
|
Object.defineProperty(err, 'name', {
|
|
217
242
|
enumerable: false,
|
|
218
243
|
configurable: true,
|
|
219
244
|
value: className,
|
|
220
245
|
writable: true
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
return err
|
|
246
|
+
});
|
|
247
|
+
return err;
|
|
224
248
|
}
|
|
225
249
|
|
|
226
|
-
inherits(HttpError, Error)
|
|
227
|
-
const desc = Object.getOwnPropertyDescriptor(HttpError, 'name')
|
|
228
|
-
desc.value = className
|
|
229
|
-
Object.defineProperty(HttpError, 'name', desc)
|
|
230
|
-
|
|
250
|
+
inherits(HttpError, Error);
|
|
251
|
+
const desc = Object.getOwnPropertyDescriptor(HttpError, 'name');
|
|
252
|
+
desc.value = className;
|
|
253
|
+
Object.defineProperty(HttpError, 'name', desc);
|
|
231
254
|
Object.assign(HttpError.prototype, {
|
|
232
255
|
status: code,
|
|
233
256
|
statusCode: code,
|
|
234
257
|
expose: code < 500
|
|
235
|
-
}, properties)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
258
|
+
}, properties);
|
|
259
|
+
return new HttpError(message);
|
|
260
|
+
};
|
|
239
261
|
|
|
240
262
|
module.exports = {
|
|
241
263
|
createPrefetchClient,
|
|
@@ -250,4 +272,4 @@ module.exports = {
|
|
|
250
272
|
jsonSafeParse,
|
|
251
273
|
normalizeHttpResponse,
|
|
252
274
|
createError
|
|
253
|
-
}
|
|
275
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@middy/util",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.7",
|
|
4
4
|
"description": "🛵 The stylish Node.js middleware engine for AWS Lambda (util package)",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"engines": {
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"url": "https://github.com/middyjs/middy/issues"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@middy/core": "^2.5.
|
|
47
|
+
"@middy/core": "^2.5.7",
|
|
48
48
|
"@types/aws-lambda": "^8.10.76",
|
|
49
49
|
"@types/node": "^16.0.0",
|
|
50
50
|
"aws-sdk": "^2.939.0",
|
|
51
51
|
"aws-xray-sdk": "^3.3.3"
|
|
52
52
|
},
|
|
53
53
|
"homepage": "https://github.com/middyjs/middy#readme",
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "3983c4b138e1a4d7fcb3ed805d3b8832fff06fc1"
|
|
55
55
|
}
|