@63klabs/cache-data 1.3.5 → 1.3.7

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.
@@ -1,33 +1,27 @@
1
-
2
- /* ****************************************************************************
3
- * Response Data Model
4
- * ----------------------------------------------------------------------------
5
- *
6
- * Provides a class that can be used to store and complie data to send back
7
- * as a response.
8
- *
9
- *************************************************************************** */
1
+ const { safeClone } = require('./utils');
10
2
 
11
3
  /**
12
- * A response object that can be used to collect data to be sent back as a response.
13
- * A structured skeleton may be created during construction to create an order of
14
- * presenting various keys. As the program executes, additional data may be added.
15
- * Other response objects may be added with keys to fill out the object. If there are
16
- * key collisions then new items matching that key are added as an element in an array.
4
+ * ResponseDataModel class for collecting and structuring response data.
5
+ * Provides methods to build complex response objects by adding items with keys or as array elements.
6
+ * Supports creating structured skeletons during construction and filling them during execution.
7
+ * Handles key collisions by converting single values to arrays when duplicate keys are added.
17
8
  *
18
- * Extends ResponseDataModel, can be used to extend as an interface.
9
+ * @class ResponseDataModel
10
+ * @example
11
+ * // Create response with skeleton
12
+ * const response = new ResponseDataModel({ users: [], metadata: {} }, 'data');
13
+ * response.addItemByKey({ id: 1, name: 'John' }, 'users');
14
+ * response.addItemByKey({ id: 2, name: 'Jane' }, 'users');
15
+ * console.log(response.toString());
16
+ * // Output: {"data":{"users":[{"id":1,"name":"John"},{"id":2,"name":"Jane"}],"metadata":{}}}
19
17
  *
20
18
  * @example
21
- * let obj = new Response(); // you can pass a skeleton that you will add to, or the full object to the constructor
22
- * obj.addItem(newItem); // where newItem is another response object or regular structured object which will be added as a node
23
- * obj.addItemByKey(newItem2,"employees");// where newItem2 is another response object or regular structured object which will be added as a node. Note that you can override a label by passing a new one. For example pluralizing a label
24
- * obj.removeEmpty(); // optional, it will remove empty keys
25
- * response = {
26
- * statusCode: 200,
27
- * body: dataResponse.toString(),
28
- * headers: {'content-type': 'application/json'}
29
- * };
30
- *
19
+ * // Add items to array
20
+ * const list = new ResponseDataModel(null, 'items');
21
+ * list.addItem({ id: 1 });
22
+ * list.addItem({ id: 2 });
23
+ * console.log(list.toString());
24
+ * // Output: {"items":[{"id":1},{"id":2}]}
31
25
  */
