@middy/util 3.0.0-alpha.0 → 3.0.0-alpha.4

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 +235 -0
  2. package/package.json +6 -4
package/index.js ADDED
@@ -0,0 +1,235 @@
1
+ import { Agent } from 'https';
2
+ import statuses from './codes.js';
3
+ import { inherits } from 'util';
4
+ export const awsClientDefaultOptions = {
5
+ httpOptions: {
6
+ agent: new Agent({
7
+ secureProtocol: 'TLSv1_2_method'
8
+ })
9
+ }
10
+ };
11
+ export const createPrefetchClient = options => {
12
+ const awsClientOptions = { ...awsClientDefaultOptions,
13
+ ...options.awsClientOptions
14
+ };
15
+ const client = new options.AwsClient(awsClientOptions);
16
+
17
+ if (options.awsClientCapture && options.disablePrefetch) {
18
+ return options.awsClientCapture(client);
19
+ } else if (options.awsClientCapture) {
20
+ console.warn('Unable to apply X-Ray outside of handler invocation scope.');
21
+ }
22
+
23
+ return client;
24
+ };
25
+ export const createClient = async (options, request) => {
26
+ let awsClientCredentials = {};
27
+
28
+ if (options.awsClientAssumeRole) {
29
+ if (!request) throw new Error('Request required when assuming role');
30
+ awsClientCredentials = await getInternal({
31
+ credentials: options.awsClientAssumeRole
32
+ }, request);
33
+ }
34
+
35
+ awsClientCredentials = { ...awsClientCredentials,
36
+ ...options.awsClientOptions
37
+ };
38
+ return createPrefetchClient({ ...options,
39
+ awsClientOptions: awsClientCredentials
40
+ });
41
+ };
42
+ export const canPrefetch = (options = {}) => {
43
+ return !options.awsClientAssumeRole && !options.disablePrefetch;
44
+ };
45
+ export const getInternal = async (variables, request) => {
46
+ if (!variables || !request) return {};
47
+ let keys = [];
48
+ let values = [];
49
+
50
+ if (variables === true) {
51
+ keys = values = Object.keys(request.internal);
52
+ } else if (typeof variables === 'string') {
53
+ keys = values = [variables];
54
+ } else if (Array.isArray(variables)) {
55
+ keys = values = variables;
56
+ } else if (typeof variables === 'object') {
57
+ keys = Object.keys(variables);
58
+ values = Object.values(variables);
59
+ }
60
+
61
+ const promises = [];
62
+
63
+ for (const internalKey of values) {
64
+ const pathOptionKey = internalKey.split('.');
65
+ const rootOptionKey = pathOptionKey.shift();
66
+ let valuePromise = request.internal[rootOptionKey];
67
+
68
+ if (typeof valuePromise.then !== 'function') {
69
+ valuePromise = Promise.resolve(valuePromise);
70
+ }
71
+
72
+ promises.push(valuePromise.then(value => pathOptionKey.reduce((p, c) => p === null || p === void 0 ? void 0 : p[c], value)));
73
+ }
74
+
75
+ values = await Promise.allSettled(promises);
76
+ const errors = values.filter(res => res.status === 'rejected').map(res => res.reason);
77
+
78
+ if (errors.length) {
79
+ const error = new Error('Failed to resolve internal values');
80
+ error.cause = errors;
81
+ throw error;
82
+ }
83
+
84
+ return keys.reduce((obj, key, index) => ({ ...obj,
85
+ [sanitizeKey(key)]: values[index].value
86
+ }), {});
87
+ };
88
+ const sanitizeKeyPrefixLeadingNumber = /^([0-9])/;
89
+ const sanitizeKeyRemoveDisallowedChar = /[^a-zA-Z0-9]+/g;
90
+ export const sanitizeKey = key => {
91
+ return key.replace(sanitizeKeyPrefixLeadingNumber, '_$1').replace(sanitizeKeyRemoveDisallowedChar, '_');
92
+ };
93
+ const cache = {};
94
+ export const processCache = (options, fetch = () => undefined, request) => {
95
+ const {
96
+ cacheExpiry,
97
+ cacheKey
98
+ } = options;
99
+
100
+ if (cacheExpiry) {
101
+ const cached = getCache(cacheKey);
102
+ const unexpired = cached.expiry && (cacheExpiry < 0 || cached.expiry > Date.now());
103
+
104
+ if (unexpired && cached.modified) {
105
+ const value = fetch(request, cached.value);
106
+ cache[cacheKey] = {
107
+ value: { ...cached.value,
108
+ ...value
109
+ },
110
+ expiry: cached.expiry
111
+ };
112
+ return cache[cacheKey];
113
+ }
114
+
115
+ if (unexpired) {
116
+ return { ...cached,
117
+ cache: true
118
+ };
119
+ }
120
+ }
121
+
122
+ const value = fetch(request);
123
+ const expiry = Date.now() + cacheExpiry;
124
+
125
+ if (cacheExpiry) {
126
+ cache[cacheKey] = {
127
+ value,
128
+ expiry
129
+ };
130
+ }
131
+
132
+ return {
133
+ value,
134
+ expiry
135
+ };
136
+ };
137
+ export const getCache = key => {
138
+ if (!cache[key]) return {};
139
+ return cache[key];
140
+ };
141
+ export const modifyCache = (cacheKey, value) => {
142
+ if (!cache[cacheKey]) return;
143
+ cache[cacheKey] = { ...cache[cacheKey],
144
+ value,
145
+ modified: true
146
+ };
147
+ };
148
+ export const clearCache = (keys = null) => {
149
+ keys = keys ?? Object.keys(cache);
150
+ if (!Array.isArray(keys)) keys = [keys];
151
+
152
+ for (const cacheKey of keys) {
153
+ cache[cacheKey] = undefined;
154
+ }
155
+ };
156
+ export const jsonSafeParse = (string, reviver) => {
157
+ if (typeof string !== 'string') return string;
158
+ const firstChar = string[0];
159
+ if (firstChar !== '{' && firstChar !== '[' && firstChar !== '"') return string;
160
+
161
+ try {
162
+ return JSON.parse(string, reviver);
163
+ } catch (e) {}
164
+
165
+ return string;
166
+ };
167
+ export const normalizeHttpResponse = request => {
168
+ var _response, _response2, _response3, _response4;
169
+
170
+ let {
171
+ response
172
+ } = request;
173
+
174
+ if (response === undefined) {
175
+ response = {};
176
+ } else if (((_response = response) === null || _response === void 0 ? void 0 : _response.statusCode) === undefined && ((_response2 = response) === null || _response2 === void 0 ? void 0 : _response2.body) === undefined && ((_response3 = response) === null || _response3 === void 0 ? void 0 : _response3.headers) === undefined) {
177
+ response = {
178
+ body: response
179
+ };
180
+ }
181
+
182
+ (_response4 = response).headers ?? (_response4.headers = {});
183
+ request.response = response;
184
+ return response;
185
+ };
186
+ const createErrorRegexp = /[^a-zA-Z]/g;
187
+ export const createError = (code, message, properties = {}) => {
188
+ const name = statuses[code].replace(createErrorRegexp, '');
189
+ const className = name.substr(-5) !== 'Error' ? name + 'Error' : name;
190
+
191
+ function HttpError(message) {
192
+ const msg = message ?? statuses[code];
193
+ const err = new Error(msg);
194
+ Error.captureStackTrace(err, HttpError);
195
+ Object.setPrototypeOf(err, HttpError.prototype);
196
+ Object.defineProperty(err, 'message', {
197
+ enumerable: true,
198
+ configurable: true,
199
+ value: msg,
200
+ writable: true
201
+ });
202
+ Object.defineProperty(err, 'name', {
203
+ enumerable: false,
204
+ configurable: true,
205
+ value: className,
206
+ writable: true
207
+ });
208
+ return err;
209
+ }
210
+
211
+ inherits(HttpError, Error);
212
+ const desc = Object.getOwnPropertyDescriptor(HttpError, 'name');
213
+ desc.value = className;
214
+ Object.defineProperty(HttpError, 'name', desc);
215
+ Object.assign(HttpError.prototype, {
216
+ status: code,
217
+ statusCode: code,
218
+ expose: code < 500
219
+ }, properties);
220
+ return new HttpError(message);
221
+ };
222
+ export default {
223
+ createPrefetchClient,
224
+ createClient,
225
+ canPrefetch,
226
+ getInternal,
227
+ sanitizeKey,
228
+ processCache,
229
+ getCache,
230
+ modifyCache,
231
+ clearCache,
232
+ jsonSafeParse,
233
+ normalizeHttpResponse,
234
+ createError
235
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middy/util",
3
- "version": "3.0.0-alpha.0",
3
+ "version": "3.0.0-alpha.4",
4
4
  "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (util package)",
5
5
  "type": "module",
6
6
  "engines": {
@@ -13,12 +13,14 @@
13
13
  "exports": "./index.js",
14
14
  "types": "index.d.ts",
15
15
  "files": [
16
+ "index.js",
16
17
  "index.d.ts",
17
18
  "codes.js"
18
19
  ],
19
20
  "scripts": {
20
21
  "test": "npm run test:unit",
21
- "test:unit": "ava"
22
+ "test:unit": "ava",
23
+ "test:benchmark": "node __benchmarks__/index.js"
22
24
  },
23
25
  "license": "MIT",
24
26
  "keywords": [
@@ -44,12 +46,12 @@
44
46
  "url": "https://github.com/middyjs/middy/issues"
45
47
  },
46
48
  "devDependencies": {
47
- "@middy/core": "^3.0.0-alpha.0",
49
+ "@middy/core": "^3.0.0-alpha.4",
48
50
  "@types/aws-lambda": "^8.10.76",
49
51
  "@types/node": "^17.0.0",
50
52
  "aws-sdk": "^2.939.0",
51
53
  "aws-xray-sdk": "^3.3.3"
52
54
  },
53
55
  "homepage": "https://github.com/middyjs/middy#readme",
54
- "gitHead": "c533f62841c8a39d061d7b94f30ba178f002c8db"
56
+ "gitHead": "d4bea7f4e21f6a9bbb1f6f6908361169598b9e53"
55
57
  }