@63klabs/cache-data 1.3.7 → 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.
@@ -44,19 +44,31 @@ const { Connections, Connection, ConnectionRequest, ConnectionAuthentication } =
44
44
  */
45
45
 
46
46
  /**
47
- * @typedef ConnectionObject
48
- * @property {object} connection A connection object
49
- * @property {string} connection.method GET or POST
50
- * @property {string} connection.uri the full uri (overrides protocol, host, path, and parameters) ex https://example.com/api/v1/1004/?key=asdf&y=4
51
- * @property {string} connection.protocol https
52
- * @property {string} connection.host host/domain: example.com
53
- * @property {string} connection.path path of the request: /api/v1/1004
54
- * @property {object} connection.parameters parameters for the query string as an object in key/value pairs
55
- * @property {object} connection.headers headers for the request as an object in key/value pairs
56
- * @property {string} connection.body for POST requests, the body
57
- * @property {string} connection.note a note for logging
58
- * @property {object} connection.options https_get options
59
- * @property {number} connection.options.timeout timeout in milliseconds
47
+ * @typedef {Object} ConnectionObject
48
+ * @property {string} method GET or POST
49
+ * @property {string} uri the full uri (overrides protocol, host, path, and parameters) ex https://example.com/api/v1/1004/?key=asdf&y=4
50
+ * @property {string} protocol https
51
+ * @property {string} host host/domain: example.com
52
+ * @property {string} path path of the request: /api/v1/1004
53
+ * @property {object} parameters parameters for the query string as an object in key/value pairs
54
+ * @property {object} headers headers for the request as an object in key/value pairs
55
+ * @property {string} body for POST requests, the body
56
+ * @property {string} note a note for logging
57
+ * @property {object} options https_get options
58
+ * @property {number} options.timeout timeout in milliseconds
59
+ * @property {CacheProfileObject[]} cache
60
+ */
61
+
62
+ /**
63
+ * @typedef {Object} CacheProfileObject
64
+ * @property {string} profile The name of the cache profile
65
+ * @property {boolean} overrideOriginHeaderExpiration If true, the cache expiration will be overridden by the origin header expiration
66
+ * @property {number} defaultExpirationInSeconds The default expiration time in seconds
67
+ * @property {boolean} expirationIsOnInterval If true, the cache expiration will be on an interval
68
+ * @property {array<string>} headersToRetain
69
+ * @property {string} hostId The host ID to use for the cache key
70
+ * @property {string} pathId The path ID to use for the cache key
71
+ * @property {boolean} encrypt If true, the cache data will be encrypted
60
72
  */
61
73
 
62
74
  /* ****************************************************************************
@@ -69,7 +81,7 @@ const { Connections, Connection, ConnectionRequest, ConnectionAuthentication } =
69
81
  *************************************************************************** */
70
82
 
71
83
  /**
72
- * _ConfigSuperClass needs to be extended by your own Config class definition.
84
+ * AppConfig needs to be extended by your own Config class definition.
73
85
  *
74
86
  * This super class holds common variables and methods that can be used by any
75
87
  * application. However, each application requires it's own methods and logic
@@ -80,36 +92,177 @@ const { Connections, Connection, ConnectionRequest, ConnectionAuthentication } =
80
92
  * initialized.
81
93
  *
82
94
  * @example
83
- * class Config extends tools._ConfigSuperClass {
95
+ * class Config extends tools.AppConfig {
84
96
  * // your custom class definition including your implementation of .init()
85
97
  * }
86
98
  *
87
99
  * Config.init();
88
100
  */
