@chadkluck/cache-data
Version:
Cache data from an API endpoint or application process using AWS S3 and DynamoDb
183 lines (158 loc) • 5.76 kB
JavaScript
/* ****************************************************************************
* Response Data Model
* ----------------------------------------------------------------------------
*
* Provides a class that can be used to store and complie data to send back
* as a response.
*
*************************************************************************** */
/**
* A response object that can be used to collect data to be sent back as a response.
* A structured skeleton may be created during construction to create an order of
* presenting various keys. As the program executes, additional data may be added.
* Other response objects may be added with keys to fill out the object. If there are
* key collisions then new items matching that key are added as an element in an array.
*
* Extends ResponseDataModel, can be used to extend as an interface.
*
* @example
* let obj = new Response(); // you can pass a skeleton that you will add to, or the full object to the constructor
* obj.addItem(newItem); // where newItem is another response object or regular structured object which will be added as a node
* 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
* obj.removeEmpty(); // optional, it will remove empty keys
* response = {
* statusCode: 200,
* body: dataResponse.toString(),
* headers: {'content-type': 'application/json'}
* };
*
*/
class ResponseDataModel {
_responseData = null;
_label = "";
/**
* Used for collecting parts of a response. A data skeleton may be passed in as an object.
*
* @param {*} data Can be a skeleton with various fields set to {}, [], "", null or defaults.
* @param {*} label
*/
constructor(data = null, label = "") {
if (data !== null) {
this._responseData = data;
}
if (label !== "") {
this._label = label;
}
};
/**
* Get the label that will be used when this object is added to another
* ResponseDataModel or returned as a response
* @returns {string} a label to use as a key for the object
*/
getLabel() {
return this._label;
};
/**
* Get the data object
* @returns {*} A copy of the data object
*/
getResponseData() {
return JSON.parse(JSON.stringify(this._responseData));
};
/**
* Add an item as part of an array.
* If the responseObject is null, it will be transformed into an array and the item will be added at index 0
* If the responseObject is an array, the item will be added as the next index
* If the responseObject is an object, the item will be added as an array element under the label (or 'items' if label is "")
* @param {ResponseDataModel|*} item
*/
addItem(item) {
let data = null;
let label = "";
if ( item instanceof ResponseDataModel ) {
data = item.getResponseData();
label = item.getLabel(); // see if there is an override key/label
} else {
data = item;
}
if ( label === "" ) {
if ( this._responseData === null ) {
this._responseData = [];
}
if ( Array.isArray(this._responseData)) {
this._responseData.push(data);
} else if ( this._responseData instanceof Object ) {
if ( !("items" in this._responseData) || this._responseData.items === null) {
this._responseData.items = [];
}
this._responseData.items.push(data);
}
} else {
if ( this._responseData === null ) {
this._responseData = {};
}
if ( !(label in this._responseData) || this._responseData[label] === null) {
this._responseData[label] = [];
}
this._responseData[label].push(data);
}
};
/**
* Add an item by key
* @param {ResponseDataModel|*} item
* @param {string} key
*/
addItemByKey(item, key = "") {
if ( this._responseData === null ) {
this._responseData = {};
}
let data = null;
let label = "";
if ( item instanceof ResponseDataModel ) {
data = item.getResponseData();
label = (key !== "" ? key : item.getLabel() ); // see if there is an override key/label
} else {
data = item;
label = key;
}
// check if the key exists, if it does (and it is not an "empty" placeholder) then we will add this item to an array
if ( label in this._responseData
&& this._responseData[label] !== null // any placeholder
&& this._responseData[label] !== "" // string placeholder
&& this._responseData[label] != 0 // number placeholder
&& !( this._responseData[label] instanceof Object && Object.keys(this._responseData[label]).length === 0 && Object.getPrototypeOf(this._responseData[label]) === Object.prototype ) // object placeholder
) {
// if it is not yet an array, convert to array and move existing data to index 0
if ( !Array.isArray(this._responseData[label]) ) {
let temp = JSON.parse(JSON.stringify(this._responseData[label])); // no pointers, create copy
this._responseData[label] = []; // reassign to array
this._responseData[label].push(temp); // move original element to array
}
this._responseData[label].push(data); // push the new data onto array
} else {
this._responseData[label] = data; // replace
}
};
/**
*
* @returns {*} The data object. If there is a label then it is returned as a key value pair where the label is the key
*/
toObject() {
let obj = {};
if (this._label === "") {
obj = this.getResponseData();
} else {
let key = this._label;
obj[key] = this.getResponseData();
}
return obj;
};
/**
*
* @returns {string} A stringified JSON object (using .toObject() ) for use as a response
*/
toString() {
return JSON.stringify(this.toObject());
};
};
module.exports = ResponseDataModel;