@63klabs/cache-data 1.2.2

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.
@@ -0,0 +1,183 @@
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
+ *************************************************************************** */
10
+
11
+ /**
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.
17
+ *
18
+ * Extends ResponseDataModel, can be used to extend as an interface.
19
+ *
20
+ * @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
+ *
31
+ */
32
+ class ResponseDataModel {
33
+
34
+ _responseData = null;
35
+ _label = "";
36
+
37
+ /**
38
+ * Used for collecting parts of a response. A data skeleton may be passed in as an object.
39
+ *
40
+ * @param {*} data Can be a skeleton with various fields set to {}, [], "", null or defaults.
41
+ * @param {*} label
42
+ */
43
+ constructor(data = null, label = "") {
44
+ if (data !== null) {
45
+ this._responseData = data;
46
+ }
47
+
48
+ if (label !== "") {
49
+ this._label = label;
50
+ }
51
+ };
52
+
53
+ /**
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
57
+ */
58
+ getLabel() {
59
+ return this._label;
60
+ };
61
+
62
+ /**
63
+ * Get the data object
64
+ * @returns {*} A copy of the data object
65
+ */
66
+ getResponseData() {
67
+ return JSON.parse(JSON.stringify(this._responseData));
68
+ };
69
+
70
+ /**
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
76
+ */
77
+ addItem(item) {
78
+
79
+ let data = null;
80
+ let label = "";
81
+
82
+ if ( item instanceof ResponseDataModel ) {
83
+ data = item.getResponseData();
84
+ label = item.getLabel(); // see if there is an override key/label
85
+ } else {
86
+ data = item;
87
+ }
88
+
89
+ if ( label === "" ) {
90
+ if ( this._responseData === null ) {
91
+ this._responseData = [];
92
+ }
93
+
94
+ if ( Array.isArray(this._responseData)) {
95
+ this._responseData.push(data);
96
+ } else if ( this._responseData instanceof Object ) {
97
+ if ( !("items" in this._responseData) || this._responseData.items === null) {
98
+ this._responseData.items = [];
99
+ }
100
+ this._responseData.items.push(data);
101
+ }
102
+ } else {
103
+ if ( this._responseData === null ) {
104
+ this._responseData = {};
105
+ }
106
+
107
+ if ( !(label in this._responseData) || this._responseData[label] === null) {
108
+ this._responseData[label] = [];
109
+ }
110
+
111
+ this._responseData[label].push(data);
112
+ }
113
+
114
+ };
115
+
116
+ /**
117
+ * Add an item by key
118
+ * @param {ResponseDataModel|*} item
119
+ * @param {string} key
120
+ */
121
+ addItemByKey(item, key = "") {
122
+
123
+ if ( this._responseData === null ) {
124
+ this._responseData = {};
125
+ }
126
+
127
+ let data = null;
128
+ let label = "";
129
+
130
+ if ( item instanceof ResponseDataModel ) {
131
+ data = item.getResponseData();
132
+ label = (key !== "" ? key : item.getLabel() ); // see if there is an override key/label
133
+ } else {
134
+ data = item;
135
+ label = key;
136
+ }
137
+
138
+ // check if the key exists, if it does (and it is not an "empty" placeholder) then we will add this item to an array
139
+ if ( label in this._responseData
140
+ && this._responseData[label] !== null // any placeholder
141
+ && this._responseData[label] !== "" // string placeholder
142
+ && this._responseData[label] != 0 // number placeholder
143
+ && !( this._responseData[label] instanceof Object && Object.keys(this._responseData[label]).length === 0 && Object.getPrototypeOf(this._responseData[label]) === Object.prototype ) // object placeholder
144
+ ) {
145
+ // if it is not yet an array, convert to array and move existing data to index 0
146
+ if ( !Array.isArray(this._responseData[label]) ) {
147
+ let temp = JSON.parse(JSON.stringify(this._responseData[label])); // no pointers, create copy
148
+ this._responseData[label] = []; // reassign to array
149
+ this._responseData[label].push(temp); // move original element to array
150
+ }
151
+ this._responseData[label].push(data); // push the new data onto array
152
+ } else {
153
+ this._responseData[label] = data; // replace
154
+ }
155
+
156
+ };
157
+
158
+ /**
159
+ *
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
161
+ */
162
+ toObject() {
163
+ let obj = {};
164
+ if (this._label === "") {
165
+ obj = this.getResponseData();
166
+ } else {
167
+ let key = this._label;
168
+ obj[key] = this.getResponseData();
169
+ }
170
+ return obj;
171
+ };
172
+
173
+ /**
174
+ *
175
+ * @returns {string} A stringified JSON object (using .toObject() ) for use as a response
176
+ */
177
+ toString() {
178
+ return JSON.stringify(this.toObject());
179
+ };
180
+
181
+ };
182
+
183
+ module.exports = ResponseDataModel;
@@ -0,0 +1,189 @@
1
+ /* */
2
+ const DebugAndLog = require("./DebugAndLog.class");
3
+
4
+ class Timer {
5
+ constructor(name, start = false) {
6
+ this.name = name;
7
+ this.startTime = -1;
8
+ this.stopTime = -1;
9
+ this.latestMessage = "";
10
+
11
+ if (start) {
12
+ this.start();
13
+ } else {
14
+ this.updateMessage("Timer '"+this.name+"' created at "+this.now());
15
+ }
16
+ };
17
+
18
+ async updateMessage(message) {
19
+ this.latestMessage = message;
20
+ DebugAndLog.diag(this.latestMessage);
21
+ };
22
+
23
+ /**
24
+ * Start the timer
25
+ */
26
+ async start() {
27
+ if ( this.startTime === -1 ) {
28
+ this.startTime = this.now();
29
+ this.updateMessage("Timer '"+this.name+"' started at "+this.startTime);
30
+ }
31
+ };
32
+
33
+ /**
34
+ * Stop the timer
35
+ *
36
+ * @returns {number} The time elapsed in milliseconds
37
+ */
38
+ stop() {
39
+ if ( this.stopTime === -1 ) {
40
+ this.stopTime = this.now();
41
+ this.updateMessage("Timer '"+this.name+"' stopped at "+this.stopTime+". Time elapsed: "+this.elapsed()+" ms");
42
+ }
43
+ return this.elapsed();
44
+ };
45
+
46
+ /**
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.
51
+ *
52
+ * @returns {number}
53
+ */
54
+ elapsed() {
55
+ return ((this.isRunning()) ? this.now() : this.stopTime ) - this.startTime;
56
+ };
57
+
58
+ /**
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
+ *
63
+ * Use elapsed() to get the amount of time between start and stop.
64
+ *
65
+ * @returns {number}
66
+ */
67
+ elapsedSinceStart() {
68
+ return (this.now() - this.startTime);
69
+ };
70
+
71
+ /**
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)
75
+ *
76
+ * @returns {number}
77
+ */
78
+ elapsedSinceStop() {
79
+ return (this.isRunning() ? -1 : this.now() - this.stopTime);
80
+ };
81
+
82
+ /**
83
+ * The time now. Same as Date.now()
84
+ *
85
+ * @returns {number}
86
+ */
87
+ now() {
88
+ return Date.now();
89
+ };
90
+
91
+ /**
92
+ * Was the timer started
93
+ * @returns {boolean}
94
+ */
95
+ wasStarted() {
96
+ return (this.startTime > 0);
97
+ };
98
+
99
+ /**
100
+ *
101
+ * @returns {boolean} Returns true if timer has not yet been started
102
+ */
103
+ notStarted() {
104
+ return !(this.wasStarted());
105
+ };
106
+
107
+ /**
108
+ *
109
+ * @returns {boolean} True if the timer is currently running. False if not running
110
+ */
111
+ isRunning() {
112
+ return (this.wasStarted() && this.stopTime < 0);
113
+ };
114
+
115
+ /**
116
+ *
117
+ * @returns {boolean} True if the timer was stopped. False if not stopped
118
+ */
119
+ wasStopped() {
120
+ return (this.wasStarted() && this.stopTime > 0);
121
+ };
122
+
123
+ /**
124
+ *
125
+ * @returns {string} Text string denoting stating. 'NOT_STARTED', 'IS_RUNNING', 'IS_STOPPED'
126
+ */
127
+ status() {
128
+ var s = "NOT_STARTED";
129
+ if ( this.wasStarted() ) {
130
+ s = (this.isRunning() ? "IS_RUNNING" : "IS_STOPPED");
131
+ }
132
+ return s;
133
+ };
134
+
135
+ /**
136
+ * Messages are internal updates about the status
137
+ * @returns {string} The latest message from the timer
138
+ */
139
+ message() {
140
+ return (this.latestMessage);
141
+ };
142
+
143
+ /**
144
+ * For debugging and testing, an object of the timer may be generated
145
+ * to see the current values of each timer function.
146
+ *
147
+ * @param {boolean} sendToLog Should the timer details object be sent to the console log
148
+ * @returns {
149
+ * {
150
+ * name: string,
151
+ * status: string,
152
+ * started: boolean,
153
+ * running: boolean,
154
+ * stopped: boolean,
155
+ * start: number,
156
+ * stop: number,
157
+ * elapsed: number,
158
+ * now: number,
159
+ * elapsedSinceStart: number,
160
+ * elapsedSinceStop: number,
161
+ * latestMessage: string
162
+ * }
163
+ * } An object describing the state of the timer
164
+ */
165
+ details(sendToLog = false) {
166
+ var details = {
167
+ name: this.name,
168
+ status: this.status(),
169
+ started: this.wasStarted(),
170
+ running: this.isRunning(),
171
+ stopped: this.wasStopped(),
172
+ start: this.startTime,
173
+ stop: this.stopTime,
174
+ elapsed: this.elapsed(),
175
+ now: this.now(),
176
+ elapsedSinceStart: this.elapsedSinceStart(),
177
+ elapsedSinceStop: this.elapsedSinceStop(),
178
+ latestMessage: this.message()
179
+ };
180
+
181
+ if (sendToLog) {
182
+ DebugAndLog.debug("Timer '"+this.name+"' details",details);
183
+ }
184
+
185
+ return details;
186
+ };
187
+ };
188
+
189
+ module.exports = Timer;
@@ -0,0 +1,88 @@
1
+ contentType = "text/html; charset=utf-8";
2
+
3
+ headers = {
4
+ "Content-Type": contentType
5
+ };
6
+
7
+ html = (title, body) => {
8
+ return `<html><head><title>${title}</title></head><body>${body}</body></html>`;
9
+ }
10
+
11
+ response200 = {
12
+ statusCode: 200,
13
+ headers: headers,
14
+ body: html("200 OK", "<p>Success</p>")
15
+ };
16
+
17
+ response400 = {
18
+ statusCode: 400,
19
+ headers: headers,
20
+ body: html("400 Bad Request", "<p>Bad Request</p>")
21
+ };
22
+
23
+ response401 = {
24
+ statusCode: 401,
25
+ headers: headers,
26
+ body: html("401 Unauthorized", "<p>Unauthorized</p>")
27
+ };
28
+
29
+ response403 = {
30
+ statusCode: 403,
31
+ headers: headers,
32
+ body: html("403 Forbidden", "<p>Forbidden</p>")
33
+ };
34
+
35
+ response404 = {
36
+ statusCode: 404,
37
+ headers: headers,
38
+ body: html("404 Not Found", "<p>Not Found</p>")
39
+ };
40
+
41
+ response405 = {
42
+ statusCode: 405,
43
+ headers: headers,
44
+ body: html("405 Method Not Allowed", "<p>Method Not Allowed</p>")
45
+ };
46
+
47
+ response500 = {
48
+ statusCode: 500,
49
+ headers: headers,
50
+ body: html("500 Error", "<p>Internal Server Error</p>")
51
+ };
52
+
53
+ /**
54
+ *
55
+ * @param {number|string} statusCode
56
+ * @returns {{statusCode: number, headers: object, body: Array|Object|string}}
57
+ */
58
+ response = function (statusCode) {
59
+ // convert to int
60
+ statusCode = parseInt(statusCode, 10);
61
+
62
+ switch (statusCode) {
63
+ case 200:
64
+ return this.response200;
65
+ case 400:
66
+ return this.response400;
67
+ case 401:
68
+ return this.response401;
69
+ case 403:
70
+ return this.response403;
71
+ case 404:
72
+ return this.response404;
73
+ case 500:
74
+ return this.response500;
75
+ default:
76
+ return this.response500;
77
+ }
78
+ };
79
+
80
+ module.exports = {
81
+ contentType,
82
+ headers,
83
+ html,
84
+ response200,
85
+ response404,
86
+ response500,
87
+ response
88
+ }
@@ -0,0 +1,102 @@
1
+ contentType = "application/json"
2
+
3
+ headers = {
4
+ "Content-Type": contentType
5
+ };
6
+
7
+ json = function (data = null) {
8
+ return data ? data : {};
9
+ };
10
+
11
+ response200 = {
12
+ statusCode: 200,
13
+ headers: headers,
14
+ body: {
15
+ message: "Success"
16
+ }
17
+ };
18
+
19
+ response400 = {
20
+ statusCode: 400,
21
+ headers: headers,
22
+ body: {
23
+ message: "Bad Request"
24
+ }
25
+ };
26
+
27
+ response401 = {
28
+ statusCode: 401,
29
+ headers: headers,
30
+ body: {
31
+ message: "Unauthorized"
32
+ }
33
+ };
34
+
35
+ response403 = {
36
+ statusCode: 403,
37
+ headers: headers,
38
+ body: {
39
+ message: "Forbidden"
40
+ }
41
+ };
42
+
43
+ response404 = {
44
+ statusCode: 404,
45
+ headers: headers,
46
+ body: {
47
+ message: "Not Found"
48
+ }
49
+ };
50
+
51
+ response405 = {
52
+ statusCode: 405,
53
+ headers: headers,
54
+ body: {
55
+ message: "Method Not Allowed"
56
+ }
57
+ };
58
+
59
+ response500 = {
60
+ statusCode: 500,
61
+ headers: headers,
62
+ body: {
63
+ message: "Internal Server Error"
64
+ }
65
+ };
66
+
67
+ /**
68
+ *
69
+ * @param {number|string} statusCode
70
+ * @returns {{statusCode: number, headers: object, body: Array|Object|string}}
71
+ */
72
+ response = function (statusCode) {
73
+ // convert to int
74
+ statusCode = parseInt(statusCode, 10);
75
+
76
+ switch (statusCode) {
77
+ case 200:
78
+ return this.response200;
79
+ case 400:
80
+ return this.response400;
81
+ case 401:
82
+ return this.response401;
83
+ case 403:
84
+ return this.response403;
85
+ case 404:
86
+ return this.response404;
87
+ case 500:
88
+ return this.response500;
89
+ default:
90
+ return this.response500;
91
+ }
92
+ };
93
+
94
+ module.exports = {
95
+ contentType,
96
+ headers,
97
+ json,
98
+ response200,
99
+ response404,
100
+ response500,
101
+ response
102
+ }
@@ -0,0 +1,88 @@
1
+ contentType = "application/rss+xml";
2
+
3
+ headers = {
4
+ "Content-Type": contentType
5
+ };
6
+
7
+ rss = (body) => {
8
+ return `<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0">${body}</rss>`;
9
+ }
10
+
11
+ response200 = {
12
+ statusCode: 200,
13
+ headers: headers,
14
+ body: rss("<hello>Success</hello>")
15
+ };
16
+
17
+ response400 = {
18
+ statusCode: 400,
19
+ headers: headers,
20
+ body: rss("<error>Bad Request</error>")
21
+ };
22
+
23
+ response401 = {
24
+ statusCode: 401,
25
+ headers: headers,
26
+ body: rss("<error>Unauthorized</error>")
27
+ };
28
+
29
+ response403 = {
30
+ statusCode: 403,
31
+ headers: headers,
32
+ body: rss("<error>Forbidden</error>")
33
+ };
34
+
35
+ response404 = {
36
+ statusCode: 404,
37
+ headers: headers,
38
+ body: rss("<error>Not Found</error>")
39
+ };
40
+
41
+ response405 = {
42
+ statusCode: 405,
43
+ headers: headers,
44
+ body: rss("<error>Method Not Allowed</error>")
45
+ };
46
+
47
+ response500 = {
48
+ statusCode: 500,
49
+ headers: headers,
50
+ body: rss("<error>Internal Server Error</error>")
51
+ };
52
+
53
+ /**
54
+ *
55
+ * @param {number|string} statusCode
56
+ * @returns {{statusCode: number, headers: object, body: Array|Object|string}}
57
+ */
58
+ response = function (statusCode) {
59
+ // convert to int
60
+ statusCode = parseInt(statusCode, 10);
61
+
62
+ switch (statusCode) {
63
+ case 200:
64
+ return this.response200;
65
+ case 400:
66
+ return this.response400;
67
+ case 401:
68
+ return this.response401;
69
+ case 403:
70
+ return this.response403;
71
+ case 404:
72
+ return this.response404;
73
+ case 500:
74
+ return this.response500;
75
+ default:
76
+ return this.response500;
77
+ }
78
+ };
79
+
80
+ module.exports = {
81
+ contentType,
82
+ headers,
83
+ rss,
84
+ response200,
85
+ response404,
86
+ response500,
87
+ response
88
+ }