89
- class _ConfigSuperClass {
101
+ class AppConfig {
90
102
 
91
103
  static _promise = null;
104
+ static _promises = [];
92
105
  static _connections = null;
93
106
  static _settings = null;
107
+ static _ssmParameters = null;
94
108
 
95
109
  /**
96
- * Get the application settings object
110
+ * Initialize the Config class with asynchronous parallel execution.
97
111
  *
98
- * Returns the settings object that was initialized during Config.init().
99
- * This typically contains application-specific configuration values loaded
100
- * from parameter store, environment variables, or other sources.
112
+ * This method returns immediately (synchronously) while initialization operations
113
+ * execute asynchronously in parallel. Use AppConfig.promise() to wait for all
114
+ * initialization to complete before accessing initialized configuration.
115
+ *
116
+ * @param {object} options Configuration options
117
+ * @param {object} options.settings Application settings retrieved by Config.settings()
118
+ * @param {ConnectionObject[]} options.connections Application connections that can then be retrieved by Config.getConn() or Config.getConnCacheProfile()
119
+ * @param {object} options.validations ClientRequest.init() options
120
+ * @param {object} options.responses Response.init() options
121
+ * @param {object} options.responses.settings
122
+ * @param {number} options.responses.settings.errorExpirationInSeconds
123
+ * @param {number} options.responses.settings.routeExpirationInSeconds
124
+ * @param {number} options.responses.settings.externalRequestHeadroomInMs
125
+ * @param {object} options.responses.jsonResponses
126
+ * @param {object} options.responses.htmlResponses
127
+ * @param {object} options.responses.xmlResponses
128
+ * @param {object} options.responses.rssResponses
129
+ * @param {object} options.responses.textResponses
130
+ * @param {object} options.ssmParameters Parameter Store
131
+ * @param {boolean} [options.debug=false] Enable debug logging
132
+ * @returns {boolean} True if initialization started successfully, false on synchronous error
133
+ * @example
134
+ * // Initialize configuration (returns immediately)
135
+ * const { Config } = require("./config");
136
+ * Config.init({
137
+ * settings: {
138
+ * dataLimit: 1000,
139
+ * cacheTTL: 300
140
+ * },
141
+ * connections: {
142
+ * myConnection: {
143
+ * method: "GET",
144
+ * host: "example.com",
145
+ * path: "/api/v1/data",
146
+ * parameters: {
147
+ * limit: 100
148
+ * }
149
+ * }
150
+ * }
151
+ * });
152
+ *
153
+ * // Wait for all initialization to complete
154
+ * await Config.promise();
155
+ *
156
+ * // Now safe to access initialized configuration
157
+ * const settings = Config.settings();
158
+ * const conn = Config.getConn('myConnection');
159
+ */
160
+ static init(options = {}) {
161
+
162
+ try {
163
+
164
+ const debug = (options?.debug === true);
165
+ if (debug) {
166
+ DebugAndLog.debug("Config Init in debug mode");
167
+ }
168
+
169
+ if (options.settings) {
170
+ const settingsPromise = new Promise((resolve) => {
171
+ try {
172
+ AppConfig._settings = options.settings;
173
+ if (debug) {
174
+ DebugAndLog.debug("Settings initialized", AppConfig._settings);
175
+ }
176
+ resolve(true);
177
+ } catch (error) {
178
+ DebugAndLog.error(`Settings initialization failed: ${error.message}`, error.stack);
179
+ resolve(false);
180
+ }
181
+ });
182
+ AppConfig.add(settingsPromise);
183
+ }
184
+
185
+ if (options.connections) {
186
+ const connectionsPromise = new Promise((resolve) => {
187
+ try {
188
+ AppConfig._connections = new Connections(options.connections);
189
+ if (debug) {
190
+ DebugAndLog.debug("Connections initialized", AppConfig._connections.info());
191
+ }
192
+ resolve(true);
193
+ } catch (error) {
194
+ DebugAndLog.error(`Connections initialization failed: ${error.message}`, error.stack);
195
+ resolve(false);
196
+ }
197
+ });
198
+ AppConfig.add(connectionsPromise);
199
+ }
200
+
201
+ if (options.validations) {
202
+ const validationsPromise = new Promise((resolve) => {
203
+ try {
204
+ ClientRequest.init(options.validations);
205
+ if (debug) {
206
+ DebugAndLog.debug("ClientRequest initialized", ClientRequest.info());
207
+ }
208
+ resolve(true);
209
+ } catch (error) {
210
+ DebugAndLog.error(`ClientRequest initialization failed: ${error.message}`, error.stack);
211
+ resolve(false);
212
+ }
213
+ });
214
+ AppConfig.add(validationsPromise);
215
+ }
216
+
217
+ if (options.responses) {
218
+ const responsesPromise = new Promise((resolve) => {
219
+ try {
220
+ Response.init(options.responses);
221
+ if (debug) {
222
+ DebugAndLog.debug("Response initialized", Response.info());
223
+ }
224
+ resolve(true);
225
+ } catch (error) {
226
+ DebugAndLog.error(`Response initialization failed: ${error.message}`, error.stack);
227
+ resolve(false);
228
+ }
229
+ });
230
+ AppConfig.add(responsesPromise);
231
+ }
232
+
233
+ if (options.ssmParameters) {
234
+ AppConfig._ssmParameters = AppConfig._initParameters(options.ssmParameters);
235
+ AppConfig.add(AppConfig._ssmParameters);
236
+ }
237
+
238
+ return true;
239
+
240
+ } catch (error) {
241
+ DebugAndLog.error(`Could not initialize Config ${error.message}`, error.stack);
242
+ return false;
243
+ }
244
+ }
245
+ ;
246
+
247
+ /**
248
+ * Add a promise to AppConfig. Use AppConfig.promise() to ensure all are resolved.
249
+ * @param {Promise} promise
250
+ */
251
+ static add(promise) {
252
+ AppConfig._promises.push(promise);
253
+ }
254
+
255
+ /**
256
+ * Get the application settings object
101
257
  *
102
258
  * @returns {object|null} Settings object containing application configuration, or null if not initialized
103
259
  * @example
104
- * // Access application settings
105
- * const settings = Config.settings();
106
- * if (settings) {
107
- * console.log('App version:', settings.version);
108
- * console.log('Environment:', settings.environment);
109
- * }
260
+ * // Config extends AppConfig
261
+ * const { Config } = require("./config");
262
+ * const limit = Config.settings().dataLimit;
110
263
  */
111
264
  static settings() {
112
- return _ConfigSuperClass._settings;
265
+ return AppConfig._settings;
113
266
  };
114
267
 
115
268
  /**
@@ -117,7 +270,7 @@ class _ConfigSuperClass {
117
270
  * @returns {Connections}
118
271
  */
119
272
  static connections() {
120
- return _ConfigSuperClass._connections;
273
+ return AppConfig._connections;
121
274
  };
122
275
 
123
276
  /**
@@ -127,10 +280,10 @@ class _ConfigSuperClass {
127
280
  * @returns {Connection|null} Connection instance or null if not found
128
281
  */
129
282
  static getConnection(name) {
130
- if (_ConfigSuperClass._connections === null) {
283
+ if (AppConfig._connections === null) {
131
284
  return null;
132
285
  }
133
- return _ConfigSuperClass._connections.get(name);
286
+ return AppConfig._connections.get(name);
134
287
  }
135
288
 
136
289
  /**
@@ -147,11 +300,11 @@ class _ConfigSuperClass {
147
300
  * )
148
301
  * */
149
302
  static getConn(name) {
150
- if (_ConfigSuperClass._connections === null) {
303
+ if (AppConfig._connections === null) {
151
304
  return null;
152
305
  }
153
306
 
154
- const connection = _ConfigSuperClass._connections.get(name);
307
+ const connection = AppConfig._connections.get(name);
155
308
 
156
309
  if (connection === null) {
157
310
  return null;
@@ -175,37 +328,42 @@ class _ConfigSuperClass {
175
328
  */
176
329
  static getConnCacheProfile(connectionName, cacheProfileName) {
177
330
 
178
- if (_ConfigSuperClass._connections === null) {
331
+ if (AppConfig._connections === null) {
179
332
  return { conn: null, cacheProfile: null };
180
333
  }
181
334
 
182
- const connection = _ConfigSuperClass._connections.get(connectionName);
335
+ const connection = AppConfig._connections.get(connectionName);
183
336
 
184
337
  if (connection === null) {
185
338
  return { conn: null, cacheProfile: null };
186
339
  }
187
340
 
188
- let cacheProfile = null;
341
+ let cacheProfile;
342
+
189
343
  try {
190
344
  const profile = connection.getCacheProfile(cacheProfileName);
191
345
  cacheProfile = (profile === undefined) ? null : profile;
192
- } catch (error) {
346
+ } catch {
193
347
  // getCacheProfile throws if _cacheProfiles is null
194
348
  cacheProfile = null;
195
349
  }
196
350
 
197
351
  return {
198
352
  conn: connection.toObject(),
199
- cacheProfile: cacheProfile
200
- };
353
+ cacheProfile
354
+ };
355
+
201
356
  }
202
357
 
203
358
  /**
204
359
  *
205
- * @returns {Promise} A promise that resolves when the Config class has finished initializing
360
+ * @returns {Promise<array>} A promise that resolves when the Config class has finished initializing
206
361
  */
207
362
  static promise() {
208
- return _ConfigSuperClass._promise;
363
+ if (AppConfig._promise !== null ) { // Backwards compatibility
364
+ AppConfig._promises.push(AppConfig._promise);
365
+ }
366
+ return Promise.all(AppConfig._promises);
209
367
  };
210
368
 
211
369
 
@@ -246,8 +404,6 @@ class _ConfigSuperClass {
246
404
  return { names: names, paths: paths};
247
405
  };
248
406
 
249
- let request = [];
250
-
251
407
  let pNames = paramNames();
252
408
 
253
409
  if (pNames.names.length > 0 || pNames.paths.length > 0 ) {
@@ -352,20 +508,20 @@ class _ConfigSuperClass {
352
508
  * ]
353
509
  * );
354
510
  * @param {array} parameters An array of parameter locations
355
- * @returns {object} Parameters from the parameter store
511
+ * @returns {Promise<object>} Parameters from the parameter store
356
512
  */
357
513
  static async _initParameters(parameters) {
358
514
  // make the call to get the parameters and wait before proceeding to the return
359
515
  return await this._getParameters(parameters);
360
516
  };
361
517
 
362
- static async _initS3File(paths) {
363
- return {};
364
- };
518
+ // static async _initS3File(paths) {
519
+ // return {};
520
+ // };
365
521
 
366
- static async _initDynamoDbRecord(query) {
367
- return {};
368
- };
522
+ // static async _initDynamoDbRecord(query) {
523
+ // return {};
524
+ // };
369
525
 
370
526
  };
371
527
 
@@ -375,8 +531,11 @@ module.exports = {
375
531
  nodeVerMinor,
376
532
  nodeVerMajorMinor,
377
533
  AWS,
534
+ Aws: AWS,
378
535
  AWSXRay,
536
+ AwsXRay: AWSXRay, // Alias
379
537
  APIRequest,
538
+ ApiRequest: APIRequest, // Alias
380
539
  ImmutableObject,
381
540
  Timer,
382
541
  DebugAndLog,
@@ -388,8 +547,10 @@ module.exports = {
388
547
  ClientRequest,
389
548
  ResponseDataModel,
390
549
  Response,
391
- _ConfigSuperClass,
550
+ AppConfig,
551
+ _ConfigSuperClass: AppConfig, // Alias
392
552
  CachedSSMParameter,
553
+ CachedSsmParameter: CachedSSMParameter, // Alias
393
554
  CachedSecret,
394
555
  CachedParameterSecret,
395
556
  CachedParameterSecrets,
@@ -0,0 +1,66 @@
1
+ /**
2
+ * ValidationExecutor - Executes validation functions with appropriate interfaces
3
+ *
4
+ * This class provides static methods for executing validation functions with either
5
+ * single-parameter or multi-parameter interfaces. It handles errors gracefully and
6
+ * logs validation failures.
7
+ *
8
+ * @private
9
+ * @class ValidationExecutor
10
+ */
11
+ class ValidationExecutor {
12
+ /**
13
+ * Execute validation function with appropriate interface.
14
+ *
15
+ * Determines whether to pass a single value or an object based on the number
16
+ * of parameters specified. Handles validation errors gracefully by catching
17
+ * exceptions and logging them.
18
+ *
19
+ * @param {Function} validateFn - Validation function to execute
20
+ * @param {Array<string>} paramNames - Parameter names to validate
21
+ * @param {Object} paramValues - All parameter values available
22
+ * @returns {boolean} True if validation passes, false if fails or throws
23
+ *
24
+ * @example
25
+ * // Single parameter validation
26
+ * const isValid = ValidationExecutor.execute(
27
+ * (value) => value.length > 0,
28
+ * ['id'],
29
+ * { id: '123' }
30
+ * );
31
+ *
32
+ * @example
33
+ * // Multi-parameter validation
34
+ * const isValid = ValidationExecutor.execute(
35
+ * ({page, limit}) => page >= 1 && limit >= 1 && limit <= 100,
36
+ * ['page', 'limit'],
37
+ * { page: 1, limit: 10 }
38
+ * );
39
+ */
40
+ static execute(validateFn, paramNames, paramValues) {
41
+ try {
42
+ if (paramNames.length === 1) {
43
+ // Single parameter: pass value directly
44
+ const value = paramValues[paramNames[0]];
45
+ return validateFn(value);
46
+ } else {
47
+ // Multiple parameters: pass object
48
+ const paramObj = {};
49
+ for (const name of paramNames) {
50
+ paramObj[name] = paramValues[name];
51
+ }
52
+ return validateFn(paramObj);
53
+ }
54
+ } catch (error) {
55
+ // Log error and treat as validation failure
56
+ const tools = require("../tools/index.js");
57
+ tools.DebugAndLog.error(
58
+ `Validation function threw error for parameters [${paramNames.join(", ")}]: ${error?.message || "Unknown error"}`,
59
+ error?.stack
60
+ );
61
+ return false;
62
+ }
63
+ }
64
+ }
65
+
66
+ module.exports = ValidationExecutor;