@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 CHANGED
@@ -8,9 +8,50 @@ 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)
11
+ ## v1.3.10 (2026-03-15)
12
+
13
+ ### Fixes
14
+
15
+ - **Security Fixes** in tests and SSM Parameter Store legacy access [Spec: 1-3-10-security-fixes-for-tests](.kiro/specs/1-3-10-security-fixes-for-tests/)
16
+ - **GitHub Workflow fix** for testing matrix. Node24 was failing while Node 20, 22 were passing [Spec: 1-3-10-github-workflow-test-fix](.kiro/specs/1-3-10-github-workflow-test-fix/)
17
+
18
+ ### Changes
19
+
20
+ - **Complete Mocha to Jest Test Migration** [Spec: 1-3-10-test-migration-phase-6](.kiro/specs/1-3-10-test-migration-phase-6/)
21
+ - Migrated all 38 remaining Mocha test files to Jest, completing the full test suite migration
22
+ - Jest is now the sole test framework for the project
23
+ - All tests use the `.jest.mjs` file extension
24
+ - Updated `npm test` to run Jest directly
25
+ - Updated all module-specific test scripts (`test:cache`, `test:config`, `test:endpoint`) to use Jest
26
+ - Updated CI/CD configuration to run Jest only
27
+ - Updated documentation (README, CONTRIBUTING, AGENTS, steering documents) to reflect Jest-only testing
28
+ - **ApiRequest** and **CachedSsmParameter** renaming to conform to naming conventions:
29
+ - `APIRequest` has been renamed to `ApiRequest`.
30
+ - `APIRequest` is now aliased to `ApiRequest` and will still work.
31
+ - `CachedSSMParameter` has been renamed to `CachedSsmParameter`.
32
+ - `CachedSSMParameter` is now aliased to `CachedSsmParameter` and will still work.
33
+ - While there is no timeframe to deprecate and remove the old naming, it will happen with a future **major** version update.
34
+ - New code should use the new conventions. Old code should be updated.
35
+ - **tools.endpoint.get()** deprecated in favor of **tools.endpoint.send()**
36
+ - `tools.endpoint.send()` removes any confusion about it accepting more than just `GET` requests and that it will send immediately when called.
37
+ - **Optimized Generic Response** for easier maintenance
38
+
39
+ ### Added
40
+
41
+ - **Enhanced Invalid Request Messaging**
42
+ - **New Response Formatting to ApiRequest**
43
+
44
+
45
+ ### Removed
46
+
47
+ - **Mocha, Chai, and Sinon Dependencies** [Spec: 1-3-10-test-migration-phase-6](.kiro/specs/1-3-10-test-migration-phase-6/)
48
+ - Removed `mocha` from devDependencies
49
+ - Removed `chai` from devDependencies
50
+ - Removed `sinon` from devDependencies
51
+ - Removed `chai-http` from devDependencies
52
+ - Removed all legacy Mocha test files (`*-tests.mjs`)
53
+ - Removed `test:all` script (no longer needed with single test framework)
12
54
 
13
- - Unreleased
14
55
 
15
56
  ## v1.3.9 (2026-03-09)
16
57
 
