@63klabs/cache-data 1.3.4 → 1.3.6

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.
@@ -8,7 +8,26 @@ const _getNodeEnv = function() {
8
8
  "use strict"
9
9
 
10
10
  /**
11
- * A simple Debug and Logging class.
11
+ * A comprehensive debug and logging class for managing application logging with environment-aware log levels.
12
+ * Provides multiple logging levels (ERROR, WARN, INFO, MSG, DIAG, DEBUG) and automatic environment detection.
13
+ * Supports both production and development environments with appropriate log level restrictions.
14
+ *
15
+ * @class DebugAndLog
16
+ * @example
17
+ * // Basic logging
18
+ * await DebugAndLog.info('Processing request');
19
+ * await DebugAndLog.error('Failed to connect', { error: err });
20
+ *
21
+ * @example
22
+ * // Check environment
23
+ * if (DebugAndLog.isDevelopment()) {
24
+ * await DebugAndLog.debug('Detailed debug info', { data });
25
+ * }
26
+ *
27
+ * @example
28
+ * // Configure via environment variables
29
+ * // Set CACHE_DATA_LOG_LEVEL=5 for DEBUG level
30
+ * // Set CACHE_DATA_ENV=DEV for development environment
12
31
  */
13
32
  class DebugAndLog {
14
33
 
@@ -47,14 +66,32 @@ class DebugAndLog {
47
66
 
48
67
  static PROD_DEFAULT_LEVEL_NUM = 2;
49
68
 
69
+ /**
70
+ * Creates a new DebugAndLog instance.
71
+ * Note: This class is typically used via static methods and does not require instantiation.
72
+ *
73
+ * @example
74
+ * // Use static methods directly (recommended)
75
+ * await DebugAndLog.info('Application started');
76
+ */
50
77
  constructor() {
51
78
  };
52
79
 
53
80
  /**
54
- * Set the log level.
55
- * Deprecated. Set Lambda Environment variable CACHE_DATA_LOG_LEVEL, LOG_LEVEL, or AWS_LAMBDA_LOG_LEVEL instead.
56
- * @param {number} logLevel 0 - 5
57
- * @param {*} expiration Deprecated - no effect
81
+ * Sets the log level (DEPRECATED).
82
+ * This method is deprecated. Use environment variables instead:
83
+ * - CACHE_DATA_LOG_LEVEL
84
+ * - LOG_LEVEL
85
+ * - AWS_LAMBDA_LOG_LEVEL
86
+ *
87
+ * @deprecated Use environment variables CACHE_DATA_LOG_LEVEL, LOG_LEVEL, or AWS_LAMBDA_LOG_LEVEL instead
88
+ * @param {number} [logLevel=-1] - Log level from 0-5 (0=ERROR, 1=WARN, 2=INFO, 3=MSG, 4=DIAG, 5=DEBUG)
89
+ * @param {*} [expiration=-1] - Deprecated parameter with no effect
90
+ * @returns {number} The set log level
91
+ * @example
92
+ * // Don't use this - it's deprecated
93
+ * // Instead, set environment variable:
94
+ * // process.env.CACHE_DATA_LOG_LEVEL = '5';
58
95
  */
59
96
  static setLogLevel(logLevel = -1, expiration = -1) {
60
97
  DebugAndLog.warn(`DebugAndLog.setLogLevel(${logLevel}, ${expiration}) is deprecated. Use CACHE_DATA_LOG_LEVEL, LOG_LEVEL, or AWS_LAMBDA_LOG_LEVEL environment variable instead.`);
@@ -73,8 +110,13 @@ class DebugAndLog {
73
110
  };
74
111
 
75
112
  /**
113
+ * Gets the current log level.
114
+ * If not explicitly set, returns the default log level based on environment variables.
76
115
  *
77
- * @returns {number} The current log level
116
+ * @returns {number} The current log level (0-5): 0=ERROR, 1=WARN, 2=INFO, 3=MSG, 4=DIAG, 5=DEBUG
117
+ * @example
118
+ * const level = DebugAndLog.getLogLevel();
119
+ * console.log(`Current log level: ${level}`);
78
120
  */
79
121
  static getLogLevel() {
80
122
 
@@ -87,19 +129,30 @@ class DebugAndLog {
87
129
  }
88
130
 
89
131
  /**
90
- * Alias for getEnvType()
132
+ * Gets the application environment type (alias for getEnvType()).
133
+ *
134
+ * @returns {string} Environment type: 'PROD', 'TEST', or 'DEV'
135
+ * @example
136
+ * const env = DebugAndLog.getEnv();
137
+ * console.log(`Running in ${env} environment`);
91
138
  */
92
139
  static getEnv() {
93
140
  return DebugAndLog.getEnvType();
94
141
  };
95
142
 
96
143
  /**
97
- * Check process.env for an environment variable named
98
- * env, deployEnvironment, environment, or stage. If they
99
- * are not set it will return DebugAndLog.PROD which
100
- * is considered safe (most restrictive)
101
- * Note: This is the application environment, not the NODE_ENV
102
- * @returns {string} PROD|TEST|DEV - The current environment.
144
+ * Gets the environment type from environment variables.
145
+ * Checks process.env for environment variables in priority order from ALLOWED_ENV_TYPE_VAR_NAMES.
146
+ * Returns 'PROD' (most restrictive) if no valid environment variable is found.
147
+ * Note: This is the application environment, not NODE_ENV.
148
+ *
149
+ * @returns {string} Environment type: 'PROD', 'TEST', or 'DEV'
150
+ * @example
151
+ * // Set environment via CACHE_DATA_ENV=DEV
152
+ * const envType = DebugAndLog.getEnvType();
153
+ * if (envType === 'DEV') {
154
+ * // Development-specific logic
155
+ * }
103
156
  */
104
157
  static getEnvType() {
105
158
  // We can switch if NODE_ENV is set to "development"
@@ -113,8 +166,12 @@ class DebugAndLog {
113
166
  return this.#environment;
114
167
  }
115
168
  /**
169
+ * Gets the environment type from the first matching environment variable.
170
+ * Searches through ALLOWED_ENV_TYPE_VAR_NAMES in priority order.
116
171
  *
117
- * @returns {string} PROD|TEST|DEV|NONE based upon first environment variable from DebugAndLog.ALLOWED_ENV_TYPE_VAR_NAMES found
172
+ * @returns {string} Environment type: 'PROD', 'TEST', 'DEV', or 'NONE' if not found
173
+ * @example
174
+ * const envType = DebugAndLog.getEnvTypeFromEnvVar();
118
175
  */
119
176
  static getEnvTypeFromEnvVar() {
120
177
  let environmentType = "none";
@@ -132,23 +189,41 @@ class DebugAndLog {
132
189
  }
133
190
 
134
191
  /**
135
- * Is Environment Variable NODE_ENV set to "development"?
192
+ * Checks if the NODE_ENV environment variable is set to "development".
193
+ *
194
+ * @returns {boolean} True if NODE_ENV is "development", false otherwise
195
+ * @example
196
+ * if (DebugAndLog.nodeEnvIsDevelopment()) {
197
+ * console.log('Running in development mode');
198
+ * }
136
199
  */
137
200
  static nodeEnvIsDevelopment() {
138
201
  return DebugAndLog.getNodeEnv() === "development";
139
202
  }
140
203
 
141
204
  /**
142
- * Is Environment Variable NODE_ENV set to "production" or "" or undefined?
205
+ * Checks if the NODE_ENV environment variable is set to "production" or is empty/undefined.
206
+ *
207
+ * @returns {boolean} True if NODE_ENV is "production" or not set, false if "development"
208
+ * @example
209
+ * if (DebugAndLog.nodeEnvIsProduction()) {
210
+ * // Production-specific logic
211
+ * }
143
212
  */
144
213
  static nodeEnvIsProduction() {
145
214
  return !this.nodeEnvIsDevelopment();
146
215
  }
147
216
 
148
217
  /**
149
- * Get the current NODE_ENV (returns "production" if not set or if NODE_ENV is set to anything other than "development")
150
- * Calls DebugAndLog.nodeEnvHasChanged() to log a warning if the value has changed since initialization. Should only change during testing.
151
- * @returns {string} development|production
218
+ * Gets the current NODE_ENV value.
219
+ * Returns "development" if NODE_ENV is set to "development", otherwise returns "production".
220
+ * Calls nodeEnvHasChanged() to log a warning if the value has changed since initialization.
221
+ * NODE_ENV should only change during testing.
222
+ *
223
+ * @returns {string} "development" or "production"
224
+ * @example
225
+ * const nodeEnv = DebugAndLog.getNodeEnv();
226
+ * console.log(`NODE_ENV: ${nodeEnv}`);
152
227
  */
153
228
  static getNodeEnv() {
154
229
  DebugAndLog.nodeEnvHasChanged();
@@ -156,10 +231,15 @@ class DebugAndLog {
156
231
  }
157
232
 
158
233
  /**
159
- * Checks to see if the current NODE_ENV environment variable has changed since DebugAndLog was initialized.
160
- * The only time this should happen is while running tests. This should never happen in a production application.
161
- * If these warnings are triggered as you application is running, something is modifying process.env.NODE_ENV during execution.
162
- * @returns {boolean}
234
+ * Checks if the NODE_ENV environment variable has changed since DebugAndLog was initialized.
235
+ * This should only happen during testing. In production applications, NODE_ENV should never change during execution.
236
+ * Logs a warning if NODE_ENV has changed (first occurrence and every 100th occurrence).
237
+ *
238
+ * @returns {boolean} True if NODE_ENV has changed, false otherwise
239
+ * @example
240
+ * if (DebugAndLog.nodeEnvHasChanged()) {
241
+ * console.warn('NODE_ENV changed during execution');
242
+ * }
163
243
  */
164
244
  static nodeEnvHasChanged() {
165
245
  const hasChanged = _getNodeEnv() !== this.#initialNodeEnv;
@@ -177,8 +257,14 @@ class DebugAndLog {
177
257
  }
178
258
 
179
259
  /**
260
+ * Gets the default log level based on environment variables.
261
+ * Checks ALLOWED_LOG_VAR_NAMES in priority order for log level configuration.
262
+ * In production, log level is capped at PROD_DEFAULT_LEVEL_NUM (2).
180
263
  *
181
- * @returns {number} log level
264
+ * @returns {number} Default log level (0-5)
265
+ * @example
266
+ * // Set via CACHE_DATA_LOG_LEVEL=5 or LOG_LEVEL=DEBUG
267
+ * const defaultLevel = DebugAndLog.getDefaultLogLevel();
182
268
  */
183
269
  static getDefaultLogLevel() {
184
270
  let possibleVars = DebugAndLog.ALLOWED_LOG_VAR_NAMES; // in priority order and we want to evaluate AWS_LAMBDA_LOG_LEVEL as upper
@@ -242,43 +328,73 @@ class DebugAndLog {
242
328
  };
243
329
 
244
330
  /**
331
+ * Checks if the application is NOT running in production environment.
245
332
  *
246
- * @returns {boolean}
333
+ * @returns {boolean} True if not in production, false if in production
334
+ * @example
335
+ * if (DebugAndLog.isNotProduction()) {
336
+ * await DebugAndLog.debug('Debug info only in non-prod');
337
+ * }
247
338
  */
248
339
  static isNotProduction() {
249
340
  return ( !DebugAndLog.isProduction() );
250
341
  };
251
342
 
252
343
  /**
344
+ * Checks if the application is running in production environment.
253
345
  *
254
- * @returns {boolean}
346
+ * @returns {boolean} True if in production, false otherwise
347
+ * @example
348
+ * if (DebugAndLog.isProduction()) {
349
+ * // Restrict logging in production
350
+ * }
255
351
  */
256
352
  static isProduction() {
257
353
  return ( DebugAndLog.getEnv() === DebugAndLog.PROD );
258
354
  };
259
355
 
260
356
  /**
357
+ * Checks if the application is running in development environment.
261
358
  *
262
- * @returns {boolean}
359
+ * @returns {boolean} True if in development, false otherwise
360
+ * @example
361
+ * if (DebugAndLog.isDevelopment()) {
362
+ * await DebugAndLog.debug('Development debug info', { data });
363
+ * }
263
364
  */
264
365
  static isDevelopment() {
265
366
  return ( DebugAndLog.getEnv() === DebugAndLog.DEV );
266
367
  };
267
368
 
268
369
  /**
370
+ * Checks if the application is running in test environment.
269
371
  *
270
- * @returns {boolean}
372
+ * @returns {boolean} True if in test environment, false otherwise
373
+ * @example
374
+ * if (DebugAndLog.isTest()) {
375
+ * // Test-specific logic
376
+ * }
271
377
  */
272
378
  static isTest() {
273
379
  return ( DebugAndLog.getEnv() === DebugAndLog.TEST );
274
380
  };
275
381
 
276
382
  /**
277
- * Write a log entry.
278
- * The format used will be "[TAG] message"
279
- * @param {string} tag This will appear first in the log in all caps between square brackets ex: [TAG]
280
- * @param {string} message The message to be displayed. May also be a delimited log string
281
- * @param {object|null} obj An object to include in the log entry
383
+ * Writes a log entry with the specified tag, message, and optional object.
384
+ * The format used will be "[TAG] message" or "[TAG] message | object".
385
+ * Log level determines whether the entry is actually written to console.
386
+ *
387
+ * @param {string} tag - Tag that appears first in the log in all caps between square brackets (e.g., [ERROR])
388
+ * @param {string} message - The message to be displayed
389
+ * @param {Object|null} [obj=null] - Optional object to include in the log entry
390
+ * @returns {Promise<boolean>} True when log is written
391
+ * @example
392
+ * await DebugAndLog.writeLog('INFO', 'User logged in', { userId: 123 });
393
+ * // Output: [INFO] User logged in | { userId: 123 }
394
+ *
395
+ * @example
396
+ * await DebugAndLog.writeLog('ERROR', 'Database connection failed');
397
+ * // Output: [ERROR] Database connection failed
282
398
  */
283
399
  static async writeLog(tag, message, obj = null) {
284
400
 
@@ -372,96 +488,149 @@ class DebugAndLog {
372
488
  };
373
489
 
374
490
  /**
375
- * Level 5 - Verbose Values and Calculations and Stack Traces
376
- * @param {string} message
377
- * @param {object} obj
491
+ * Logs a debug message at level 5 (DEBUG).
492
+ * Used for verbose values, calculations, and stack traces.
493
+ * Only logged when log level is 5 or higher.
494
+ *
495
+ * @param {string} message - The debug message
496
+ * @param {Object} [obj=null] - Optional object with additional debug information
497
+ * @returns {Promise<boolean>} True when log is written
498
+ * @example
499
+ * await DebugAndLog.debug('Variable state', { x: 10, y: 20, result: 30 });
500
+ *
501
+ * @example
502
+ * await DebugAndLog.debug('Stack trace', { stack: new Error().stack });
378
503
  */
379
504
  static async debug(message, obj = null) {
380
505
  return DebugAndLog.writeLog(DebugAndLog.DEBUG, message, obj);
381
506
  };
382
507
 
383
508
  /**
384
- * Level 3 - Verbose timing and counts
385
- * @param {string} message
386
- * @param {object} obj
509
+ * Logs a diagnostic message at level 4 (DIAG).
510
+ * Used for verbose timing and counts.
511
+ * Only logged when log level is 4 or higher.
512
+ *
513
+ * @param {string} message - The diagnostic message
514
+ * @param {Object} [obj=null] - Optional object with diagnostic data
515
+ * @returns {Promise<boolean>} True when log is written
516
+ * @example
517
+ * await DebugAndLog.diag('Query execution time: 45ms', { queryTime: 45, rowCount: 100 });
387
518
  */
388
519
  static async diag(message, obj = null) {
389
520
  return DebugAndLog.writeLog(DebugAndLog.DIAG, message, obj);
390
521
  };
391
522
 
392
523
  /**
393
- * Level 2 - Short messages and status
394
- * @param {string} message
395
- * @param {object} obj
524
+ * Logs a message at level 3 (MSG).
525
+ * Used for short messages and status updates.
526
+ * Only logged when log level is 3 or higher.
527
+ *
528
+ * @param {string} message - The message
529
+ * @param {Object} [obj=null] - Optional object with additional information
530
+ * @returns {Promise<boolean>} True when log is written
531
+ * @example
532
+ * await DebugAndLog.msg('Processing batch 5 of 10');
396
533
  */
397
534
  static async msg(message, obj = null) {
398
535
  return DebugAndLog.writeLog(DebugAndLog.MSG, message, obj);
399
536
  };
400
537
 
401
538
  /**
402
- * Level 2 - Short messages and status
403
- * (same as DebugAndLog.msg() )
404
- * @param {string} message
405
- * @param {object} obj
539
+ * Logs a message at level 3 (MSG).
540
+ * Alias for msg(). Used for short messages and status updates.
541
+ *
542
+ * @param {string} message - The message
543
+ * @param {Object} [obj=null] - Optional object with additional information
544
+ * @returns {Promise<boolean>} True when log is written
545
+ * @example
546
+ * await DebugAndLog.message('Request processed successfully');
406
547
  */
407
548
  static async message(message, obj = null) {
408
549
  return DebugAndLog.msg(message, obj);
409
550
  };
410
551
 
411
552
  /**
412
- * Level 1 - Short messages and status
413
- * @param {string} message
414
- * @param {object} obj
553
+ * Logs an informational message at level 2 (INFO).
554
+ * Used for short messages and status updates.
555
+ * Only logged when log level is 2 or higher.
556
+ *
557
+ * @param {string} message - The informational message
558
+ * @param {Object} [obj=null] - Optional object with additional information
559
+ * @returns {Promise<boolean>} True when log is written
560
+ * @example
561
+ * await DebugAndLog.info('User authentication successful', { userId: 'user123' });
415
562
  */
416
563
  static async info(message, obj = null) {
417
564
  return DebugAndLog.writeLog(DebugAndLog.INFO, message, obj);
418
565
  };
419
566
 
420
567
  /**
421
- * Level 0 - Production worthy log entries that are not errors or warnings
422
- * These should be formatted in a consistent manner and typically only
423
- * one entry produced per invocation. (Usually produced at the end of a
424
- * script's execution)
425
- * @param {string} message The message, either a text string or fields separated by | or another character you can use to parse your logs
426
- * @param {string} tag Optional. The tag that appears at the start of the log. Default is LOG. In logs it will appear at the start within square brackets '[LOG] message' You can use this to filter when parsing log reports
427
- * @param {object} obj
568
+ * Logs a production-worthy log entry at level 0 (LOG).
569
+ * These should be formatted consistently and typically only one entry per invocation.
570
+ * Usually produced at the end of a script's execution.
571
+ * Always logged regardless of log level.
572
+ *
573
+ * @param {string} message - The message, either text or fields separated by | or another delimiter for log parsing
574
+ * @param {string} [tag='LOG'] - Optional tag that appears at the start within square brackets (e.g., [LOG])
575
+ * @param {Object} [obj=null] - Optional object with additional data
576
+ * @returns {Promise<boolean>} True when log is written
577
+ * @example
578
+ * await DebugAndLog.log('Request completed | duration: 150ms | status: 200');
579
+ *
580
+ * @example
581
+ * await DebugAndLog.log('Batch processed', 'BATCH', { count: 100, errors: 0 });
428
582
  */
429
583
  static async log(message, tag = DebugAndLog.LOG, obj = null) {
430
584
  return DebugAndLog.writeLog(tag, message, obj);
431
585
  };
432
586
 
433
587
  /**
434
- * Level 0 - Warnings
435
- * Errors are handled and execution continues.
436
- * ClientRequest validation should be done first, and if we received an invalid
437
- * request, then a warning, not an error, should be logged even though an
438
- * error is returned to the client (error is on client side, not here,
439
- * but we want to keep track of client errors).
440
- * Requests should be validated first before all other processing.
441
- * @param {string} message
442
- * @param {object} obj
588
+ * Logs a warning message at level 1 (WARN).
589
+ * Used when errors are handled and execution continues.
590
+ * For client validation errors, use warn() rather than error() since the error is on the client side.
591
+ * Always logged regardless of log level (level 0).
592
+ *
593
+ * @param {string} message - The warning message
594
+ * @param {Object} [obj=null] - Optional object with warning details
595
+ * @returns {Promise<void>}
596
+ * @example
597
+ * await DebugAndLog.warn('Invalid request parameter', { param: 'userId', value: null });
598
+ *
599
+ * @example
600
+ * await DebugAndLog.warn('Deprecated API usage detected');
443
601
  */
444
602
  static async warn(message, obj = null) {
445
603
  DebugAndLog.writeLog(DebugAndLog.WARN, message, obj);
446
604
  };
447
605
 
448
606
  /**
449
- * Level 0 - Warnings
450
- * (same as DebugAndLog.warn() )
451
- * @param {string} message
452
- * @param {object} obj
607
+ * Logs a warning message at level 1 (WARN).
608
+ * Alias for warn(). Used when errors are handled and execution continues.
609
+ *
610
+ * @param {string} message - The warning message
611
+ * @param {Object} [obj=null] - Optional object with warning details
612
+ * @returns {Promise<void>}
613
+ * @example
614
+ * await DebugAndLog.warning('Cache miss, fetching from database');
453
615
  */
454
616
  static async warning(message, obj = null) {
455
617
  DebugAndLog.warn(message, obj);
456
618
  };
457
619
 
458
620
  /**
459
- * Level 0 - Errors
460
- * Errors cannot be handled in a way that will allow continued execution.
461
- * An error will be passed back to the client. If a client sent a bad
462
- * request, send a warning instead.
463
- * @param {string} message
464
- * @param {object} obj
621
+ * Logs an error message at level 0 (ERROR).
622
+ * Used when errors cannot be handled and execution cannot continue normally.
623
+ * An error will be passed back to the client. For client-side errors (bad requests), use warn() instead.
624
+ * Always logged regardless of log level.
625
+ *
626
+ * @param {string} message - The error message
627
+ * @param {Object} [obj=null] - Optional object with error details
628
+ * @returns {Promise<void>}
629
+ * @example
630
+ * await DebugAndLog.error('Database connection failed', { error: err.message, code: err.code });
631
+ *
632
+ * @example
633
+ * await DebugAndLog.error('Critical system failure');
465
634
  */
466
635
  static async error(message, obj = null) {
467
636
  DebugAndLog.writeLog(DebugAndLog.ERROR, message, obj);
@@ -1,7 +1,47 @@
1
+ const { safeClone } = require('./utils');
1
2
 
2
3
  /**
3
4
  * Create an object that is able to return a copy and not
4
5
  * a reference to its properties.
6
+ * @example
7
+ * // Create an immutable object
8
+ * const config = new ImmutableObject({
9
+ * apiKey: 'secret-key',
10
+ * timeout: 5000,
11
+ * retries: 3
12
+ * });
13
+ *
14
+ * // Lock it to prevent changes
15
+ * config.finalize();
16
+ *
17
+ * // Get a copy (not a reference)
18
+ * const configCopy = config.get();
19
+ * configCopy.apiKey = 'modified'; // Original is unchanged
20
+ *
21
+ * @example
22
+ * // Create and finalize immediately
23
+ * const settings = new ImmutableObject({
24
+ * database: { host: 'localhost', port: 5432 },
25
+ * cache: { ttl: 300 }
26
+ * }, true);
27
+ *
28
+ * // Get nested values
29
+ * const dbConfig = settings.get('database');
30
+ * console.log(dbConfig); // { host: 'localhost', port: 5432 }
31
+ *
32
+ * @example
33
+ * // Use for connection configurations
34
+ * const connections = new ImmutableObject({
35
+ * api: { host: 'api.example.com', path: '/v1' },
36
+ * auth: { host: 'auth.example.com', path: '/oauth' }
37
+ * });
38
+ *
39
+ * connections.finalize();
40
+ *
41
+ * // Each get() returns a fresh copy
42
+ * const apiConn1 = connections.get('api');
43
+ * const apiConn2 = connections.get('api');
44
+ * apiConn1.path = '/v2'; // apiConn2 is unaffected
5
45
  */
6
46
  class ImmutableObject {
7
47
 
@@ -25,7 +65,7 @@ class ImmutableObject {
25
65
  if ( !this.locked ) {
26
66
  /* We'll stringify the object to break all references,
27
67
  then change it back to an object */
28
- this.obj = JSON.parse(JSON.stringify(this.obj));
68
+ this.obj = safeClone(this.obj);
29
69
  this.locked = true;
30
70
  }
31
71
  };
@@ -63,7 +103,9 @@ class ImmutableObject {
63
103
  //return {...this.connection[key]}; // doesn't make a deep copy
64
104
  //return Object.assign({}, this.connection[key]);
65
105
 
66
- return JSON.parse(JSON.stringify( (key === "" || !(key in this.obj)) ? this.obj : this.obj[key] ));
106
+ // If no key argument was provided (undefined), return the whole object
107
+ // Otherwise, return the value at the specified key (even if key is "")
108
+ return safeClone( (arguments.length === 0 || !(key in this.obj)) ? this.obj : this.obj[key] );
67
109
 
68
110
  };
69
111
  };
@@ -13,6 +13,44 @@ const ImmutableObject = require("./ImmutableObject.class");
13
13
  * Processes the request from the event data. Parses out
14
14
  * client details such as ip and user agent. May be extended
15
15
  * to provide custom processing for the application.
16
+ * @example
17
+ * // Basic usage in Lambda handler
18
+ * exports.handler = async (event, context) => {
19
+ * const requestInfo = new RequestInfo(event);
20
+ *
21
+ * // Get client information
22
+ * const userAgent = requestInfo.getClientUserAgent();
23
+ * const clientIP = requestInfo.getClientIP();
24
+ * const referer = requestInfo.getClientReferer();
25
+ *
26
+ * console.log(`Request from ${clientIP} using ${userAgent}`);
27
+ *
28
+ * // Check if request is valid
29
+ * if (!requestInfo.isValid()) {
30
+ * return { statusCode: 400, body: 'Invalid request' };
31
+ * }
32
+ *
33
+ * // Process request...
34
+ * };
35
+ *
36
+ * @example
37
+ * // Extend RequestInfo for custom processing
38
+ * class CustomRequestInfo extends RequestInfo {
39
+ * constructor(event) {
40
+ * super(event);
41
+ * // Add custom processing
42
+ * }
43
+ *
44
+ * getCustomData() {
45
+ * return this.get('client');
46
+ * }
47
+ * }
48
+ *
49
+ * @example
50
+ * // Get request data as object
51
+ * const requestInfo = new RequestInfo(event);
52
+ * const fullData = requestInfo.toObject(true); // Include sensitive data
53
+ * const safeData = requestInfo.toObject(); // Sensitive data stripped
16
54
  */
17
55
  class RequestInfo {
18
56