@oino-ts/types 0.0.12 → 0.0.13

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.
@@ -52,15 +52,50 @@ class OINOBenchmark {
52
52
  * Complete benchmark timing
53
53
  *
54
54
  * @param name of the benchmark
55
+ * @param category optional subcategory of the benchmark
55
56
  */
56
- static end(name) {
57
+ static end(name, category) {
57
58
  let result = 0;
58
59
  if (this._benchmarkEnabled[name]) {
60
+ const duration = performance.now() - this._benchmarkStart[name];
59
61
  this._benchmarkCount[name] += 1;
60
- this._benchmarkData[name] += performance.now() - this._benchmarkStart[name];
62
+ this._benchmarkData[name] += duration;
63
+ if (category) {
64
+ const category_name = name + "." + category;
65
+ if (this._benchmarkCount[category_name] == undefined) {
66
+ this._benchmarkCount[category_name] = 0;
67
+ this._benchmarkData[category_name] = 0;
68
+ }
69
+ this._benchmarkCount[category_name] += 1;
70
+ this._benchmarkData[category_name] += duration;
71
+ }
61
72
  result = this._benchmarkData[name] / this._benchmarkCount[name];
62
73
  }
63
74
  return result;
64
75
  }
76
+ /**
77
+ * Get given benchmark data.
78
+ *
79
+ * @param name of the benchmark
80
+ */
81
+ static get(name) {
82
+ if (this._benchmarkEnabled[name]) {
83
+ return this._benchmarkData[name] / this._benchmarkCount[name];
84
+ }
85
+ return -1;
86
+ }
87
+ /**
88
+ * Get all benchmark data.
89
+ *
90
+ */
91
+ static getAll() {
92
+ let result = {};
93
+ for (const name in this._benchmarkData) {
94
+ if (this._benchmarkCount[name] > 0) {
95
+ result[name] = this._benchmarkData[name] / this._benchmarkCount[name];
96
+ }
97
+ }
98
+ return result;
99
+ }
65
100
  }
66
101
  exports.OINOBenchmark = OINOBenchmark;
@@ -8,23 +8,20 @@ const _1 = require(".");
8
8
  class OINOHtmlTemplate {
9
9
  /** HTML template string */
10
10
  template;
11
+ /** Cache modified value for template */
12
+ modified;
11
13
  /** Cache expiration value for template */
12
14
  expires;
13
15
  /**
14
16
  * Creates HTML Response from a key-value-pair.
15
17
  *
16
18
  * @param template template string
17
- * @param expires cache expiration value
18
19
  *
19
20
  */
20
- constructor(template, expires) {
21
+ constructor(template) {
21
22
  this.template = template;
22
- if (expires) {
23
- this.expires = expires;
24
- }
25
- else {
26
- this.expires = -1;
27
- }
23
+ this.modified = 0;
24
+ this.expires = 0;
28
25
  }
29
26
  /**
30
27
  * @returns whether template is empty
@@ -42,6 +39,12 @@ class OINOHtmlTemplate {
42
39
  renderFromKeyValue(key, value) {
43
40
  const html = this.template.replaceAll('###' + key + '###', _1.OINOStr.encode(value, _1.OINOContentType.html));
44
41
  const result = new _1.OINOHttpResult(html);
42
+ if (this.expires >= 1) {
43
+ result.expires = Math.round(this.expires);
44
+ }
45
+ if (this.modified >= 1) {
46
+ result.lastModified = this.modified;
47
+ }
45
48
  return result;
46
49
  }
47
50
  /**
@@ -63,7 +66,10 @@ class OINOHtmlTemplate {
63
66
  html = html.replace(/###[^#]*###/g, "");
64
67
  const result = new _1.OINOHttpResult(html);
65
68
  if (this.expires >= 1) {
66
- result.headers["Expires"] = Math.round(this.expires).toString();
69
+ result.expires = Math.round(this.expires);
70
+ }
71
+ if (this.modified >= 1) {
72
+ result.lastModified = this.modified;
67
73
  }
68
74
  return result;
69
75
  }
@@ -101,6 +107,12 @@ class OINOHtmlTemplate {
101
107
  }
102
108
  html = html.replace(/###[^#]*###/g, "");
103
109
  const http_result = new _1.OINOHttpResult(html);
110
+ if (this.expires >= 1) {
111
+ http_result.expires = Math.round(this.expires);
112
+ }
113
+ if (this.modified >= 1) {
114
+ http_result.lastModified = this.modified;
115
+ }
104
116
  return http_result;
105
117
  }
106
118
  }
@@ -6,6 +6,7 @@
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.OINOHttpResult = exports.OINOResult = void 0;
9
+ const node_crypto_1 = require("node:crypto");
9
10
  const _1 = require(".");
10
11
  /**
11
12
  * OINO API request result object with returned data and/or http status code/message and
@@ -153,25 +154,36 @@ exports.OINOResult = OINOResult;
153
154
  * Specialized result for HTTP responses.
154
155
  */
155
156
  class OINOHttpResult extends OINOResult {
157
+ _etag;
156
158
  /** HTTP body data */
157
159
  body;
158
- /** HTTP header values */
159
- headers;
160
+ /** HTTP cache expiration value */
161
+ expires;
162
+ /** HTTP cache last-modified value */
163
+ lastModified;
160
164
  /**
161
165
  * Constructor for a `OINOHttpResult`
162
166
  *
163
167
  * @param body HTTP body
164
- * @param headers HTTP headers
168
+ *
165
169
  */
166
- constructor(body, headers) {
170
+ constructor(body) {
167
171
  super();
168
172
  this.body = body;
169
- if (headers) {
170
- this.headers = headers;
171
- }
172
- else {
173
- this.headers = {};
173
+ this.expires = 0;
174
+ this.lastModified = 0;
175
+ this._etag = "";
176
+ }
177
+ /**
178
+ * Get the ETag value for the body opportunistically, i.e. don't calculate until requested and reuse value.
179
+ *
180
+ */
181
+ getEtag() {
182
+ if (this._etag == "") {
183
+ const hash = (0, node_crypto_1.createHash)("sha256");
184
+ this._etag = hash.update(this.body).digest("hex");
174
185
  }
186
+ return this._etag;
175
187
  }
176
188
  /**
177
189
  * Get a Response object from the result values.
@@ -179,11 +191,18 @@ class OINOHttpResult extends OINOResult {
179
191
  * @param headers HTTP headers (overrides existing values)
180
192
  */
181
193
  getResponse(headers) {
182
- if (!headers) {
183
- headers = this.headers;
184
- }
185
- headers['Content-Length'] = this.body.length.toString();
186
194
  const result = new Response(this.body, { status: this.statusCode, statusText: this.statusMessage, headers: headers });
195
+ result.headers.set('Content-Length', this.body.length.toString());
196
+ if (this.lastModified > 0) {
197
+ result.headers.set('Last-Modified', new Date(this.lastModified).toUTCString());
198
+ }
199
+ if (this.expires >= 0) {
200
+ result.headers.set('Expires', Math.round(this.expires).toString());
201
+ if (this.expires == 0) {
202
+ result.headers.set('Pragma', 'no-cache');
203
+ }
204
+ }
205
+ result.headers.set("ETag", this.getEtag());
187
206
  return result;
188
207
  }
189
208
  }
@@ -49,14 +49,49 @@ export class OINOBenchmark {
49
49
  * Complete benchmark timing
50
50
  *
51
51
  * @param name of the benchmark
52
+ * @param category optional subcategory of the benchmark
52
53
  */
53
- static end(name) {
54
+ static end(name, category) {
54
55
  let result = 0;
55
56
  if (this._benchmarkEnabled[name]) {
57
+ const duration = performance.now() - this._benchmarkStart[name];
56
58
  this._benchmarkCount[name] += 1;
57
- this._benchmarkData[name] += performance.now() - this._benchmarkStart[name];
59
+ this._benchmarkData[name] += duration;
60
+ if (category) {
61
+ const category_name = name + "." + category;
62
+ if (this._benchmarkCount[category_name] == undefined) {
63
+ this._benchmarkCount[category_name] = 0;
64
+ this._benchmarkData[category_name] = 0;
65
+ }
66
+ this._benchmarkCount[category_name] += 1;
67
+ this._benchmarkData[category_name] += duration;
68
+ }
58
69
  result = this._benchmarkData[name] / this._benchmarkCount[name];
59
70
  }
60
71
  return result;
61
72
  }
73
+ /**
74
+ * Get given benchmark data.
75
+ *
76
+ * @param name of the benchmark
77
+ */
78
+ static get(name) {
79
+ if (this._benchmarkEnabled[name]) {
80
+ return this._benchmarkData[name] / this._benchmarkCount[name];
81
+ }
82
+ return -1;
83
+ }
84
+ /**
85
+ * Get all benchmark data.
86
+ *
87
+ */
88
+ static getAll() {
89
+ let result = {};
90
+ for (const name in this._benchmarkData) {
91
+ if (this._benchmarkCount[name] > 0) {
92
+ result[name] = this._benchmarkData[name] / this._benchmarkCount[name];
93
+ }
94
+ }
95
+ return result;
96
+ }
62
97
  }
@@ -5,23 +5,20 @@ import { OINOStr, OINOContentType, OINOHttpResult, OINO_ERROR_PREFIX, OINO_WARNI
5
5
  export class OINOHtmlTemplate {
6
6
  /** HTML template string */
7
7
  template;
8
+ /** Cache modified value for template */
9
+ modified;
8
10
  /** Cache expiration value for template */
9
11
  expires;
10
12
  /**
11
13
  * Creates HTML Response from a key-value-pair.
12
14
  *
13
15
  * @param template template string
14
- * @param expires cache expiration value
15
16
  *
16
17
  */
17
- constructor(template, expires) {
18
+ constructor(template) {
18
19
  this.template = template;
19
- if (expires) {
20
- this.expires = expires;
21
- }
22
- else {
23
- this.expires = -1;
24
- }
20
+ this.modified = 0;
21
+ this.expires = 0;
25
22
  }
26
23
  /**
27
24
  * @returns whether template is empty
@@ -39,6 +36,12 @@ export class OINOHtmlTemplate {
39
36
  renderFromKeyValue(key, value) {
40
37
  const html = this.template.replaceAll('###' + key + '###', OINOStr.encode(value, OINOContentType.html));
41
38
  const result = new OINOHttpResult(html);
39
+ if (this.expires >= 1) {
40
+ result.expires = Math.round(this.expires);
41
+ }
42
+ if (this.modified >= 1) {
43
+ result.lastModified = this.modified;
44
+ }
42
45
  return result;
43
46
  }
44
47
  /**
@@ -60,7 +63,10 @@ export class OINOHtmlTemplate {
60
63
  html = html.replace(/###[^#]*###/g, "");
61
64
  const result = new OINOHttpResult(html);
62
65
  if (this.expires >= 1) {
63
- result.headers["Expires"] = Math.round(this.expires).toString();
66
+ result.expires = Math.round(this.expires);
67
+ }
68
+ if (this.modified >= 1) {
69
+ result.lastModified = this.modified;
64
70
  }
65
71
  return result;
66
72
  }
@@ -98,6 +104,12 @@ export class OINOHtmlTemplate {
98
104
  }
99
105
  html = html.replace(/###[^#]*###/g, "");
100
106
  const http_result = new OINOHttpResult(html);
107
+ if (this.expires >= 1) {
108
+ http_result.expires = Math.round(this.expires);
109
+ }
110
+ if (this.modified >= 1) {
111
+ http_result.lastModified = this.modified;
112
+ }
101
113
  return http_result;
102
114
  }
103
115
  }
@@ -3,6 +3,7 @@
3
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
4
4
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
+ import { createHash } from "node:crypto";
6
7
  import { OINO_DEBUG_PREFIX, OINO_ERROR_PREFIX, OINO_INFO_PREFIX, OINO_WARNING_PREFIX } from ".";
7
8
  /**
8
9
  * OINO API request result object with returned data and/or http status code/message and
@@ -149,25 +150,36 @@ export class OINOResult {
149
150
  * Specialized result for HTTP responses.
150
151
  */
151
152
  export class OINOHttpResult extends OINOResult {
153
+ _etag;
152
154
  /** HTTP body data */
153
155
  body;
154
- /** HTTP header values */
155
- headers;
156
+ /** HTTP cache expiration value */
157
+ expires;
158
+ /** HTTP cache last-modified value */
159
+ lastModified;
156
160
  /**
157
161
  * Constructor for a `OINOHttpResult`
158
162
  *
159
163
  * @param body HTTP body
160
- * @param headers HTTP headers
164
+ *
161
165
  */
162
- constructor(body, headers) {
166
+ constructor(body) {
163
167
  super();
164
168
  this.body = body;
165
- if (headers) {
166
- this.headers = headers;
167
- }
168
- else {
169
- this.headers = {};
169
+ this.expires = 0;
170
+ this.lastModified = 0;
171
+ this._etag = "";
172
+ }
173
+ /**
174
+ * Get the ETag value for the body opportunistically, i.e. don't calculate until requested and reuse value.
175
+ *
176
+ */
177
+ getEtag() {
178
+ if (this._etag == "") {
179
+ const hash = createHash("sha256");
180
+ this._etag = hash.update(this.body).digest("hex");
170
181
  }
182
+ return this._etag;
171
183
  }
172
184
  /**
173
185
  * Get a Response object from the result values.
@@ -175,11 +187,18 @@ export class OINOHttpResult extends OINOResult {
175
187
  * @param headers HTTP headers (overrides existing values)
176
188
  */
177
189
  getResponse(headers) {
178
- if (!headers) {
179
- headers = this.headers;
180
- }
181
- headers['Content-Length'] = this.body.length.toString();
182
190
  const result = new Response(this.body, { status: this.statusCode, statusText: this.statusMessage, headers: headers });
191
+ result.headers.set('Content-Length', this.body.length.toString());
192
+ if (this.lastModified > 0) {
193
+ result.headers.set('Last-Modified', new Date(this.lastModified).toUTCString());
194
+ }
195
+ if (this.expires >= 0) {
196
+ result.headers.set('Expires', Math.round(this.expires).toString());
197
+ if (this.expires == 0) {
198
+ result.headers.set('Pragma', 'no-cache');
199
+ }
200
+ }
201
+ result.headers.set("ETag", this.getEtag());
183
202
  return result;
184
203
  }
185
204
  }
@@ -28,6 +28,18 @@ export declare class OINOBenchmark {
28
28
  * Complete benchmark timing
29
29
  *
30
30
  * @param name of the benchmark
31
+ * @param category optional subcategory of the benchmark
31
32
  */
32
- static end(name: string): number;
33
+ static end(name: string, category?: string): number;
34
+ /**
35
+ * Get given benchmark data.
36
+ *
37
+ * @param name of the benchmark
38
+ */
39
+ static get(name: string): number;
40
+ /**
41
+ * Get all benchmark data.
42
+ *
43
+ */
44
+ static getAll(): number;
33
45
  }
@@ -5,16 +5,17 @@ import { OINOResult, OINOHttpResult } from ".";
5
5
  export declare class OINOHtmlTemplate {
6
6
  /** HTML template string */
7
7
  template: string;
8
+ /** Cache modified value for template */
9
+ modified: number;
8
10
  /** Cache expiration value for template */
9
11
  expires: number;
10
12
  /**
11
13
  * Creates HTML Response from a key-value-pair.
12
14
  *
13
15
  * @param template template string
14
- * @param expires cache expiration value
15
16
  *
16
17
  */
17
- constructor(template: string, expires?: number);
18
+ constructor(template: string);
18
19
  /**
19
20
  * @returns whether template is empty
20
21
  */
@@ -77,17 +77,25 @@ export declare class OINOResult {
77
77
  * Specialized result for HTTP responses.
78
78
  */
79
79
  export declare class OINOHttpResult extends OINOResult {
80
+ private _etag;
80
81
  /** HTTP body data */
81
- body: string;
82
- /** HTTP header values */
83
- headers: Record<string, string>;
82
+ readonly body: string;
83
+ /** HTTP cache expiration value */
84
+ expires: number;
85
+ /** HTTP cache last-modified value */
86
+ lastModified: number;
84
87
  /**
85
88
  * Constructor for a `OINOHttpResult`
86
89
  *
87
90
  * @param body HTTP body
88
- * @param headers HTTP headers
91
+ *
92
+ */
93
+ constructor(body: string);
94
+ /**
95
+ * Get the ETag value for the body opportunistically, i.e. don't calculate until requested and reuse value.
96
+ *
89
97
  */
90
- constructor(body: string, headers?: Record<string, string>);
98
+ getEtag(): string;
91
99
  /**
92
100
  * Get a Response object from the result values.
93
101
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oino-ts/types",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "OINO TS package for types.",
5
5
  "author": "Matias Kiviniemi (pragmatta)",
6
6
  "license": "MPL-2.0",
@@ -55,14 +55,51 @@ export class OINOBenchmark {
55
55
  * Complete benchmark timing
56
56
  *
57
57
  * @param name of the benchmark
58
+ * @param category optional subcategory of the benchmark
58
59
  */
59
- static end(name:string):number {
60
+ static end(name:string, category?:string):number {
60
61
  let result:number = 0
61
62
  if (this._benchmarkEnabled[name]) {
63
+ const duration = performance.now() - this._benchmarkStart[name]
62
64
  this._benchmarkCount[name] += 1
63
- this._benchmarkData[name] += performance.now() - this._benchmarkStart[name]
65
+ this._benchmarkData[name] += duration
66
+ if (category) {
67
+ const category_name = name + "." + category
68
+ if (this._benchmarkCount[category_name] == undefined) {
69
+ this._benchmarkCount[category_name] = 0
70
+ this._benchmarkData[category_name] = 0
71
+ }
72
+ this._benchmarkCount[category_name] += 1
73
+ this._benchmarkData[category_name] += duration
74
+ }
64
75
  result = this._benchmarkData[name] / this._benchmarkCount[name]
65
76
  }
66
77
  return result
67
78
  }
79
+
80
+ /**
81
+ * Get given benchmark data.
82
+ *
83
+ * @param name of the benchmark
84
+ */
85
+ static get(name:string):number {
86
+ if (this._benchmarkEnabled[name]) {
87
+ return this._benchmarkData[name] / this._benchmarkCount[name]
88
+ }
89
+ return -1
90
+ }
91
+
92
+ /**
93
+ * Get all benchmark data.
94
+ *
95
+ */
96
+ static getAll():number {
97
+ let result:any = {}
98
+ for (const name in this._benchmarkData) {
99
+ if (this._benchmarkCount[name] > 0) {
100
+ result[name] = this._benchmarkData[name] / this._benchmarkCount[name]
101
+ }
102
+ }
103
+ return result
104
+ }
68
105
  }
@@ -7,6 +7,9 @@ export class OINOHtmlTemplate {
7
7
  /** HTML template string */
8
8
  template: string;
9
9
 
10
+ /** Cache modified value for template */
11
+ modified: number;
12
+
10
13
  /** Cache expiration value for template */
11
14
  expires: number;
12
15
 
@@ -14,16 +17,12 @@ export class OINOHtmlTemplate {
14
17
  * Creates HTML Response from a key-value-pair.
15
18
  *
16
19
  * @param template template string
17
- * @param expires cache expiration value
18
20
  *
19
21
  */
20
- constructor (template:string, expires?: number) {
22
+ constructor (template:string) {
21
23
  this.template = template
22
- if (expires) {
23
- this.expires = expires
24
- } else {
25
- this.expires = -1
26
- }
24
+ this.modified = 0
25
+ this.expires = 0
27
26
  }
28
27
 
29
28
  /**
@@ -43,6 +42,12 @@ export class OINOHtmlTemplate {
43
42
  renderFromKeyValue(key:string, value:string):OINOHttpResult {
44
43
  const html:string = this.template.replaceAll('###' + key + '###', OINOStr.encode(value, OINOContentType.html))
45
44
  const result:OINOHttpResult = new OINOHttpResult(html)
45
+ if (this.expires >= 1) {
46
+ result.expires = Math.round(this.expires)
47
+ }
48
+ if (this.modified >= 1) {
49
+ result.lastModified = this.modified
50
+ }
46
51
  return result
47
52
  }
48
53
 
@@ -65,7 +70,10 @@ export class OINOHtmlTemplate {
65
70
  html = html.replace(/###[^#]*###/g, "")
66
71
  const result:OINOHttpResult = new OINOHttpResult(html)
67
72
  if (this.expires >= 1) {
68
- result.headers["Expires"] = Math.round(this.expires).toString()
73
+ result.expires = Math.round(this.expires)
74
+ }
75
+ if (this.modified >= 1) {
76
+ result.lastModified = this.modified
69
77
  }
70
78
  return result
71
79
  }
@@ -105,6 +113,12 @@ export class OINOHtmlTemplate {
105
113
  }
106
114
  html = html.replace(/###[^#]*###/g, "")
107
115
  const http_result:OINOHttpResult = new OINOHttpResult(html)
116
+ if (this.expires >= 1) {
117
+ http_result.expires = Math.round(this.expires)
118
+ }
119
+ if (this.modified >= 1) {
120
+ http_result.lastModified = this.modified
121
+ }
108
122
  return http_result
109
123
  }
110
124
  };
package/src/OINOResult.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
6
 
7
+ import { createHash, Hash } from "node:crypto";
7
8
  import { OINO_DEBUG_PREFIX, OINO_ERROR_PREFIX, OINO_INFO_PREFIX, OINO_WARNING_PREFIX } from ".";
8
9
 
9
10
  /**
@@ -162,26 +163,41 @@ export class OINOResult {
162
163
  * Specialized result for HTTP responses.
163
164
  */
164
165
  export class OINOHttpResult extends OINOResult {
166
+ private _etag:string
167
+
165
168
  /** HTTP body data */
166
- body: string
169
+ readonly body: string
170
+
171
+ /** HTTP cache expiration value */
172
+ expires: number
167
173
 
168
- /** HTTP header values */
169
- headers: Record<string, string>
174
+ /** HTTP cache last-modified value */
175
+ lastModified: number
170
176
 
171
177
  /**
172
178
  * Constructor for a `OINOHttpResult`
173
179
  *
174
180
  * @param body HTTP body
175
- * @param headers HTTP headers
181
+ *
176
182
  */
177
- constructor(body:string, headers?:Record<string, string>) {
183
+ constructor(body:string) {
178
184
  super()
179
185
  this.body = body
180
- if (headers) {
181
- this.headers = headers
182
- } else {
183
- this.headers = {}
186
+ this.expires = 0
187
+ this.lastModified = 0
188
+ this._etag = ""
189
+ }
190
+
191
+ /**
192
+ * Get the ETag value for the body opportunistically, i.e. don't calculate until requested and reuse value.
193
+ *
194
+ */
195
+ getEtag():string {
196
+ if (this._etag == "") {
197
+ const hash:Hash = createHash("sha256")
198
+ this._etag = hash.update(this.body).digest("hex")
184
199
  }
200
+ return this._etag
185
201
  }
186
202
 
187
203
  /**
@@ -190,11 +206,18 @@ export class OINOHttpResult extends OINOResult {
190
206
  * @param headers HTTP headers (overrides existing values)
191
207
  */
192
208
  getResponse(headers?:Record<string, string>):Response {
193
- if (!headers) {
194
- headers = this.headers
209
+ const result:Response = new Response(this.body, {status:this.statusCode, statusText: this.statusMessage, headers: headers})
210
+ result.headers.set('Content-Length', this.body.length.toString())
211
+ if (this.lastModified > 0) {
212
+ result.headers.set('Last-Modified', new Date(this.lastModified).toUTCString())
213
+ }
214
+ if (this.expires >= 0) {
215
+ result.headers.set('Expires', Math.round(this.expires).toString())
216
+ if (this.expires == 0) {
217
+ result.headers.set('Pragma', 'no-cache')
218
+ }
195
219
  }
196
- headers['Content-Length'] = this.body.length.toString()
197
- const result = new Response(this.body, {status:this.statusCode, statusText: this.statusMessage, headers: headers})
220
+ result.headers.set("ETag", this.getEtag())
198
221
  return result
199
222
  }
200
223