32
26
  class ResponseDataModel {
33
27
 
@@ -35,10 +29,18 @@ class ResponseDataModel {
35
29
  _label = "";
36
30
 
37
31
  /**
38
- * Used for collecting parts of a response. A data skeleton may be passed in as an object.
32
+ * Creates a new ResponseDataModel instance for collecting response data.
33
+ * A data skeleton may be passed in with various fields set to {}, [], "", null, or default values.
39
34
  *
40
- * @param {*} data Can be a skeleton with various fields set to {}, [], "", null or defaults.
41
- * @param {*} label
35
+ * @param {*} [data=null] - Initial data structure (can be a skeleton or complete object)
36
+ * @param {string} [label=""] - Label to use as a key when this object is added to another ResponseDataModel
37
+ * @example
38
+ * // Create with skeleton
39
+ * const response = new ResponseDataModel({ users: [], count: 0 }, 'data');
40
+ *
41
+ * @example
42
+ * // Create empty
43
+ * const response = new ResponseDataModel();
42
44
  */
43
45
  constructor(data = null, label = "") {
44
46
  if (data !== null) {
@@ -51,28 +53,48 @@ class ResponseDataModel {
51
53
  };
52
54
 
53
55
  /**
54
- * Get the label that will be used when this object is added to another
55
- * ResponseDataModel or returned as a response
56
- * @returns {string} a label to use as a key for the object
56
+ * Gets the label that will be used when this object is added to another ResponseDataModel.
57
+ *
58
+ * @returns {string} The label to use as a key for the object
59
+ * @example
60
+ * const response = new ResponseDataModel({ id: 1 }, 'user');
61
+ * console.log(response.getLabel()); // 'user'
57
62
  */
58
63
  getLabel() {
59
64
  return this._label;
60
65
  };
61
66
 
62
67
  /**
63
- * Get the data object
64
- * @returns {*} A copy of the data object
68
+ * Gets a copy of the response data object.
69
+ *
70
+ * @returns {*} A cloned copy of the data object
71
+ * @example
72
+ * const data = response.getResponseData();
73
+ * console.log(data);
65
74
  */
66
75
  getResponseData() {
67
- return JSON.parse(JSON.stringify(this._responseData));
76
+ return safeClone(this._responseData);
68
77
  };
69
78
 
70
79
  /**
71
- * Add an item as part of an array.
72
- * If the responseObject is null, it will be transformed into an array and the item will be added at index 0
73
- * If the responseObject is an array, the item will be added as the next index
74
- * If the responseObject is an object, the item will be added as an array element under the label (or 'items' if label is "")
75
- * @param {ResponseDataModel|*} item
80
+ * Adds an item as part of an array or under a labeled key.
81
+ * - If responseData is null, transforms it into an array and adds item at index 0
82
+ * - If responseData is an array, adds item as the next element
83
+ * - If responseData is an object, adds item as an array element under the label (or 'items' if no label)
84
+ *
85
+ * @param {ResponseDataModel|*} item - Item to add (can be ResponseDataModel or any value)
86
+ * @returns {void}
87
+ * @example
88
+ * const response = new ResponseDataModel();
89
+ * response.addItem({ id: 1, name: 'John' });
90
+ * response.addItem({ id: 2, name: 'Jane' });
91
+ * // Result: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]
92
+ *
93
+ * @example
94
+ * // Add with label
95
+ * const item = new ResponseDataModel({ id: 1 }, 'user');
96
+ * response.addItem(item);
97
+ * // Result: { user: [{ id: 1 }] }
76
98
  */
77
99
  addItem(item) {
78
100
 
@@ -83,7 +105,18 @@ class ResponseDataModel {
83
105
  data = item.getResponseData();
84
106
  label = item.getLabel(); // see if there is an override key/label
85
107
  } else {
86
- data = item;
108
+ // Clone plain objects to prevent external mutation
109
+ // If cloning fails (e.g., functions, symbols), use the original value
110
+ if (typeof item === 'object' && item !== null) {
111
+ try {
112
+ data = safeClone(item);
113
+ } catch (e) {
114
+ // If safeClone fails, fall back to original value
115
+ data = item;
116
+ }
117
+ } else {
118
+ data = item;
119
+ }
87
120
  }
88
121
 
89
122
  if ( label === "" ) {
@@ -114,9 +147,23 @@ class ResponseDataModel {
114
147
  };
115
148
 
116
149
  /**
117
- * Add an item by key
118
- * @param {ResponseDataModel|*} item
119
- * @param {string} key
150
+ * Adds an item by a specific key.
151
+ * If the key exists and contains non-empty data, converts to array and appends new item.
152
+ * If the key doesn't exist or contains placeholder data, replaces with new item.
153
+ *
154
+ * @param {ResponseDataModel|*} item - Item to add (can be ResponseDataModel or any value)
155
+ * @param {string} [key=""] - Key to use for the item (overrides item's label if provided)
156
+ * @returns {void}
157
+ * @example
158
+ * const response = new ResponseDataModel({});
159
+ * response.addItemByKey({ id: 1, name: 'John' }, 'user');
160
+ * response.addItemByKey({ id: 2, name: 'Jane' }, 'user');
161
+ * // Result: { user: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }] }
162
+ *
163
+ * @example
164
+ * // Override label
165
+ * const item = new ResponseDataModel({ id: 1 }, 'employee');
166
+ * response.addItemByKey(item, 'employees'); // Pluralize the label
120
167
  */
121
168
  addItemByKey(item, key = "") {
122
169
 
@@ -131,7 +178,18 @@ class ResponseDataModel {
131
178
  data = item.getResponseData();
132
179
  label = (key !== "" ? key : item.getLabel() ); // see if there is an override key/label
133
180
  } else {
134
- data = item;
181
+ // Clone plain objects to prevent external mutation
182
+ // If cloning fails (e.g., functions, symbols), use the original value
183
+ if (typeof item === 'object' && item !== null) {
184
+ try {
185
+ data = safeClone(item);
186
+ } catch (e) {
187
+ // If safeClone fails, fall back to original value
188
+ data = item;
189
+ }
190
+ } else {
191
+ data = item;
192
+ }
135
193
  label = key;
136
194
  }
137
195
 
@@ -144,7 +202,7 @@ class ResponseDataModel {
144
202
  ) {
145
203
  // if it is not yet an array, convert to array and move existing data to index 0
146
204
  if ( !Array.isArray(this._responseData[label]) ) {
147
- let temp = JSON.parse(JSON.stringify(this._responseData[label])); // no pointers, create copy
205
+ let temp = safeClone(this._responseData[label]); // no pointers, create copy
148
206
  this._responseData[label] = []; // reassign to array
149
207
  this._responseData[label].push(temp); // move original element to array
150
208
  }
@@ -156,8 +214,20 @@ class ResponseDataModel {
156
214
  };
157
215
 
158
216
  /**
217
+ * Converts the response data to an object.
218
+ * If there's a label, returns the data as a key-value pair with the label as the key.
219
+ * If no label, returns the data directly.
220
+ *
221
+ * @returns {*} The data object, optionally wrapped with label as key
222
+ * @example
223
+ * const response = new ResponseDataModel({ id: 1 }, 'user');
224
+ * console.log(response.toObject());
225
+ * // Output: { user: { id: 1 } }
159
226
  *
160
- * @returns {*} The data object. If there is a label then it is returned as a key value pair where the label is the key
227
+ * @example
228
+ * const response = new ResponseDataModel({ id: 1 });
229
+ * console.log(response.toObject());
230
+ * // Output: { id: 1 }
161
231
  */
162
232
  toObject() {
163
233
  let obj = {};
@@ -171,8 +241,14 @@ class ResponseDataModel {
171
241
  };
172
242
 
173
243
  /**
244
+ * Converts the response data to a JSON string.
245
+ * Uses toObject() to get the object representation, then stringifies it.
174
246
  *
175
- * @returns {string} A stringified JSON object (using .toObject() ) for use as a response
247
+ * @returns {string} JSON string representation of the response data
248
+ * @example
249
+ * const response = new ResponseDataModel({ users: [{ id: 1 }] }, 'data');
250
+ * console.log(response.toString());
251
+ * // Output: '{"data":{"users":[{"id":1}]}}'
176
252
  */
177
253
  toString() {
178
254
  return JSON.stringify(this.toObject());
@@ -1,7 +1,40 @@
1
1
  /* */
2
2
  const DebugAndLog = require("./DebugAndLog.class");
3
3
 
4
+ /**
5
+ * Timer class for measuring execution time and tracking performance metrics.
6
+ * Provides methods to start, stop, and query elapsed time with diagnostic logging.
7
+ *
8
+ * @class Timer
9
+ * @example
10
+ * // Create and start a timer
11
+ * const timer = new Timer('myOperation', true);
12
+ * // ... perform operation ...
13
+ * const elapsed = timer.stop();
14
+ * console.log(`Operation took ${elapsed}ms`);
15
+ *
16
+ * @example
17
+ * // Create timer without auto-start
18
+ * const timer = new Timer('delayedOperation');
19
+ * await timer.start();
20
+ * // ... perform operation ...
21
+ * timer.stop();
22
+ */
4
23
  class Timer {
24
+ /**
25
+ * Creates a new Timer instance.
26
+ *
27
+ * @param {string} name - The name of the timer for identification in logs
28
+ * @param {boolean} [start=false] - Whether to automatically start the timer upon creation
29
+ * @example
30
+ * // Create timer with auto-start
31
+ * const timer = new Timer('apiCall', true);
32
+ *
33
+ * @example
34
+ * // Create timer without auto-start
35
+ * const timer = new Timer('batchProcess');
36
+ * await timer.start();
37
+ */
5
38
  constructor(name, start = false) {
6
39
  this.name = name;
7
40
  this.startTime = -1;
@@ -15,13 +48,29 @@ class Timer {
15
48
  }
16
49
  };
17
50
 
51
+ /**
52
+ * Updates the timer's internal message and logs it for diagnostics.
53
+ *
54
+ * @param {string} message - The message to set and log
55
+ * @returns {Promise<void>}
56
+ * @example
57
+ * await timer.updateMessage('Processing batch 1 of 10');
58
+ */
18
59
  async updateMessage(message) {
19
60
  this.latestMessage = message;
20
61
  DebugAndLog.diag(this.latestMessage);
21
62
  };
22
63
 
23
64
  /**
24
- * Start the timer
65
+ * Starts the timer if it hasn't been started already.
66
+ * Records the start time and logs a diagnostic message.
67
+ *
68
+ * @returns {Promise<void>}
69
+ * @example
70
+ * const timer = new Timer('operation');
71
+ * await timer.start();
72
+ * // ... perform operation ...
73
+ * timer.stop();
25
74
  */
26
75
  async start() {
27
76
  if ( this.startTime === -1 ) {
@@ -31,9 +80,15 @@ class Timer {
31
80
  };
32
81
 
33
82
  /**
34
- * Stop the timer
83
+ * Stops the timer if it hasn't been stopped already.
84
+ * Records the stop time, logs elapsed time, and returns the elapsed duration.
35
85
  *
36
- * @returns {number} The time elapsed in milliseconds
86
+ * @returns {number} The time elapsed in milliseconds between start and stop
87
+ * @example
88
+ * const timer = new Timer('dataProcessing', true);
89
+ * // ... process data ...
90
+ * const duration = timer.stop();
91
+ * console.log(`Processing completed in ${duration}ms`);
37
92
  */
38
93
  stop() {
39
94
  if ( this.stopTime === -1 ) {
@@ -44,85 +99,137 @@ class Timer {
44
99
  };
45
100
 
46
101
  /**
47
- * The amount of time elapsed between the start and stop of the timer.
48
- * If the timer is still running it will be the amount of time between
49
- * start and now(). If the timer is stopped it will be the amount of
50
- * time between the start and stop.
102
+ * Gets the amount of time elapsed between the start and stop of the timer.
103
+ * If the timer is still running, returns the time between start and now().
104
+ * If the timer is stopped, returns the time between start and stop.
51
105
  *
52
- * @returns {number}
106
+ * @returns {number} Elapsed time in milliseconds
107
+ * @example
108
+ * const timer = new Timer('operation', true);
109
+ * // ... perform operation ...
110
+ * console.log(`Current elapsed: ${timer.elapsed()}ms`);
111
+ * timer.stop();
112
+ * console.log(`Final elapsed: ${timer.elapsed()}ms`);
53
113
  */
54
114
  elapsed() {
55
115
  return ((this.isRunning()) ? this.now() : this.stopTime ) - this.startTime;
56
116
  };
57
117
 
58
118
  /**
59
- * The amount of time elapsed between the start of the timer and now()
60
- * Even if the timer is stopped, it will use now() and this value will
61
- * continue to increase during execution.
62
- *
119
+ * Gets the amount of time elapsed between the start of the timer and now().
120
+ * Even if the timer is stopped, this value will continue to increase during execution.
63
121
  * Use elapsed() to get the amount of time between start and stop.
64
122
  *
65
- * @returns {number}
123
+ * @returns {number} Time in milliseconds since the timer was started
124
+ * @example
125
+ * const timer = new Timer('longOperation', true);
126
+ * // ... perform operation ...
127
+ * timer.stop();
128
+ * console.log(`Time since start: ${timer.elapsedSinceStart()}ms`);
66
129
  */
67
130
  elapsedSinceStart() {
68
131
  return (this.now() - this.startTime);
69
132
  };
70
133
 
71
134
  /**
72
- * The amount of time elapsed since the timer was stopped and will increase
73
- * during execution. If the timer has not been stopped, it will
74
- * return -1 (negative one)
135
+ * Gets the amount of time elapsed since the timer was stopped.
136
+ * This value will increase during execution after the timer is stopped.
137
+ * If the timer has not been stopped, returns -1.
75
138
  *
76
- * @returns {number}
139
+ * @returns {number} Time in milliseconds since the timer was stopped, or -1 if still running
140
+ * @example
141
+ * const timer = new Timer('operation', true);
142
+ * timer.stop();
143
+ * setTimeout(() => {
144
+ * console.log(`Time since stop: ${timer.elapsedSinceStop()}ms`);
145
+ * }, 1000);
77
146
  */
78
147
  elapsedSinceStop() {
79
148
  return (this.isRunning() ? -1 : this.now() - this.stopTime);
80
149
  };
81
150
 
82
151
  /**
83
- * The time now. Same as Date.now()
152
+ * Gets the current time in milliseconds since the Unix epoch.
153
+ * Equivalent to Date.now().
84
154
  *
85
- * @returns {number}
155
+ * @returns {number} Current timestamp in milliseconds
156
+ * @example
157
+ * const timer = new Timer('test');
158
+ * const timestamp = timer.now();
159
+ * console.log(`Current time: ${timestamp}`);
86
160
  */
87
161
  now() {
88
162
  return Date.now();
89
163
  };
90
164
 
91
165
  /**
92
- * Was the timer started
93
- * @returns {boolean}
166
+ * Checks whether the timer has been started.
167
+ *
168
+ * @returns {boolean} True if the timer was started, false otherwise
169
+ * @example
170
+ * const timer = new Timer('operation');
171
+ * console.log(timer.wasStarted()); // false
172
+ * await timer.start();
173
+ * console.log(timer.wasStarted()); // true
94
174
  */
95
175
  wasStarted() {
96
176
  return (this.startTime > 0);
97
177
  };
98
178
 
99
179
  /**
180
+ * Checks whether the timer has not been started yet.
100
181
  *
101
- * @returns {boolean} Returns true if timer has not yet been started
182
+ * @returns {boolean} True if timer has not yet been started, false otherwise
183
+ * @example
184
+ * const timer = new Timer('operation');
185
+ * console.log(timer.notStarted()); // true
186
+ * await timer.start();
187
+ * console.log(timer.notStarted()); // false
102
188
  */
103
189
  notStarted() {
104
190
  return !(this.wasStarted());
105
191
  };
106
192
 
107
193
  /**
194
+ * Checks whether the timer is currently running.
195
+ * A timer is running if it has been started but not yet stopped.
108
196
  *
109
- * @returns {boolean} True if the timer is currently running. False if not running
197
+ * @returns {boolean} True if the timer is currently running, false if not running
198
+ * @example
199
+ * const timer = new Timer('operation', true);
200
+ * console.log(timer.isRunning()); // true
201
+ * timer.stop();
202
+ * console.log(timer.isRunning()); // false
110
203
  */
111
204
  isRunning() {
112
205
  return (this.wasStarted() && this.stopTime < 0);
113
206
  };
114
207
 
115
208
  /**
209
+ * Checks whether the timer has been stopped.
116
210
  *
117
- * @returns {boolean} True if the timer was stopped. False if not stopped
211
+ * @returns {boolean} True if the timer was stopped, false if not stopped
212
+ * @example
213
+ * const timer = new Timer('operation', true);
214
+ * console.log(timer.wasStopped()); // false
215
+ * timer.stop();
216
+ * console.log(timer.wasStopped()); // true
118
217
  */
119
218
  wasStopped() {
120
219
  return (this.wasStarted() && this.stopTime > 0);
121
220
  };
122
221
 
123
222
  /**
223
+ * Gets the current status of the timer as a string.
124
224
  *
125
- * @returns {string} Text string denoting stating. 'NOT_STARTED', 'IS_RUNNING', 'IS_STOPPED'
225
+ * @returns {string} Status string: 'NOT_STARTED', 'IS_RUNNING', or 'IS_STOPPED'
226
+ * @example
227
+ * const timer = new Timer('operation');
228
+ * console.log(timer.status()); // 'NOT_STARTED'
229
+ * await timer.start();
230
+ * console.log(timer.status()); // 'IS_RUNNING'
231
+ * timer.stop();
232
+ * console.log(timer.status()); // 'IS_STOPPED'
126
233
  */
127
234
  status() {
128
235
  var s = "NOT_STARTED";
@@ -133,8 +240,13 @@ class Timer {
133
240
  };
134
241
 
135
242
  /**
136
- * Messages are internal updates about the status
243
+ * Gets the latest internal message from the timer.
244
+ * Messages are internal updates about the timer's status.
245
+ *
137
246
  * @returns {string} The latest message from the timer
247
+ * @example
248
+ * const timer = new Timer('operation', true);
249
+ * console.log(timer.message()); // "Timer 'operation' started at ..."
138
250
  */
139
251
  message() {
140
252
  return (this.latestMessage);
@@ -92,6 +92,22 @@ class _ConfigSuperClass {
92
92
  static _connections = null;
93
93
  static _settings = null;
94
94
 
95
+ /**
96
+ * Get the application settings object
97
+ *
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.
101
+ *
102
+ * @returns {object|null} Settings object containing application configuration, or null if not initialized
103
+ * @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
+ * }
110
+ */
95
111
  static settings() {
96
112
  return _ConfigSuperClass._settings;
97
113
  };
@@ -105,14 +121,85 @@ class _ConfigSuperClass {
105
121
  };
106
122
 
107
123
  /**
124
+ * Get a connection by name and return the Connection instance
108
125
  *
109
- * @param {string} name
110
- * @returns {Connection}
126
+ * @param {string} name The name of the connection to retrieve
127
+ * @returns {Connection|null} Connection instance or null if not found
111
128
  */
112
129
  static getConnection(name) {
130
+ if (_ConfigSuperClass._connections === null) {
131
+ return null;
132
+ }
113
133
  return _ConfigSuperClass._connections.get(name);
114
134
  }
115
135
 
136
+ /**
137
+ * Get a connection by name and return it as a plain object
138
+ *
139
+ * @param {string} name The name of the connection to retrieve
140
+ * @returns {{method: string, uri: string, protocol: string, host: string, path: string, headers: object, parameters: object, body: string, options: object, note: string, authentication: object}|null} Connection object with properties or null if not found
141
+ * @example
142
+ * const conn = Config.getConn('myConnection');
143
+ * const cacheObj = await CacheableDataAccess.getData(
144
+ * cacheProfile,
145
+ * endpoint.get
146
+ * conn
147
+ * )
148
+ * */
149
+ static getConn(name) {
150
+ if (_ConfigSuperClass._connections === null) {
151
+ return null;
152
+ }
153
+
154
+ const connection = _ConfigSuperClass._connections.get(name);
155
+
156
+ if (connection === null) {
157
+ return null;
158
+ }
159
+
160
+ return connection.toObject();
161
+ }
162
+
163
+ /**
164
+ * Get a connection AND one of its Cache Profiles by name and return as plain objects
165
+ * @param {string} connectionName The name of the connection to retrieve
166
+ * @param {string} cacheProfileName The name of the cache profile to retrieve from the connection
167
+ * @returns {{conn: {method: string, uri: string, protocol: string, host: string, path: string, headers: object, parameters: object, body: string, options: object, note: string, authentication: object}|null, cacheProfile: {profile: string, overrideOriginHeaderExpiration: boolean, defaultExpirationInSeconds: number, expirationIsOnInterval: boolean, hostId: string, pathId: string, encrypt: boolean, defaultExpirationExtensionOnErrorInSeconds: number}|null}} Connection and Cache Profile objects or null if not found
168
+ * @example
169
+ * const { conn, cacheProfile } = Config.getConnCacheProfile('myConnection', 'myCacheProfile');
170
+ * const cacheObj = await CacheableDataAccess.getData(
171
+ * cacheProfile,
172
+ * endpoint.get
173
+ * conn
174
+ * )
175
+ */
176
+ static getConnCacheProfile(connectionName, cacheProfileName) {
177
+
178
+ if (_ConfigSuperClass._connections === null) {
179
+ return { conn: null, cacheProfile: null };
180
+ }
181
+
182
+ const connection = _ConfigSuperClass._connections.get(connectionName);
183
+
184
+ if (connection === null) {
185
+ return { conn: null, cacheProfile: null };
186
+ }
187
+
188
+ let cacheProfile = null;
189
+ try {
190
+ const profile = connection.getCacheProfile(cacheProfileName);
191
+ cacheProfile = (profile === undefined) ? null : profile;
192
+ } catch (error) {
193
+ // getCacheProfile throws if _cacheProfiles is null
194
+ cacheProfile = null;
195
+ }
196
+
197
+ return {
198
+ conn: connection.toObject(),
199
+ cacheProfile: cacheProfile
200
+ };
201
+ }
202
+
116
203
  /**
117
204
  *
118
205
  * @returns {Promise} A promise that resolves when the Config class has finished initializing