@63klabs/cache-data 1.3.9 → 1.3.10
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/CHANGELOG.md +48 -7
- package/CONTRIBUTING.md +56 -3
- package/README.md +5 -5
- package/package.json +14 -26
- package/src/lib/dao-cache.js +25 -34
- package/src/lib/dao-endpoint.js +68 -38
- package/src/lib/tools/{APIRequest.class.js → ApiRequest.class.js} +164 -51
- package/src/lib/tools/CachedParametersSecrets.classes.js +10 -10
- package/src/lib/tools/ClientRequest.class.js +174 -25
- package/src/lib/tools/Connections.classes.js +5 -5
- package/src/lib/tools/Response.class.js +25 -0
- package/src/lib/tools/generic.response.html.js +8 -113
- package/src/lib/tools/generic.response.js +73 -0
- package/src/lib/tools/generic.response.json.js +5 -135
- package/src/lib/tools/generic.response.rss.js +10 -114
- package/src/lib/tools/generic.response.text.js +5 -115
- package/src/lib/tools/generic.response.xml.js +10 -114
- package/src/lib/tools/index.js +19 -8
- package/src/lib/utils/ValidationExecutor.class.js +8 -4
- package/src/lib/utils/ValidationMatcher.class.js +13 -1
- package/AGENTS.md +0 -1107
|
@@ -114,7 +114,7 @@ const DebugAndLog = require('./DebugAndLog.class.js');
|
|
|
114
114
|
|
|
115
115
|
/**
|
|
116
116
|
* @typedef {object} APIResponse
|
|
117
|
-
* @description Standard response object returned by
|
|
117
|
+
* @description Standard response object returned by ApiRequest.send()
|
|
118
118
|
*
|
|
119
119
|
* @property {boolean} success - Whether the request was successful (statusCode < 400)
|
|
120
120
|
* @property {number} statusCode - HTTP status code
|
|
@@ -143,12 +143,12 @@ const xRayProxy = (AWSXRay !== null) ? AWS.XRay.getSegment() : {
|
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
|
-
* An internal tools function used by
|
|
146
|
+
* An internal tools function used by ApiRequest. https.get does not work well
|
|
147
147
|
* inside a class object (specifically doesn't like this.*), so we make it
|
|
148
148
|
* external to the class and pass the class as a reference to be updated either
|
|
149
149
|
* with a response or redirect uri.
|
|
150
150
|
* @param {object} options The options object for https.get()
|
|
151
|
-
* @param {
|
|
151
|
+
* @param {ApiRequest} requestObject The ApiRequest object that contains internal functions, request info (including uri) and redirects. This object will be updated with any redirects and responses
|
|
152
152
|
* @returns A promise that will resolve to a boolean denoting whether or not the response is considered complete (no unresolved redirects). The boolean does not mean "error free." Even if we receive errors it is considered complete.
|
|
153
153
|
*/
|
|
154
154
|
const _httpGetExecute = async function (options, requestObject, xRaySegment = xRayProxy) {
|
|
@@ -202,7 +202,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
202
202
|
|
|
203
203
|
- ELSE We will produce an error of too many redirects.
|
|
204
204
|
*/
|
|
205
|
-
if ( redirects <
|
|
205
|
+
if ( redirects < ApiRequest.MAX_REDIRECTS ) {
|
|
206
206
|
|
|
207
207
|
// we'll gather variables to use in logging
|
|
208
208
|
let newLocation = res.headers.location;
|
|
@@ -232,8 +232,8 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
232
232
|
addRedirect(newLocation);
|
|
233
233
|
|
|
234
234
|
} else {
|
|
235
|
-
DebugAndLog.warn(`Too many redirects. Limit of ${
|
|
236
|
-
setResponse(
|
|
235
|
+
DebugAndLog.warn(`Too many redirects. Limit of ${ApiRequest.MAX_REDIRECTS}`);
|
|
236
|
+
setResponse(ApiRequest.responseFormat(false, 500, "Too many redirects"));
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
} else {
|
|
@@ -247,7 +247,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
247
247
|
if (res.statusCode === 304) {
|
|
248
248
|
// 304 not modified
|
|
249
249
|
DebugAndLog.debug("304 Not Modified. Setting body to null");
|
|
250
|
-
setResponse(
|
|
250
|
+
setResponse(ApiRequest.responseFormat(
|
|
251
251
|
true,
|
|
252
252
|
res.statusCode,
|
|
253
253
|
"SUCCESS",
|
|
@@ -312,7 +312,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
312
312
|
// xRaySegment.close(); // we are handling in calling func
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
setResponse(
|
|
315
|
+
setResponse(ApiRequest.responseFormat(
|
|
316
316
|
success,
|
|
317
317
|
res.statusCode,
|
|
318
318
|
(success ? "SUCCESS" : "FAIL"),
|
|
@@ -322,7 +322,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
322
322
|
} catch (error) {
|
|
323
323
|
DebugAndLog.error(`Error during http get callback for host ${requestObject.getHost()} ${requestObject.getNote()} ${error.message}`, error.stack);
|
|
324
324
|
xRaySegment.addError(error);
|
|
325
|
-
setResponse(
|
|
325
|
+
setResponse(ApiRequest.responseFormat(false, 500, "https.get resulted in error"));
|
|
326
326
|
}
|
|
327
327
|
});
|
|
328
328
|
|
|
@@ -330,7 +330,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
330
330
|
DebugAndLog.error(`API error during request/response for host ${requestObject.getHost()} ${requestObject.getNote()} ${error.message}`, error.stack);
|
|
331
331
|
xRaySegment.addError(error);
|
|
332
332
|
// xRaySegment.close(); // we are handling in calling func
|
|
333
|
-
setResponse(
|
|
333
|
+
setResponse(ApiRequest.responseFormat(false, 500, "https.get resulted in error"));
|
|
334
334
|
});
|
|
335
335
|
|
|
336
336
|
}
|
|
@@ -339,7 +339,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
339
339
|
} catch (error) {
|
|
340
340
|
DebugAndLog.error(`Error during http get callback for host ${requestObject.getHost()} ${requestObject.getNote()} ${error.message}`, error.stack);
|
|
341
341
|
xRaySegment.addError(error);
|
|
342
|
-
setResponse(
|
|
342
|
+
setResponse(ApiRequest.responseFormat(false, 500, "https.get resulted in error"));
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
});
|
|
@@ -350,7 +350,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
350
350
|
xRaySegment.addFaultFlag();
|
|
351
351
|
xRaySegment.addError(new Error("Endpoint request timeout reached"));
|
|
352
352
|
// xRaySegment.close(); // we are handling in calling func
|
|
353
|
-
setResponse(
|
|
353
|
+
setResponse(ApiRequest.responseFormat(false, 504, "https.request resulted in timeout"));
|
|
354
354
|
req.destroy(); //req.end()
|
|
355
355
|
|
|
356
356
|
});
|
|
@@ -360,7 +360,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
360
360
|
xRaySegment.addFaultFlag();
|
|
361
361
|
xRaySegment.addError(error);
|
|
362
362
|
// xRaySegment.close(); // we are handling in calling func
|
|
363
|
-
setResponse(
|
|
363
|
+
setResponse(ApiRequest.responseFormat(false, 500, "https.request resulted in error"));
|
|
364
364
|
});
|
|
365
365
|
|
|
366
366
|
if ( requestObject.getMethod() === "POST" && requestObject.getBody() !== null ) {
|
|
@@ -387,18 +387,18 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
387
387
|
* async call() {
|
|
388
388
|
* var response = null;
|
|
389
389
|
* try {
|
|
390
|
-
* var apiRequest = new tools.
|
|
390
|
+
* var apiRequest = new tools.ApiRequest(this.request);
|
|
391
391
|
* response = await apiRequest.send();
|
|
392
392
|
* } catch (error) {
|
|
393
393
|
* DebugAndLog.error(`Error in call: ${error.message}`, error.stack);
|
|
394
|
-
* response = tools.
|
|
394
|
+
* response = tools.ApiRequest.responseFormat(false, 500, "Error in call()");
|
|
395
395
|
* }
|
|
396
396
|
* return response;
|
|
397
397
|
* }
|
|
398
398
|
*
|
|
399
399
|
* @example
|
|
400
400
|
* // Using pagination feature
|
|
401
|
-
* const apiRequest = new tools.
|
|
401
|
+
* const apiRequest = new tools.ApiRequest({
|
|
402
402
|
* host: 'api.example.com',
|
|
403
403
|
* path: '/data',
|
|
404
404
|
* pagination: {
|
|
@@ -412,7 +412,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
412
412
|
*
|
|
413
413
|
* @example
|
|
414
414
|
* // Using retry feature
|
|
415
|
-
* const apiRequest = new tools.
|
|
415
|
+
* const apiRequest = new tools.ApiRequest({
|
|
416
416
|
* host: 'api.example.com',
|
|
417
417
|
* path: '/data',
|
|
418
418
|
* retry: {
|
|
@@ -425,7 +425,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
425
425
|
*
|
|
426
426
|
* @example
|
|
427
427
|
* // Using both pagination and retry
|
|
428
|
-
* const apiRequest = new tools.
|
|
428
|
+
* const apiRequest = new tools.ApiRequest({
|
|
429
429
|
* host: 'api.example.com',
|
|
430
430
|
* path: '/data',
|
|
431
431
|
* pagination: { enabled: true },
|
|
@@ -438,7 +438,7 @@ const _httpGetExecute = async function (options, requestObject, xRaySegment = xR
|
|
|
438
438
|
* console.log('Pagination:', response.metadata.pagination);
|
|
439
439
|
* }
|
|
440
440
|
*/
|
|
441
|
-
class
|
|
441
|
+
class ApiRequest {
|
|
442
442
|
|
|
443
443
|
static MAX_REDIRECTS = 5;
|
|
444
444
|
|
|
@@ -489,7 +489,7 @@ class APIRequest {
|
|
|
489
489
|
*
|
|
490
490
|
* @example
|
|
491
491
|
* // Basic request without pagination or retry
|
|
492
|
-
* const request = new
|
|
492
|
+
* const request = new ApiRequest({
|
|
493
493
|
* host: 'api.example.com',
|
|
494
494
|
* path: '/users',
|
|
495
495
|
* parameters: { limit: 10 }
|
|
@@ -498,7 +498,7 @@ class APIRequest {
|
|
|
498
498
|
*
|
|
499
499
|
* @example
|
|
500
500
|
* // Request with minimal pagination configuration (uses all defaults)
|
|
501
|
-
* const request = new
|
|
501
|
+
* const request = new ApiRequest({
|
|
502
502
|
* host: 'api.example.com',
|
|
503
503
|
* path: '/data',
|
|
504
504
|
* pagination: { enabled: true }
|
|
@@ -508,7 +508,7 @@ class APIRequest {
|
|
|
508
508
|
*
|
|
509
509
|
* @example
|
|
510
510
|
* // Request with custom pagination labels
|
|
511
|
-
* const request = new
|
|
511
|
+
* const request = new ApiRequest({
|
|
512
512
|
* host: 'api.example.com',
|
|
513
513
|
* path: '/data',
|
|
514
514
|
* pagination: {
|
|
@@ -524,7 +524,7 @@ class APIRequest {
|
|
|
524
524
|
*
|
|
525
525
|
* @example
|
|
526
526
|
* // Request with minimal retry configuration (uses all defaults)
|
|
527
|
-
* const request = new
|
|
527
|
+
* const request = new ApiRequest({
|
|
528
528
|
* host: 'api.example.com',
|
|
529
529
|
* path: '/data',
|
|
530
530
|
* retry: { enabled: true }
|
|
@@ -534,7 +534,7 @@ class APIRequest {
|
|
|
534
534
|
*
|
|
535
535
|
* @example
|
|
536
536
|
* // Request with custom retry configuration
|
|
537
|
-
* const request = new
|
|
537
|
+
* const request = new ApiRequest({
|
|
538
538
|
* host: 'api.example.com',
|
|
539
539
|
* path: '/data',
|
|
540
540
|
* retry: {
|
|
@@ -551,7 +551,7 @@ class APIRequest {
|
|
|
551
551
|
*
|
|
552
552
|
* @example
|
|
553
553
|
* // Request with both pagination and retry
|
|
554
|
-
* const request = new
|
|
554
|
+
* const request = new ApiRequest({
|
|
555
555
|
* host: 'api.example.com',
|
|
556
556
|
* path: '/data',
|
|
557
557
|
* pagination: { enabled: true },
|
|
@@ -1024,7 +1024,7 @@ class APIRequest {
|
|
|
1024
1024
|
|
|
1025
1025
|
/**
|
|
1026
1026
|
* Fetch a single page of paginated results. This private method creates a new
|
|
1027
|
-
*
|
|
1027
|
+
* ApiRequest instance for a specific page offset and retrieves that page's data.
|
|
1028
1028
|
* If X-Ray is available, it creates a subsegment to track the page request.
|
|
1029
1029
|
*
|
|
1030
1030
|
* @private
|
|
@@ -1060,7 +1060,7 @@ class APIRequest {
|
|
|
1060
1060
|
|
|
1061
1061
|
// Create subsegment for this paginated request if X-Ray is available
|
|
1062
1062
|
if (AWSXRay) {
|
|
1063
|
-
const subsegmentName = `
|
|
1063
|
+
const subsegmentName = `ApiRequest/${this.getHost()}/Page-${offset}`;
|
|
1064
1064
|
|
|
1065
1065
|
return await AWSXRay.captureAsyncFunc(subsegmentName, async (subsegment) => {
|
|
1066
1066
|
try {
|
|
@@ -1077,8 +1077,8 @@ class APIRequest {
|
|
|
1077
1077
|
parentNote: this.#request.note
|
|
1078
1078
|
});
|
|
1079
1079
|
|
|
1080
|
-
// Create new
|
|
1081
|
-
const pageApiRequest = new
|
|
1080
|
+
// Create new ApiRequest instance for this page
|
|
1081
|
+
const pageApiRequest = new ApiRequest(pageRequest);
|
|
1082
1082
|
const response = await pageApiRequest.send();
|
|
1083
1083
|
|
|
1084
1084
|
subsegment.addAnnotation('success', response.success ? "true" : "false");
|
|
@@ -1095,7 +1095,7 @@ class APIRequest {
|
|
|
1095
1095
|
});
|
|
1096
1096
|
} else {
|
|
1097
1097
|
// No X-Ray available, just create and send the request
|
|
1098
|
-
const pageApiRequest = new
|
|
1098
|
+
const pageApiRequest = new ApiRequest(pageRequest);
|
|
1099
1099
|
return await pageApiRequest.send();
|
|
1100
1100
|
}
|
|
1101
1101
|
}
|
|
@@ -1215,13 +1215,13 @@ class APIRequest {
|
|
|
1215
1215
|
*
|
|
1216
1216
|
* @example
|
|
1217
1217
|
* // Basic request
|
|
1218
|
-
* const apiRequest = new
|
|
1218
|
+
* const apiRequest = new ApiRequest({ host: 'api.example.com', path: '/users' });
|
|
1219
1219
|
* const response = await apiRequest.send();
|
|
1220
1220
|
* console.log(response.body);
|
|
1221
1221
|
*
|
|
1222
1222
|
* @example
|
|
1223
1223
|
* // Request with pagination
|
|
1224
|
-
* const apiRequest = new
|
|
1224
|
+
* const apiRequest = new ApiRequest({
|
|
1225
1225
|
* host: 'api.example.com',
|
|
1226
1226
|
* path: '/data',
|
|
1227
1227
|
* pagination: { enabled: true }
|
|
@@ -1233,7 +1233,7 @@ class APIRequest {
|
|
|
1233
1233
|
*
|
|
1234
1234
|
* @example
|
|
1235
1235
|
* // Request with retry
|
|
1236
|
-
* const apiRequest = new
|
|
1236
|
+
* const apiRequest = new ApiRequest({
|
|
1237
1237
|
* host: 'api.example.com',
|
|
1238
1238
|
* path: '/data',
|
|
1239
1239
|
* retry: { enabled: true, maxRetries: 2 }
|
|
@@ -1327,7 +1327,7 @@ class APIRequest {
|
|
|
1327
1327
|
if (AWSXRay) {
|
|
1328
1328
|
|
|
1329
1329
|
// Use timestamp to ensure unique subsegment names for each request
|
|
1330
|
-
const subsegmentName = `
|
|
1330
|
+
const subsegmentName = `ApiRequest/${this.getHost()}/${Date.now()}`;
|
|
1331
1331
|
|
|
1332
1332
|
await AWSXRay.captureAsyncFunc(subsegmentName, async (subsegment) => {
|
|
1333
1333
|
|
|
@@ -1384,7 +1384,7 @@ class APIRequest {
|
|
|
1384
1384
|
|
|
1385
1385
|
return true;
|
|
1386
1386
|
} catch (error) {
|
|
1387
|
-
DebugAndLog.error(`Error in
|
|
1387
|
+
DebugAndLog.error(`Error in ApiRequest call to remote endpoint (${this.getNote()}): ${error.message}`, error.stack);
|
|
1388
1388
|
subsegment.addError(error);
|
|
1389
1389
|
throw error;
|
|
1390
1390
|
} finally {
|
|
@@ -1438,12 +1438,12 @@ class APIRequest {
|
|
|
1438
1438
|
resolve( this.#response );
|
|
1439
1439
|
}
|
|
1440
1440
|
catch (error) {
|
|
1441
|
-
DebugAndLog.error(`Error in
|
|
1442
|
-
resolve(
|
|
1441
|
+
DebugAndLog.error(`Error in ApiRequest call to _httpGetExecute (${this.getNote()}): ${error.message}`, error.stack);
|
|
1442
|
+
resolve(ApiRequest.responseFormat(false, 500, "Error during send request"));
|
|
1443
1443
|
}
|
|
1444
1444
|
} catch (error) {
|
|
1445
|
-
DebugAndLog.error(`API error while trying request for host ${this.getHost()} ${this.getNote()} ${error.message}`, {
|
|
1446
|
-
resolve(
|
|
1445
|
+
DebugAndLog.error(`API error while trying request for host ${this.getHost()} ${this.getNote()} ${error.message}`, { ApiRequest: this.toObject(), trace: error.stack } );
|
|
1446
|
+
resolve(ApiRequest.responseFormat(false, 500, "Error during send request"));
|
|
1447
1447
|
|
|
1448
1448
|
}
|
|
1449
1449
|
});
|
|
@@ -1461,7 +1461,7 @@ class APIRequest {
|
|
|
1461
1461
|
toObject() {
|
|
1462
1462
|
|
|
1463
1463
|
return {
|
|
1464
|
-
MAX_REDIRECTS:
|
|
1464
|
+
MAX_REDIRECTS: ApiRequest.MAX_REDIRECTS,
|
|
1465
1465
|
request: this.#request,
|
|
1466
1466
|
requestComplete: this.#requestComplete,
|
|
1467
1467
|
redirects: this.#redirects,
|
|
@@ -1470,6 +1470,126 @@ class APIRequest {
|
|
|
1470
1470
|
|
|
1471
1471
|
};
|
|
1472
1472
|
|
|
1473
|
+
/**
|
|
1474
|
+
* Creates a standardized response format object using a destructured options
|
|
1475
|
+
* parameter. This is the core formatting method that all other response
|
|
1476
|
+
* formatting methods delegate to. Unlike `responseFormat()`, which uses
|
|
1477
|
+
* positional arguments, `format()` accepts a single object so callers can
|
|
1478
|
+
* specify only the fields they need.
|
|
1479
|
+
*
|
|
1480
|
+
* @param {boolean} [success=false] - Whether the operation succeeded
|
|
1481
|
+
* @param {number} [statusCode=0] - HTTP status code
|
|
1482
|
+
* @param {string|null} [message=null] - Human-readable status message
|
|
1483
|
+
* @param {object|null} [headers=null] - Response headers
|
|
1484
|
+
* @param {object|string|null} [body=null] - Response body
|
|
1485
|
+
* @returns {{success: boolean, statusCode: number, message: string|null, headers: object|null, body: object|string|null}} Response_Format_Object with exactly five properties
|
|
1486
|
+
*
|
|
1487
|
+
* @example
|
|
1488
|
+
* // Create a response with defaults (no arguments)
|
|
1489
|
+
* const response = ApiRequest.format();
|
|
1490
|
+
* // { success: false, statusCode: 0, message: null, headers: null, body: null }
|
|
1491
|
+
*
|
|
1492
|
+
* @example
|
|
1493
|
+
* // Create a response specifying only the fields you need
|
|
1494
|
+
* const response = ApiRequest.format({ success: true, statusCode: 200, body: { id: 1 } });
|
|
1495
|
+
* // { success: true, statusCode: 200, message: null, headers: null, body: { id: 1 } }
|
|
1496
|
+
*/
|
|
1497
|
+
static format({
|
|
1498
|
+
success = false,
|
|
1499
|
+
statusCode = 0,
|
|
1500
|
+
message = null,
|
|
1501
|
+
headers = null,
|
|
1502
|
+
body = null
|
|
1503
|
+
} = {}) {
|
|
1504
|
+
return { success, statusCode, message, headers, body };
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
/**
|
|
1508
|
+
* Shortcut for creating a successful response format object with
|
|
1509
|
+
* success-oriented defaults. Delegates to `format()` for construction.
|
|
1510
|
+
*
|
|
1511
|
+
* @param {boolean} [success=true] - Whether the operation succeeded
|
|
1512
|
+
* @param {number} [statusCode=200] - HTTP status code
|
|
1513
|
+
* @param {string|null} [message="SUCCESS"] - Human-readable status message
|
|
1514
|
+
* @param {object|null} [headers=null] - Response headers
|
|
1515
|
+
* @param {object|string|null} [body=null] - Response body
|
|
1516
|
+
* @returns {{success: boolean, statusCode: number, message: string|null, headers: object|null, body: object|string|null}} Response_Format_Object with exactly five properties
|
|
1517
|
+
*
|
|
1518
|
+
* @example
|
|
1519
|
+
* // Create a success response with defaults
|
|
1520
|
+
* const response = ApiRequest.success();
|
|
1521
|
+
* // { success: true, statusCode: 200, message: "SUCCESS", headers: null, body: null }
|
|
1522
|
+
*/
|
|
1523
|
+
static success({
|
|
1524
|
+
success = true,
|
|
1525
|
+
statusCode = 200,
|
|
1526
|
+
message = "SUCCESS",
|
|
1527
|
+
headers = null,
|
|
1528
|
+
body = null
|
|
1529
|
+
} = {}) {
|
|
1530
|
+
return ApiRequest.format({ success, statusCode, message, headers, body });
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1533
|
+
/**
|
|
1534
|
+
* Shortcut for creating an error response format object with
|
|
1535
|
+
* error-oriented defaults. Delegates to `format()` for construction.
|
|
1536
|
+
*
|
|
1537
|
+
* @param {boolean} [success=false] - Whether the operation succeeded
|
|
1538
|
+
* @param {number} [statusCode=500] - HTTP status code
|
|
1539
|
+
* @param {string|null} [message="ERROR"] - Human-readable status message
|
|
1540
|
+
* @param {object|null} [headers=null] - Response headers
|
|
1541
|
+
* @param {object|string|null} [body=null] - Response body
|
|
1542
|
+
* @returns {{success: boolean, statusCode: number, message: string|null, headers: object|null, body: object|string|null}} Response_Format_Object with exactly five properties
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* // Create an error response with defaults
|
|
1546
|
+
* const response = ApiRequest.error();
|
|
1547
|
+
* // { success: false, statusCode: 500, message: "ERROR", headers: null, body: null }
|
|
1548
|
+
*/
|
|
1549
|
+
static error({
|
|
1550
|
+
success = false,
|
|
1551
|
+
statusCode = 500,
|
|
1552
|
+
message = "ERROR",
|
|
1553
|
+
headers = null,
|
|
1554
|
+
body = null
|
|
1555
|
+
} = {}) {
|
|
1556
|
+
return ApiRequest.format({ success, statusCode, message, headers, body });
|
|
1557
|
+
};
|
|
1558
|
+
|
|
1559
|
+
/**
|
|
1560
|
+
* Convert a Format_Options object into an Api_Gateway_Object suitable for
|
|
1561
|
+
* returning directly from an AWS Lambda handler to API Gateway. Delegates
|
|
1562
|
+
* to `format()` for normalization, then extracts `statusCode`, `headers`,
|
|
1563
|
+
* and `body`. Object bodies are stringified with `JSON.stringify()`;
|
|
1564
|
+
* string and `null` bodies pass through unchanged.
|
|
1565
|
+
*
|
|
1566
|
+
* @param {boolean} [success=false] - Whether the operation succeeded (not included in output)
|
|
1567
|
+
* @param {number} [statusCode=0] - HTTP status code
|
|
1568
|
+
* @param {string|null} [message=null] - Human-readable status message (not included in output)
|
|
1569
|
+
* @param {object|null} [headers=null] - Response headers
|
|
1570
|
+
* @param {object|string|null} [body=null] - Response body (objects are JSON.stringified)
|
|
1571
|
+
* @returns {{statusCode: number, headers: object|null, body: string|null}} Api_Gateway_Object with exactly three properties
|
|
1572
|
+
*
|
|
1573
|
+
* @example
|
|
1574
|
+
* // Create an API Gateway response with an object body
|
|
1575
|
+
* const response = ApiRequest.apiGateway({ statusCode: 200, body: { id: 1 } });
|
|
1576
|
+
* // { statusCode: 200, headers: null, body: '{"id":1}' }
|
|
1577
|
+
*/
|
|
1578
|
+
static apiGateway({
|
|
1579
|
+
success = false,
|
|
1580
|
+
statusCode = 0,
|
|
1581
|
+
message = null,
|
|
1582
|
+
headers = null,
|
|
1583
|
+
body = null
|
|
1584
|
+
} = {}) {
|
|
1585
|
+
const resp = ApiRequest.format({ success, statusCode, message, headers, body });
|
|
1586
|
+
return {
|
|
1587
|
+
statusCode: resp.statusCode,
|
|
1588
|
+
headers: resp.headers,
|
|
1589
|
+
body: (resp.body !== null && typeof resp.body === "object") ? JSON.stringify(resp.body) : resp.body
|
|
1590
|
+
};
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1473
1593
|
/**
|
|
1474
1594
|
* Formats the response for returning to program logic. When pagination or retry
|
|
1475
1595
|
* features are used, the response may include an optional metadata field with
|
|
@@ -1489,12 +1609,12 @@ class APIRequest {
|
|
|
1489
1609
|
*
|
|
1490
1610
|
* @example
|
|
1491
1611
|
* // Basic response format
|
|
1492
|
-
* const response =
|
|
1612
|
+
* const response = ApiRequest.responseFormat(true, 200, "SUCCESS", headers, body);
|
|
1493
1613
|
* // { success: true, statusCode: 200, headers: {...}, body: "...", message: "SUCCESS" }
|
|
1494
1614
|
*
|
|
1495
1615
|
* @example
|
|
1496
1616
|
* // Error response format
|
|
1497
|
-
* const response =
|
|
1617
|
+
* const response = ApiRequest.responseFormat(false, 500, "Internal Server Error");
|
|
1498
1618
|
* // { success: false, statusCode: 500, headers: null, body: null, message: "Internal Server Error" }
|
|
1499
1619
|
*
|
|
1500
1620
|
* @example
|
|
@@ -1514,15 +1634,8 @@ class APIRequest {
|
|
|
1514
1634
|
* // }
|
|
1515
1635
|
*/
|
|
1516
1636
|
static responseFormat(success = false, statusCode = 0, message = null, headers = null, body = null) {
|
|
1517
|
-
|
|
1518
|
-
return {
|
|
1519
|
-
success: success,
|
|
1520
|
-
statusCode: statusCode,
|
|
1521
|
-
headers: headers,
|
|
1522
|
-
body: body,
|
|
1523
|
-
message: message
|
|
1524
|
-
};
|
|
1637
|
+
return ApiRequest.format({ success, statusCode, message, headers, body });
|
|
1525
1638
|
};
|
|
1526
1639
|
};
|
|
1527
1640
|
|
|
1528
|
-
module.exports =
|
|
1641
|
+
module.exports = ApiRequest;
|
|
@@ -22,7 +22,7 @@ const Timer = require('./Timer.class');
|
|
|
22
22
|
* @class CachedParameterSecrets - Container class for CachedParameterSecret objects
|
|
23
23
|
* @example
|
|
24
24
|
* // Create parameters and secrets
|
|
25
|
-
* const dbPassword = new
|
|
25
|
+
* const dbPassword = new CachedSsmParameter('/myapp/db/password');
|
|
26
26
|
* const apiKey = new CachedSecret('myapp-api-key');
|
|
27
27
|
*
|
|
28
28
|
* // Prime all parameters and secrets before use
|
|
@@ -140,7 +140,7 @@ class CachedParameterSecrets {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
* @class CachedParameterSecret - Base class for
|
|
143
|
+
* @class CachedParameterSecret - Base class for CachedSsmParameter and CachedSecret
|
|
144
144
|
* Accesses data through Systems Manager Parameter Store and Secrets Manager Lambda Extension
|
|
145
145
|
* Since the Lambda Extension runs a localhost via http, it handles it's own http request. Also,
|
|
146
146
|
* since the lambda extension needs time to boot during a cold start, it is not available during
|
|
@@ -156,7 +156,7 @@ class CachedParameterSecrets {
|
|
|
156
156
|
* }
|
|
157
157
|
*
|
|
158
158
|
* async main () => {
|
|
159
|
-
* const myParam = new
|
|
159
|
+
* const myParam = new CachedSsmParameter('myParam');
|
|
160
160
|
* myParam.prime(); // gets things started in the background
|
|
161
161
|
*
|
|
162
162
|
* // ... some code that may take a few ms to run ...
|
|
@@ -250,7 +250,7 @@ class CachedParameterSecret {
|
|
|
250
250
|
* @returns {string} The constructor name
|
|
251
251
|
*/
|
|
252
252
|
instanceof() {
|
|
253
|
-
return this.constructor.name; //((this instanceof
|
|
253
|
+
return this.constructor.name; //((this instanceof CachedSsmParameter) ? 'CachedSsmParameter' : 'CachedSecret');
|
|
254
254
|
};
|
|
255
255
|
|
|
256
256
|
/**
|
|
@@ -473,11 +473,11 @@ class CachedParameterSecret {
|
|
|
473
473
|
}
|
|
474
474
|
|
|
475
475
|
/**
|
|
476
|
-
*
|
|
476
|
+
* CachedSsmParameter extends CachedParameterSecret and is used to retrieve parameters from AWS Systems Manager Parameter Store
|
|
477
477
|
* @extends CachedParameterSecret
|
|
478
478
|
* @example
|
|
479
479
|
* // Create a cached SSM parameter
|
|
480
|
-
* const dbPassword = new
|
|
480
|
+
* const dbPassword = new CachedSsmParameter('/myapp/db/password');
|
|
481
481
|
*
|
|
482
482
|
* // Get the parameter value (async)
|
|
483
483
|
* const password = await dbPassword.getValue();
|
|
@@ -485,7 +485,7 @@ class CachedParameterSecret {
|
|
|
485
485
|
*
|
|
486
486
|
* @example
|
|
487
487
|
* // Use with synchronous functions after priming
|
|
488
|
-
* const apiKey = new
|
|
488
|
+
* const apiKey = new CachedSsmParameter('/myapp/api/key');
|
|
489
489
|
*
|
|
490
490
|
* async function init() {
|
|
491
491
|
* // Prime the parameter in the background
|
|
@@ -501,7 +501,7 @@ class CachedParameterSecret {
|
|
|
501
501
|
* return key;
|
|
502
502
|
* }
|
|
503
503
|
*/
|
|
504
|
-
class
|
|
504
|
+
class CachedSsmParameter extends CachedParameterSecret {
|
|
505
505
|
/**
|
|
506
506
|
* Returns the URL path for the AWS Parameters and Secrets Lambda Extension to retrieve this SSM parameter
|
|
507
507
|
* @returns {string} The URL path with encoded parameter name
|
|
@@ -578,7 +578,7 @@ class CachedSecret extends CachedParameterSecret {
|
|
|
578
578
|
module.exports = {
|
|
579
579
|
CachedParameterSecrets,
|
|
580
580
|
CachedParameterSecret,
|
|
581
|
-
|
|
582
|
-
|
|
581
|
+
CachedSsmParameter,
|
|
582
|
+
CachedSSMParameter: CachedSsmParameter,
|
|
583
583
|
CachedSecret
|
|
584
584
|
}
|