@@ -92,14 +133,14 @@ Report all vulnerabilities under the [Security menu](https://github.com/63Klabs/
92
133
  - Production dependencies remain secure (0 vulnerabilities)
93
134
 
94
135
  ### Added
95
- - **APIRequest Pagination, Retry, and X-Ray Enhancements** [Spec: 1-3-8-api-request-pagination-retries-xray](.kiro/specs/1-3-8-api-request-pagination-retries-xray/) addresses [#171](https://github.com/63Klabs/cache-data/issues/171), [#172](https://github.com/63Klabs/cache-data/issues/172), [#173](https://github.com/63Klabs/cache-data/issues/173)
96
- - **Automatic Pagination**: APIRequest now supports automatic pagination for APIs that return paginated results
136
+ - **ApiRequest Pagination, Retry, and X-Ray Enhancements** [Spec: 1-3-8-api-request-pagination-retries-xray](.kiro/specs/1-3-8-api-request-pagination-retries-xray/) addresses [#171](https://github.com/63Klabs/cache-data/issues/171), [#172](https://github.com/63Klabs/cache-data/issues/172), [#173](https://github.com/63Klabs/cache-data/issues/173)
137
+ - **Automatic Pagination**: ApiRequest now supports automatic pagination for APIs that return paginated results
97
138
  - Configurable pagination labels for different API response structures
98
139
  - Batch processing for concurrent page requests
99
140
  - Support for both offset-based and token-based pagination
100
141
  - Automatic result combination into single response
101
142
  - Pagination metadata in response (total pages, total items, incomplete status)
102
- - **Automatic Retry Logic**: APIRequest now includes built-in retry functionality for transient failures
143
+ - **Automatic Retry Logic**: ApiRequest now includes built-in retry functionality for transient failures
103
144
  - Configurable retry attempts (default: 1 retry after initial attempt)
104
145
  - Automatic retry on network errors, empty responses, parse errors, and 5xx status codes
105
146
  - Optional retry on 4xx status codes (disabled by default)
@@ -275,9 +316,9 @@ While `DebugAndLog` has also been optimized, there is no change to its results.
275
316
 
276
317
  ## 1.1.4 (2025-03-18) Added XRay sub-segment for API requests
277
318
 
278
- - Feature: Added XRay Segment for APIRequest class
319
+ - Feature: Added XRay Segment for ApiRequest class
279
320
 
280
- When using the tools.APIRequest class, each remote request is now annotated and provided meta data.
321
+ When using the tools.ApiRequest class, each remote request is now annotated and provided meta data.
281
322
 
282
323
  ## 1.1.3 (2025-02-17) Additional Options for Sending Parameters via Query String
283
324
 
package/CONTRIBUTING.md CHANGED
@@ -120,10 +120,63 @@ Ensure all tests pass before submitting changes:
120
120
  npm test
121
121
 
122
122
  # Run specific test suites
123
- npm test -- test/documentation/
124
- npm test -- test/cache/
123
+ npm test -- test/documentation
124
+ npm test -- test/cache
125
125
  ```
126
126
 
127
+ ## Testing
128
+
129
+ This project uses Jest as its test framework. All tests use the `.jest.mjs` file extension.
130
+
131
+ ### Test Framework
132
+
133
+ - Test Runner: Jest
134
+ - Assertions: Jest built-in (`expect`)
135
+ - Property Testing: fast-check
136
+ - Mocking: Jest built-in (`jest.spyOn`, `jest.fn`)
137
+ - File Pattern: `*.jest.mjs`
138
+
139
+ ### Running Tests
140
+
141
+ ```bash
142
+ # Run all tests
143
+ npm test
144
+
145
+ # Run specific test suites
146
+ npm test -- test/cache
147
+ npm test -- test/endpoint
148
+ npm test -- test/documentation
149
+ ```
150
+
151
+ ### Writing Tests
152
+
153
+ All tests must use Jest. Example:
154
+
155
+ ```javascript
156
+ import { describe, it, expect, jest, afterEach } from '@jest/globals';
157
+ import { Cache } from '../src/lib/dao-cache.js';
158
+
159
+ describe('Cache', () => {
160
+ afterEach(() => {
161
+ jest.restoreAllMocks();
162
+ });
163
+
164
+ it('should generate consistent hash for same input', () => {
165
+ const conn = { host: 'example.com', path: '/api' };
166
+ const hash1 = Cache.generateIdHash(conn);
167
+ const hash2 = Cache.generateIdHash(conn);
168
+ expect(hash1).toBe(hash2);
169
+ });
170
+ });
171
+ ```
172
+
173
+ ### Test Naming Conventions
174
+
175
+ - Test files: `*-tests.jest.mjs`
176
+ - Property tests: `*-property-tests.jest.mjs`
177
+ - Integration tests: `*-integration-tests.jest.mjs`
178
+ - Unit tests: `*-unit-tests.jest.mjs`
179
+
127
180
  ## Documentation Standards
128
181
 
129
182
  All public APIs must have complete JSDoc documentation. See [JSDoc Documentation Standards](.kiro/steering/documentation-standards-jsdoc.md) for detailed requirements.
@@ -149,7 +202,7 @@ All public APIs must have complete JSDoc documentation. See [JSDoc Documentation
149
202
  * @example
150
203
  * const result = await CacheableDataAccess.getData(
151
204
  * cacheProfile,
152
- * endpoint.get,
205
+ * endpoint.send,
153
206
  * connection
154
207
  * );
155
208
  * console.log(result.data);
package/README.md CHANGED
@@ -116,7 +116,7 @@ cache.Cache.init({
116
116
  // Retrieve cached data
117
117
  const conn = { host: "api.example.com", path: "api/users"};
118
118
  const cacheProfile = {/* cache parameters */};
119
- const cachedData = await CacheableDataAccess.getData(cacheProfile, endpoint.get, conn);
119
+ const cachedData = await CacheableDataAccess.getData(cacheProfile, endpoint.send, conn);
120
120
  const data = cachedData.getBody(true);
121
121
  ```
122
122
 
@@ -126,7 +126,7 @@ const data = cachedData.getBody(true);
126
126
  const { endpoint } = require("@63klabs/cache-data");
127
127
 
128
128
  // Make a simple GET request to an API
129
- const response = await endpoint.get(
129
+ const response = await endpoint.send(
130
130
  { host: "api.example.com", path: "/data", parameters: { q: "search-term" } }
131
131
  );
132
132
 
@@ -134,13 +134,13 @@ console.log("API Response:", response.body);
134
134
  console.log("Status Code:", response.statusCode);
135
135
  ```
136
136
 
137
- ### Using APIRequest with Pagination and Retry
137
+ ### Using ApiRequest with Pagination and Retry
138
138
 
139
139
  ```javascript
140
- const { tools: {APIRequest} } = require("@63klabs/cache-data");
140
+ const { tools: {ApiRequest} } = require("@63klabs/cache-data");
141
141
 
142
142
  // Make a request with automatic pagination and retry
143
- const request = new tools.APIRequest({
143
+ const request = new tools.ApiRequest({
144
144
  host: "api.example.com",
145
145
  path: "/users",
146
146
  parameters: {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@63klabs/cache-data",
3
- "version": "1.3.9",
4
- "description": "Cache data from an API endpoint or application process using AWS S3 and DynamoDb",
5
- "author": "Chad Leigh Kluck (https://chadkluck.me)",
3
+ "version": "1.3.10",
4
+ "description": "A package for AWS Lambda Node.js applications to access and cache data from remote API endpoints (or other sources) utilizing AWS S3 and DynamoDb for the cache storage. Also provides a simple request handling, routing, and response logging framework for running a web service with minimal dependencies.",
5
+ "author": "Chad Kluck (https://chadkluck.me)",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -26,36 +26,24 @@
26
26
  "@aws-sdk/client-ssm": "^3.995.0",
27
27
  "@aws-sdk/lib-dynamodb": "^3.995.0",
28
28
  "@eslint/js": "^10.0.1",
29
- "chai": "^6.2.2",
30
- "chai-http": "^5.1.2",
31
29
  "eslint": "^10.0.1",
32
30
  "fast-check": "^4.5.3",
33
- "jest": "^30.2.0",
34
- "mocha": "^11.7.5",
35
- "sinon": "^21.0.1"
36
- },
31
+ "jest": "^30.2.0" },
37
32
  "overrides": {
38
- "diff": ">=8.0.3",
39
33
  "fast-xml-parser": ">=5.3.4",
40
34
  "glob": ">=13.0.6",
41
- "minimatch": ">=10.2.2",
42
- "serialize-javascript": ">=7.0.3"
35
+ "minimatch": ">=10.2.2"
43
36
  },
44
37
  "scripts": {
45
- "test": "mocha 'test/**/*-tests.mjs' --exclude 'test/migration/property/test-execution-equivalence-property-tests.mjs'",
46
- "test:jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
47
- "test:all": "npm test && npm run test:jest",
48
- "test:migration:validation": "mocha test/migration/property/test-execution-equivalence-property-tests.mjs",
49
- "test:cache": "mocha 'test/cache/**/*-tests.mjs'",
50
- "test:cache:jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/cache",
51
- "test:config": "mocha 'test/config/**/*-tests.mjs'",
52
- "test:endpoint": "mocha 'test/endpoint/**/*-tests.mjs'",
53
- "test:endpoint:jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/endpoint",
54
- "test:tools:jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/tools",
55
- "test:logging": "mocha 'test/logging/**/*-tests.mjs'",
56
- "test:request": "mocha 'test/request/**/*-tests.mjs'",
57
- "test:response": "mocha 'test/response/**/*-tests.mjs'",
58
- "test:utils": "mocha 'test/utils/**/*-tests.mjs'",
38
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
39
+ "test:cache": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/cache",
40
+ "test:config": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/config",
41
+ "test:endpoint": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/endpoint",
42
+ "test:tools": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/tools",
43
+ "test:logging": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/logging",
44
+ "test:request": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/request",
45
+ "test:response": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/response",
46
+ "test:utils": "node --experimental-vm-modules node_modules/jest/bin/jest.js test/utils",
59
47
  "lint": "eslint .",
60
48
  "lint:fix": "eslint . --fix",
61
49
  "lint:ci": "eslint . --max-warnings 0"
@@ -38,9 +38,10 @@ const moment = require('moment-timezone');
38
38
  * and retrieval operations - cache expiration logic and data management are
39
39
  * handled by the CacheData class.
40
40
  *
41
- * Use this class when you need direct access to S3 cache storage operations.
42
- * For most use cases, use the Cache or CacheableDataAccess classes instead.
41
+ * Used by Cache object to write and retrieve data that is larger than what
42
+ * we want to store in DynamoDB
43
43
  *
44
+ * @private
44
45
  * @example
45
46
  * // Initialize S3Cache with bucket name
46
47
  * S3Cache.init('my-cache-bucket');
@@ -57,8 +58,13 @@ class S3Cache {
57
58
  static #bucket = null;
58
59
  static #objPath = "cache/";
59
60
 
60
- constructor () {
61
- };
61
+ /**
62
+ * Create a new S3Cache instance.
63
+ * Private constructor - instances should be created through static methods.
64
+ *
65
+ * @private
66
+ */
67
+ constructor () {};
62
68
 
63
69
  /**
64
70
  * Get the S3 bucket name configured for cache storage.
@@ -106,7 +112,6 @@ class S3Cache {
106
112
  * process.env.CACHE_DATA_S3_BUCKET = 'my-cache-bucket';
107
113
  * S3Cache.init();
108
114
  */
109
-
110
115
  static init(bucket = null) {
111
116
  if ( S3Cache.getBucket() === null ) {
112
117
  bucket = (bucket === null) ? process.env?.CACHE_DATA_S3_BUCKET || null : bucket;
@@ -272,14 +277,14 @@ class S3Cache {
272
277
  };
273
278
 
274
279
  /**
275
- * Basic DynamoDb read/write for cache data. Provides low-level storage operations
280
+ * Basic DynamoDB read/write for cache data. Provides low-level storage operations
276
281
  * for cached data in Amazon DynamoDB. This class handles only the storage format
277
282
  * and retrieval operations - cache expiration logic and data management are
278
283
  * handled by the CacheData class.
279
284
  *
280
- * Use this class when you need direct access to DynamoDB cache storage operations.
281
- * For most use cases, use the Cache or CacheableDataAccess classes instead.
285
+ * Used by Cache object to write and retrieve data in DynamoDB
282
286
  *
287
+ * @private
283
288
  * @example
284
289
  * // Initialize DynamoDbCache with table name
285
290
  * DynamoDbCache.init('my-cache-table');
@@ -455,8 +460,8 @@ class DynamoDbCache {
455
460
  * coordinates storage between DynamoDB (for small items) and S3 (for large items).
456
461
  *
457
462
  * This class is used internally by the publicly exposed Cache class and should
458
- * not be used directly in most cases. Use the Cache or CacheableDataAccess
459
- * classes instead for application-level caching.
463
+ * not be used directly. Use the CacheableDataAccess to access data for
464
+ * application-level caching.
460
465
  *
461
466
  * Key responsibilities:
462
467
  * - Expiration time calculations and interval-based caching
@@ -464,6 +469,7 @@ class DynamoDbCache {
464
469
  * - Automatic routing between DynamoDB and S3 based on size
465
470
  * - ETag and Last-Modified header generation
466
471
  *
472
+ * @private
467
473
  * @example
468
474
  * // Initialize CacheData (typically done through Cache.init())
469
475
  * CacheData.init({
@@ -508,7 +514,7 @@ class CacheData {
508
514
  * @param {string} [parameters.dynamoDbTable] DynamoDB table name (or use CACHE_DATA_DYNAMO_DB_TABLE env var)
509
515
  * @param {string} [parameters.s3Bucket] S3 bucket name (or use CACHE_DATA_S3_BUCKET env var)
510
516
  * @param {string} [parameters.secureDataAlgorithm='aes-256-cbc'] Encryption algorithm (or use CACHE_DATA_SECURE_DATA_ALGORITHM env var)
511
- * @param {string|Buffer|tools.Secret|tools.CachedSSMParameter|tools.CachedSecret} parameters.secureDataKey Encryption key (required, no env var for security)
517
+ * @param {string|Buffer|tools.Secret|tools.CachedSsmParameter|tools.CachedSecret} parameters.secureDataKey Encryption key (required, no env var for security)
512
518
  * @param {number} [parameters.DynamoDbMaxCacheSize_kb=10] Max size in KB for DynamoDB storage (or use CACHE_DATA_DYNAMO_DB_MAX_CACHE_SIZE_KB env var)
513
519
  * @param {number} [parameters.purgeExpiredCacheEntriesAfterXHours=24] Hours after expiration to purge entries (or use CACHE_DATA_PURGE_EXPIRED_CACHE_ENTRIES_AFTER_X_HRS env var)
514
520
  * @param {string} [parameters.timeZoneForInterval='Etc/UTC'] Timezone for interval calculations (or use CACHE_DATA_TIME_ZONE_FOR_INTERVAL env var)
@@ -1373,26 +1379,18 @@ class CacheData {
1373
1379
  };
1374
1380
 
1375
1381
  /**
1376
- * The Cache object handles the settings for the cache system
1382
+ * The Cache object handles the settings for the cache system and is only
1383
+ * accessed by the application during init.
1377
1384
  *
1378
- * Before using it must be initialized.
1385
+ * Reading of the cache is done through CacheableDataAccess.getData()
1386
+ *
1387
+ * Before using the Cache, it must be initialized.
1379
1388
  *
1380
1389
  * Many settings can be set through Environment variables or by
1381
1390
  * passing parameters to Cache.init():
1382
1391
  *
1383
1392
  * Cache.init({parameters});
1384
1393
  *
1385
- * Then you can then make a request, sending it through CacheableDataAccess:
1386
- *
1387
- * const { cache } = require("@63klabs/cache-data");
1388
- *
1389
- * const cacheObj = await cache.CacheableDataAccess.getData(
1390
- * cacheCfg,
1391
- * yourFetchFunction,
1392
- * conn,
1393
- * daoQuery
1394
- * );
1395
- *
1396
1394
  * @example
1397
1395
  * // Initialize the cache system
1398
1396
  * Cache.init({
@@ -1401,13 +1399,6 @@ class CacheData {
1401
1399
  * idHashAlgorithm: 'sha256'
1402
1400
  * });
1403
1401
  *
1404
- * // Create a cache instance with connection and profile
1405
- * const connection = { host: 'api.example.com', path: '/data' };
1406
- * const cacheProfile = {
1407
- * defaultExpirationInSeconds: 300,
1408
- * encrypt: true
1409
- * };
1410
- * const cacheInstance = new Cache(connection, cacheProfile);
1411
1402
  */
1412
1403
  class Cache {
1413
1404
 
@@ -1526,7 +1517,7 @@ class Cache {
1526
1517
  * @param {string} parameters.dynamoDbTable Can also be set with environment variable CACHE_DATA_DYNAMO_DB_TABLE
1527
1518
  * @param {string} parameters.s3Bucket Can also be set with environment variable CACHE_DATA_S3_BUCKET
1528
1519
  * @param {string} parameters.secureDataAlgorithm Can also be set with environment variable CACHE_DATA_SECURE_DATA_ALGORITHM
1529
- * @param {string|Buffer|tools.Secret|tools.CachedSSMParameter|tools.CachedSecret} parameters.secureDataKey Must be passed, will not accept an environment variable for security reasons.
1520
+ * @param {string|Buffer|tools.Secret|tools.CachedSsmParameter|tools.CachedSecret} parameters.secureDataKey Must be passed, will not accept an environment variable for security reasons.
1530
1521
  * @param {number} parameters.DynamoDbMaxCacheSize_kb Can also be set with environment variable CACHE_DATA_DYNAMO_DB_MAX_CACHE_SIZE_KB
1531
1522
  * @param {number} parameters.purgeExpiredCacheEntriesAfterXHours Can also be set with environment variable CACHE_DATA_PURGE_EXPIRED_CACHE_ENTRIES_AFTER_X_HRS
1532
1523
  * @param {string} parameters.timeZoneForInterval Can also be set with environment variable CACHE_DATA_TIME_ZONE_FOR_INTERVAL
@@ -3012,7 +3003,7 @@ class Cache {
3012
3003
  /**
3013
3004
  * The CacheableDataAccess object provides an interface to
3014
3005
  * the cache. It is responsible for reading from and writing to cache.
3015
- * All requests to data go through the cache
3006
+ * All requests to data go through CacheableDataAccess.getData
3016
3007
  *
3017
3008
  * Before using CacheableDataAccess, the Cache must be initialized.
3018
3009
  *
@@ -3099,7 +3090,7 @@ class CacheableDataAccess {
3099
3090
  *
3100
3091
  * const cache = await CacheableDataAccess.getData(
3101
3092
  * cachePolicy,
3102
- * endpoint.get,
3093
+ * endpoint.send,
3103
3094
  * connection,
3104
3095
  * null,
3105
3096
  * {path: 'users', id: '123'}