@63klabs/cache-data 1.3.8 → 1.3.9
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/AGENTS.md +96 -1
- package/CHANGELOG.md +63 -0
- package/CONTRIBUTING.md +2 -2
- package/README.md +17 -31
- package/package.json +5 -4
- package/src/lib/dao-cache.js +30 -13
- package/src/lib/tools/AWS.classes.js +58 -5
- package/src/lib/tools/CachedParametersSecrets.classes.js +1 -0
- package/src/lib/tools/ClientRequest.class.js +826 -32
- package/src/lib/tools/index.js +96 -34
- package/src/lib/utils/ValidationExecutor.class.js +66 -0
- package/src/lib/utils/ValidationMatcher.class.js +405 -0
package/AGENTS.md
CHANGED
|
@@ -234,7 +234,102 @@ src/
|
|
|
234
234
|
5. **Immutability**: Prefer immutable objects where possible
|
|
235
235
|
6. **Error Handling**: Always handle errors gracefully, log appropriately
|
|
236
236
|
|
|
237
|
-
### 3.4
|
|
237
|
+
### 3.4 Non-Public Class Organization
|
|
238
|
+
|
|
239
|
+
**CRITICAL**: Not all classes should be exported in the public API. Internal implementation classes must be kept separate from user-facing APIs.
|
|
240
|
+
|
|
241
|
+
#### Directory Structure for Classes
|
|
242
|
+
|
|
243
|
+
- **`src/lib/tools/`**: Public API classes and utilities
|
|
244
|
+
- Classes exported in `src/lib/tools/index.js`
|
|
245
|
+
- User-facing functionality
|
|
246
|
+
- Examples: `DebugAndLog`, `Timer`, `Response`, `APIRequest`
|
|
247
|
+
|
|
248
|
+
- **`src/lib/utils/`**: Internal implementation classes
|
|
249
|
+
- Classes NOT exported in public API
|
|
250
|
+
- Used internally by public classes
|
|
251
|
+
- Examples: `InMemoryCache`, `ValidationExecutor`, `ValidationMatcher`
|
|
252
|
+
|
|
253
|
+
#### When to Use Each Directory
|
|
254
|
+
|
|
255
|
+
**Use `src/lib/tools/` when:**
|
|
256
|
+
- Class is part of the public API
|
|
257
|
+
- Users need direct access to the class
|
|
258
|
+
- Class is exported in `src/index.js` or `src/lib/tools/index.js`
|
|
259
|
+
- Class provides user-facing functionality
|
|
260
|
+
|
|
261
|
+
**Use `src/lib/utils/` when:**
|
|
262
|
+
- Class is internal implementation detail
|
|
263
|
+
- Class is only used by other classes in the package
|
|
264
|
+
- Class should not be exposed to users
|
|
265
|
+
- Class is a helper or utility for internal use
|
|
266
|
+
|
|
267
|
+
#### Example: ValidationExecutor and ValidationMatcher
|
|
268
|
+
|
|
269
|
+
These classes are internal to ClientRequest's validation system:
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
// src/lib/utils/ValidationExecutor.class.js
|
|
273
|
+
// Internal class - not exported in public API
|
|
274
|
+
class ValidationExecutor {
|
|
275
|
+
static execute(validateFn, paramNames, paramValues) {
|
|
276
|
+
// Implementation
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/lib/utils/ValidationMatcher.class.js
|
|
281
|
+
// Internal class - not exported in public API
|
|
282
|
+
class ValidationMatcher {
|
|
283
|
+
constructor(paramValidations, httpMethod, resourcePath) {
|
|
284
|
+
// Implementation
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/lib/tools/ClientRequest.class.js
|
|
289
|
+
// Public class - uses internal classes
|
|
290
|
+
const ValidationMatcher = require('../utils/ValidationMatcher.class');
|
|
291
|
+
const ValidationExecutor = require('../utils/ValidationExecutor.class');
|
|
292
|
+
|
|
293
|
+
class ClientRequest {
|
|
294
|
+
// Uses ValidationMatcher and ValidationExecutor internally
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Testing Internal Classes
|
|
299
|
+
|
|
300
|
+
Internal classes can still be tested using direct imports in test files:
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
// test/request/validation/unit/validation-executor-tests.jest.mjs
|
|
304
|
+
const ValidationExecutorModule = await import('../../../../src/lib/utils/ValidationExecutor.class.js');
|
|
305
|
+
const ValidationExecutor = ValidationExecutorModule.default;
|
|
306
|
+
|
|
307
|
+
describe('ValidationExecutor', () => {
|
|
308
|
+
it('should execute validation correctly', () => {
|
|
309
|
+
// Test internal class
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### Rules for AI Assistants
|
|
315
|
+
|
|
316
|
+
When creating new classes:
|
|
317
|
+
|
|
318
|
+
1. **Determine visibility**: Is this class part of the public API?
|
|
319
|
+
2. **Choose directory**:
|
|
320
|
+
- Public API → `src/lib/tools/`
|
|
321
|
+
- Internal implementation → `src/lib/utils/`
|
|
322
|
+
3. **Update exports**: Only export public classes in `src/lib/tools/index.js`
|
|
323
|
+
4. **Document clearly**: Mark internal classes with `@private` JSDoc tag
|
|
324
|
+
5. **Test appropriately**: Internal classes can be tested directly
|
|
325
|
+
|
|
326
|
+
**DO NOT**:
|
|
327
|
+
- Export internal classes in public API
|
|
328
|
+
- Place public API classes in `src/lib/utils/`
|
|
329
|
+
- Mix concerns between directories
|
|
330
|
+
- Change class location without updating all imports
|
|
331
|
+
|
|
332
|
+
### 3.5 Adding New Functionality
|
|
238
333
|
|
|
239
334
|
**Before adding new methods or classes:**
|
|
240
335
|
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,69 @@ To report an issue, or to see proposed and upcoming enhancements, check out [63K
|
|
|
8
8
|
|
|
9
9
|
Report all vulnerabilities under the [Security menu](https://github.com/63Klabs/cache-data/security/advisories) in the Cache-Data GitHub repository.
|
|
10
10
|
|
|
11
|
+
## v1.3.9 (unreleased)
|
|
12
|
+
|
|
13
|
+
- Unreleased
|
|
14
|
+
|
|
15
|
+
## v1.3.9 (2026-03-09)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **Body Parameter Validation for ClientRequest** [Spec: 1-3-9-body-validation-and-header-format-fix](.kiro/specs/1-3-9-body-validation-and-header-format-fix/)
|
|
19
|
+
- **Body Parameter Validation**: ClientRequest now validates body parameters using the same validation framework as path, query, header, and cookie parameters
|
|
20
|
+
- Automatic JSON parsing with error handling for request bodies
|
|
21
|
+
- Support for both API Gateway v1 and v2 formats
|
|
22
|
+
- Validation using existing ValidationMatcher and ValidationExecutor classes
|
|
23
|
+
- Body validation integrated into validation chain after cookie validation
|
|
24
|
+
- `getBodyParameters()` method now returns validated body parameters
|
|
25
|
+
- **Header Key Conversion Utility**: New static method `convertHeaderKeyToCamelCase(headerKey)` helps developers determine correct validation rule keys
|
|
26
|
+
- Converts HTTP header names from kebab-case to camelCase (e.g., `content-type` → `contentType`)
|
|
27
|
+
- Handles multiple hyphens and uppercase input correctly
|
|
28
|
+
- Documented with examples of common HTTP headers
|
|
29
|
+
- **Enhanced Documentation**: Comprehensive JSDoc documentation for header key conversion behavior
|
|
30
|
+
- Header key conversion reference table showing HTTP headers and their camelCase equivalents
|
|
31
|
+
- Detailed explanation of conversion algorithm and why it's necessary
|
|
32
|
+
- Examples showing validation configuration with converted header keys
|
|
33
|
+
- Complete body validation examples with error handling
|
|
34
|
+
- **Backwards Compatible**: All new features are opt-in and maintain full backwards compatibility
|
|
35
|
+
- Existing code continues to work without modification
|
|
36
|
+
- Body validation only activates when configured
|
|
37
|
+
- No changes to existing validation behavior for other parameter types
|
|
38
|
+
- **Comprehensive Testing**: 8 property-based tests and extensive unit/integration tests validate correctness properties
|
|
39
|
+
- Body validation round-trip property
|
|
40
|
+
- Validation failure propagation
|
|
41
|
+
- JSON parsing precondition
|
|
42
|
+
- Header key conversion correctness
|
|
43
|
+
- Backwards compatibility preservation
|
|
44
|
+
- Common validation pattern support
|
|
45
|
+
- Multi-parameter validation interface
|
|
46
|
+
|
|
47
|
+
### Security
|
|
48
|
+
- **Fixed npm security vulnerabilities in serialize-javascript dependency** [Spec: 1-3-9-npm-security-vulnerabilities-fix](.kiro/specs/1-3-9-npm-security-vulnerabilities-fix/)
|
|
49
|
+
- Fixed 2 high severity vulnerabilities in serialize-javascript (RCE via RegExp.flags and Date.prototype.toISOString)
|
|
50
|
+
- Added npm override for serialize-javascript >=7.0.3 to force secure version
|
|
51
|
+
- No breaking changes to public APIs
|
|
52
|
+
- All existing tests pass
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- **Enhanced Validation System for ClientRequest** [Spec: 1-3-9-improve-validations-object](.kiro/specs/1-3-9-improve-validations-object/)
|
|
56
|
+
- **Route-Specific Validations**: Define different validation rules for the same parameter name in different routes (e.g., `id` in `/product/{id}` vs `/employee/{id}`)
|
|
57
|
+
- **Method-Specific Validations**: Define different validation rules based on HTTP method (e.g., stricter validation for `POST` than `GET`)
|
|
58
|
+
- **Method-and-Route Validations**: Most precise control with validation rules for specific method-route combinations (e.g., `POST:join/{id}`)
|
|
59
|
+
- **Multi-Parameter Validations**: Validate multiple parameters together to enforce cross-parameter constraints
|
|
60
|
+
- **Clear Priority Order**: Four-tier priority system (method-and-route > route-only > method-only > global)
|
|
61
|
+
- **Backwards Compatible**: Existing global parameter validations continue to work without any code changes
|
|
62
|
+
- **Performance Optimized**: Pattern normalization caching and early exit optimization for minimal overhead
|
|
63
|
+
- **Comprehensive Testing**: 15 correctness properties validated through property-based testing
|
|
64
|
+
|
|
65
|
+
### Enhancement
|
|
66
|
+
- **AppConfig Async Initialization Optimization** [Spec: 1-3-9-appconfig-async-init-optimization](.kiro/specs/1-3-9-appconfig-async-init-optimization/)
|
|
67
|
+
- **Parallel Initialization**: All AppConfig.init() operations now execute asynchronously in parallel, improving Lambda cold start performance by 10-20%
|
|
68
|
+
- **Backwards Compatible**: No API changes - existing code continues to work without modifications
|
|
69
|
+
- **Optimized Operations**: Settings, connections, validations, responses, and SSM parameters all initialize concurrently
|
|
70
|
+
- **Error Resilient**: Individual initialization failures don't block other operations
|
|
71
|
+
- **Transparent**: Debug logging and error handling work identically to previous implementation
|
|
72
|
+
- **Performance**: Cold start time reduced from 62-212ms to 50-200ms (sequential to parallel execution)
|
|
73
|
+
|
|
11
74
|
## v1.3.8 (2026-03-02)
|
|
12
75
|
|
|
13
76
|
### Security
|
package/CONTRIBUTING.md
CHANGED
|
@@ -26,7 +26,7 @@ Spec-Driven, AI-Assisted Engineering (SD-AI) is a software development methodolo
|
|
|
26
26
|
|
|
27
27
|
Code must be reviewed, understood, and tested by a human before being merged.
|
|
28
28
|
|
|
29
|
-
Kiro is the required AI coding assistant for final integrations, documentation, and testing, as it is in the AWS Ecosystem and this project is
|
|
29
|
+
Kiro is the required AI coding assistant for final integrations, documentation, and testing, as it is in the AWS Ecosystem and this project is developed to deploy on the AWS platform. Just like test suites, Kiro ensures the proper tests, documentation, and guardrails are in place. Kiro is as important as commit-hooks and tests as it is a tool that ensures quality checks and should not be bypassed.
|
|
30
30
|
|
|
31
31
|
Ensure [AGENTS](./AGENTS.md) and Kiro steering documents are reviewed, understood, and used by both humans and AI.
|
|
32
32
|
|
|
@@ -126,7 +126,7 @@ npm test -- test/cache/
|
|
|
126
126
|
|
|
127
127
|
## Documentation Standards
|
|
128
128
|
|
|
129
|
-
All public APIs must have complete JSDoc documentation. See [Documentation Standards](.kiro/steering/documentation-standards.md) for detailed requirements.
|
|
129
|
+
All public APIs must have complete JSDoc documentation. See [JSDoc Documentation Standards](.kiro/steering/documentation-standards-jsdoc.md) for detailed requirements.
|
|
130
130
|
|
|
131
131
|
**Required JSDoc tags:**
|
|
132
132
|
- Description of what the function/class does
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ The @63klabs/cache-data package provides three main modules:
|
|
|
50
50
|
|
|
51
51
|
### Requirements
|
|
52
52
|
|
|
53
|
-
- Node.js >=
|
|
53
|
+
- Node.js >=22.0.0 runtime on Lambda
|
|
54
54
|
- AWS Services:
|
|
55
55
|
- **AWS Lambda**: For running your serverless functions
|
|
56
56
|
- **Amazon S3**: For storing large cached objects
|
|
@@ -68,7 +68,7 @@ Install the package using npm:
|
|
|
68
68
|
npm install @63klabs/cache-data
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
The simplest way to get started is to use the [63klabs Atlantis Templates and Script
|
|
71
|
+
The simplest way to get started is to use the [63klabs Atlantis Templates and Script Platform](https://github.com/63Klabs/atlantis) to deploy this and other ready-to-run solutions via CI/CD.
|
|
72
72
|
|
|
73
73
|
However, if you want to write your own templates and code, follow the following steps:
|
|
74
74
|
|
|
@@ -102,26 +102,22 @@ It is recommended that you use the quick-start method when implementing for the
|
|
|
102
102
|
### Basic Caching Example
|
|
103
103
|
|
|
104
104
|
```javascript
|
|
105
|
-
const { cache } = require("@63klabs/cache-data");
|
|
105
|
+
const { cache: {CacheableDataAccess, Cache}, endpoint } = require("@63klabs/cache-data");
|
|
106
106
|
|
|
107
107
|
// Initialize cache with your S3 bucket and DynamoDB table
|
|
108
108
|
cache.Cache.init({
|
|
109
|
-
s3Bucket: process.env.CACHE_DATA_S3_BUCKET,
|
|
110
|
-
dynamoDbTable: process.env.CACHE_DATA_DYNAMODB_TABLE,
|
|
111
|
-
securityKey: process.env.CACHE_DATA_SECURITY_KEY
|
|
109
|
+
s3Bucket: process.env.CACHE_DATA_S3_BUCKET, // Cache.init will check this env variable automatically if not provided here
|
|
110
|
+
dynamoDbTable: process.env.CACHE_DATA_DYNAMODB_TABLE, // Cache.init will check this env variable automatically if not provided here
|
|
111
|
+
securityKey: process.env.CACHE_DATA_SECURITY_KEY // don't do this, use SSM Parameter Store - example only
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
//
|
|
115
|
-
const cacheKey = "my-data-key";
|
|
116
|
-
const dataToCache = { message: "Hello, World!", timestamp: Date.now() };
|
|
117
|
-
|
|
118
|
-
await cache.Cache.put(cacheKey, dataToCache, 3600); // Cache for 1 hour
|
|
114
|
+
//
|
|
119
115
|
|
|
120
116
|
// Retrieve cached data
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
const conn = { host: "api.example.com", path: "api/users"};
|
|
118
|
+
const cacheProfile = {/* cache parameters */};
|
|
119
|
+
const cachedData = await CacheableDataAccess.getData(cacheProfile, endpoint.get, conn);
|
|
120
|
+
const data = cachedData.getBody(true);
|
|
125
121
|
```
|
|
126
122
|
|
|
127
123
|
### Making Endpoint Requests
|
|
@@ -131,8 +127,7 @@ const { endpoint } = require("@63klabs/cache-data");
|
|
|
131
127
|
|
|
132
128
|
// Make a simple GET request to an API
|
|
133
129
|
const response = await endpoint.get(
|
|
134
|
-
{ host: "api.example.com", path: "/data" }
|
|
135
|
-
{ parameters: { q: "search-term" } }
|
|
130
|
+
{ host: "api.example.com", path: "/data", parameters: { q: "search-term" } }
|
|
136
131
|
);
|
|
137
132
|
|
|
138
133
|
console.log("API Response:", response.body);
|
|
@@ -142,7 +137,7 @@ console.log("Status Code:", response.statusCode);
|
|
|
142
137
|
### Using APIRequest with Pagination and Retry
|
|
143
138
|
|
|
144
139
|
```javascript
|
|
145
|
-
const { tools } = require("@63klabs/cache-data");
|
|
140
|
+
const { tools: {APIRequest} } = require("@63klabs/cache-data");
|
|
146
141
|
|
|
147
142
|
// Make a request with automatic pagination and retry
|
|
148
143
|
const request = new tools.APIRequest({
|
|
@@ -165,23 +160,15 @@ const response = await request.send();
|
|
|
165
160
|
// Response contains all users from all pages
|
|
166
161
|
const allUsers = JSON.parse(response.body).items;
|
|
167
162
|
console.log(`Retrieved ${allUsers.length} total users`);
|
|
168
|
-
|
|
169
|
-
// Check metadata
|
|
170
|
-
if (response.metadata?.pagination?.occurred) {
|
|
171
|
-
console.log(`Fetched ${response.metadata.pagination.totalPages} pages`);
|
|
172
|
-
}
|
|
173
|
-
if (response.metadata?.retries?.occurred) {
|
|
174
|
-
console.log(`Succeeded after ${response.metadata.retries.attempts} attempts`);
|
|
175
|
-
}
|
|
176
163
|
```
|
|
177
164
|
|
|
178
165
|
### Using Utility Tools
|
|
179
166
|
|
|
180
167
|
```javascript
|
|
181
|
-
const { tools } = require("@63klabs/cache-data");
|
|
168
|
+
const { tools: {DebugAndLog, Timer} } = require("@63klabs/cache-data");
|
|
182
169
|
|
|
183
170
|
// Create a timer to measure performance
|
|
184
|
-
const timer = new
|
|
171
|
+
const timer = new Timer("my-operation");
|
|
185
172
|
timer.start();
|
|
186
173
|
|
|
187
174
|
// Your code here...
|
|
@@ -190,9 +177,8 @@ timer.stop();
|
|
|
190
177
|
console.log(`Operation took ${timer.elapsed()}ms`);
|
|
191
178
|
|
|
192
179
|
// Use the logger
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
logger.error("An error occurred", { details: "error info" });
|
|
180
|
+
DebugAndLog.debug("MyApp");
|
|
181
|
+
DebugAndLog.error("Error in Service", error.msg);
|
|
196
182
|
```
|
|
197
183
|
|
|
198
184
|
## Help
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@63klabs/cache-data",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.9",
|
|
4
4
|
"description": "Cache data from an API endpoint or application process using AWS S3 and DynamoDb",
|
|
5
5
|
"author": "Chad Leigh Kluck (https://chadkluck.me)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"node": ">=20.0.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"aws-xray-sdk-core": "^3.12.0",
|
|
20
19
|
"moment-timezone": "^0.6.0",
|
|
21
20
|
"object-hash": "^3.0.0"
|
|
22
21
|
},
|
|
23
22
|
"devDependencies": {
|
|
23
|
+
"aws-xray-sdk-core": "^3.12.0",
|
|
24
24
|
"@aws-sdk/client-dynamodb": "^3.995.0",
|
|
25
25
|
"@aws-sdk/client-s3": "^3.995.0",
|
|
26
26
|
"@aws-sdk/client-ssm": "^3.995.0",
|
|
@@ -35,10 +35,11 @@
|
|
|
35
35
|
"sinon": "^21.0.1"
|
|
36
36
|
},
|
|
37
37
|
"overrides": {
|
|
38
|
-
"fast-xml-parser": ">=5.3.4",
|
|
39
38
|
"diff": ">=8.0.3",
|
|
39
|
+
"fast-xml-parser": ">=5.3.4",
|
|
40
|
+
"glob": ">=13.0.6",
|
|
40
41
|
"minimatch": ">=10.2.2",
|
|
41
|
-
"
|
|
42
|
+
"serialize-javascript": ">=7.0.3"
|
|
42
43
|
},
|
|
43
44
|
"scripts": {
|
|
44
45
|
"test": "mocha 'test/**/*-tests.mjs' --exclude 'test/migration/property/test-execution-equivalence-property-tests.mjs'",
|
package/src/lib/dao-cache.js
CHANGED
|
@@ -1545,8 +1545,8 @@ class Cache {
|
|
|
1545
1545
|
("CACHE_DATA_USE_TOOLS_HASH" in process.env ? Cache.bool(process.env.CACHE_DATA_USE_TOOLS_HASH_METHOD) : false);
|
|
1546
1546
|
|
|
1547
1547
|
// Initialize in-memory cache feature flag
|
|
1548
|
-
this.#useInMemoryCache = parameters.useInMemoryCache ||
|
|
1549
|
-
(process.env.CACHE_USE_IN_MEMORY
|
|
1548
|
+
this.#useInMemoryCache = Cache.bool(parameters.useInMemoryCache) ||
|
|
1549
|
+
Cache.bool(process.env.CACHE_USE_IN_MEMORY) ||
|
|
1550
1550
|
false;
|
|
1551
1551
|
|
|
1552
1552
|
// Initialize InMemoryCache if enabled
|
|
@@ -1654,34 +1654,51 @@ class Cache {
|
|
|
1654
1654
|
};
|
|
1655
1655
|
|
|
1656
1656
|
/**
|
|
1657
|
-
* Convert a value to boolean with
|
|
1657
|
+
* Convert a value to boolean with strict handling for string values.
|
|
1658
1658
|
*
|
|
1659
1659
|
* JavaScript's Boolean() function treats any non-empty string as true, including
|
|
1660
|
-
* the string "false". This method
|
|
1661
|
-
* (case-insensitive)
|
|
1662
|
-
*
|
|
1660
|
+
* the string "false". This method provides strict boolean conversion where:
|
|
1661
|
+
* - The string "true" (case-insensitive) returns true
|
|
1662
|
+
* - The string "1" returns true
|
|
1663
|
+
* - The number 1 returns true
|
|
1664
|
+
* - The boolean true returns true
|
|
1665
|
+
* - All other values return false (including "false", "0", "no", whitespace, empty strings, null, undefined)
|
|
1663
1666
|
*
|
|
1664
|
-
*
|
|
1667
|
+
* This is useful when dealing with environment variables, JSON data, query parameters,
|
|
1668
|
+
* or configuration strings where only explicit "true" or "1" should enable a feature.
|
|
1665
1669
|
*
|
|
1666
1670
|
* @param {*} value A value to convert to boolean
|
|
1667
|
-
* @returns {boolean}
|
|
1671
|
+
* @returns {boolean} True only if value is explicitly truthy ("true", "1", 1, or true), false otherwise
|
|
1668
1672
|
* @example
|
|
1669
1673
|
* Cache.bool(true); // true
|
|
1670
1674
|
* Cache.bool(false); // false
|
|
1671
1675
|
* Cache.bool("true"); // true
|
|
1672
|
-
* Cache.bool("
|
|
1673
|
-
* Cache.bool("
|
|
1676
|
+
* Cache.bool("TRUE"); // true (case-insensitive)
|
|
1677
|
+
* Cache.bool("1"); // true
|
|
1674
1678
|
* Cache.bool(1); // true
|
|
1679
|
+
* Cache.bool("false"); // false
|
|
1680
|
+
* Cache.bool("0"); // false
|
|
1681
|
+
* Cache.bool("no"); // false
|
|
1682
|
+
* Cache.bool(" "); // false (whitespace)
|
|
1683
|
+
* Cache.bool(" "); // false (whitespace)
|
|
1675
1684
|
* Cache.bool(0); // false
|
|
1676
1685
|
* Cache.bool(null); // false
|
|
1686
|
+
* Cache.bool(undefined); // false
|
|
1677
1687
|
* Cache.bool(""); // false
|
|
1678
1688
|
*/
|
|
1679
1689
|
static bool (value) {
|
|
1680
1690
|
|
|
1681
|
-
|
|
1691
|
+
// >! Handle strings with strict true/false logic
|
|
1692
|
+
// >! Only "true" and "1" are considered truthy strings
|
|
1693
|
+
if ( typeof value === 'string') {
|
|
1694
|
+
value = value.trim().toLowerCase();
|
|
1695
|
+
return value === 'true' || value === '1';
|
|
1696
|
+
}
|
|
1682
1697
|
|
|
1683
|
-
//
|
|
1684
|
-
|
|
1698
|
+
// >! For non-strings, use standard Boolean conversion
|
|
1699
|
+
// >! This handles: true, 1, objects, arrays
|
|
1700
|
+
// >! And returns false for: false, 0, null, undefined, NaN
|
|
1701
|
+
return Boolean(value);
|
|
1685
1702
|
};
|
|
1686
1703
|
|
|
1687
1704
|
/**
|
|
@@ -17,7 +17,17 @@ const isTrue = (value) => {
|
|
|
17
17
|
*/
|
|
18
18
|
const USE_XRAY = isTrue(process.env?.CacheData_AWSXRayOn) || isTrue(process.env?.CACHE_DATA_AWS_X_RAY_ON);
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* X-Ray object if it is enabled
|
|
22
|
+
* @returns {object|null} The AWSXRay object if enabled and initialized, null otherwise
|
|
23
|
+
*/
|
|
20
24
|
let AWSXRay = null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Whether or not X-Ray is initialized
|
|
28
|
+
* @private
|
|
29
|
+
* @returns {object|null} The AWSXRay object if enabled and initialized, null otherwise
|
|
30
|
+
*/
|
|
21
31
|
let xrayInitialized = false;
|
|
22
32
|
|
|
23
33
|
const initializeXRay = () => {
|
|
@@ -278,9 +288,25 @@ class AWS {
|
|
|
278
288
|
}
|
|
279
289
|
}
|
|
280
290
|
)();
|
|
281
|
-
|
|
291
|
+
|
|
282
292
|
/**
|
|
283
|
-
*
|
|
293
|
+
* Provides a DynamoDB client and helper functions.
|
|
294
|
+
*
|
|
295
|
+
* @returns {{
|
|
296
|
+
* client: object,
|
|
297
|
+
* put: {(params:Object) => Promise<any>},
|
|
298
|
+
* get: {(params:Object) => Promise<any>},
|
|
299
|
+
* scan: {(params:Object) => Promise<any>},
|
|
300
|
+
* delete: {(params:Object) => Promise<any>},
|
|
301
|
+
* update: {(params:Object) => Promise<any>},
|
|
302
|
+
* sdk: {
|
|
303
|
+
* DynamoDB: object,
|
|
304
|
+
* DynamoDBClient: object,
|
|
305
|
+
* DynamoDBDocumentClient: object,
|
|
306
|
+
* GetCommand: object,
|
|
307
|
+
* PutCommand: object
|
|
308
|
+
* }
|
|
309
|
+
* }}
|
|
284
310
|
*/
|
|
285
311
|
static get dynamo() {
|
|
286
312
|
return {
|
|
@@ -295,7 +321,18 @@ class AWS {
|
|
|
295
321
|
}
|
|
296
322
|
|
|
297
323
|
/**
|
|
298
|
-
*
|
|
324
|
+
* Provides a S3 client and helper functions.
|
|
325
|
+
*
|
|
326
|
+
* @returns {{
|
|
327
|
+
* client: object,
|
|
328
|
+
* put: {(params:Object) => Promise<any>},
|
|
329
|
+
* get: {(params:Object) => Promise<any>},
|
|
330
|
+
* sdk: {
|
|
331
|
+
* S3: object,
|
|
332
|
+
* GetObjectCommand: object,
|
|
333
|
+
* PutObjectCommand: object
|
|
334
|
+
* }
|
|
335
|
+
* }}
|
|
299
336
|
*/
|
|
300
337
|
static get s3() {
|
|
301
338
|
return {
|
|
@@ -307,7 +344,18 @@ class AWS {
|
|
|
307
344
|
}
|
|
308
345
|
|
|
309
346
|
/**
|
|
310
|
-
*
|
|
347
|
+
* Provides a SSM client and helper functions.
|
|
348
|
+
*
|
|
349
|
+
* @returns {{
|
|
350
|
+
* client: object,
|
|
351
|
+
* getByName: {(query:Object) => Promise<any>},
|
|
352
|
+
* getByPath: {(query:Object) => Promise<any>},
|
|
353
|
+
* sdk: {
|
|
354
|
+
* SSMClient: object,
|
|
355
|
+
* GetParametersByPathCommand: object,
|
|
356
|
+
* GetParametersCommand: object
|
|
357
|
+
* }
|
|
358
|
+
* }}
|
|
311
359
|
*/
|
|
312
360
|
static get ssm() {
|
|
313
361
|
return {
|
|
@@ -327,4 +375,9 @@ class AWS {
|
|
|
327
375
|
|
|
328
376
|
};
|
|
329
377
|
|
|
330
|
-
module.exports = {
|
|
378
|
+
module.exports = {
|
|
379
|
+
AWS,
|
|
380
|
+
Aws: AWS, // alias
|
|
381
|
+
AWSXRay,
|
|
382
|
+
AwsXRay: AWSXRay, // alias
|
|
383
|
+
};
|