@oino-ts/types 0.0.18 → 0.1.1

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.
Files changed (53) hide show
  1. package/{dist/types → common/src}/index.d.ts +0 -1
  2. package/db/src/OINODb.d.ts +180 -0
  3. package/db/src/OINODbApi.d.ts +82 -0
  4. package/db/src/OINODbConfig.d.ts +52 -0
  5. package/db/src/OINODbDataField.d.ts +202 -0
  6. package/db/src/OINODbDataModel.d.ts +108 -0
  7. package/db/src/OINODbDataSet.d.ts +95 -0
  8. package/db/src/OINODbFactory.d.ts +35 -0
  9. package/db/src/OINODbModelSet.d.ts +51 -0
  10. package/{dist/types/OINOParser.d.ts → db/src/OINODbParser.d.ts} +3 -3
  11. package/db/src/OINODbRequestParams.d.ts +146 -0
  12. package/db/src/OINODbSqlParams.d.ts +147 -0
  13. package/db/src/OINODbSwagger.d.ts +25 -0
  14. package/db/src/index.d.ts +111 -0
  15. package/db-bunsqlite/src/OINODbBunSqlite.d.ts +77 -0
  16. package/db-bunsqlite/src/index.d.ts +1 -0
  17. package/db-mariadb/src/OINODbMariadb.d.ts +78 -0
  18. package/db-mariadb/src/index.d.ts +1 -0
  19. package/db-mssql/src/OINODbMsSql.d.ts +86 -0
  20. package/db-mssql/src/index.d.ts +1 -0
  21. package/db-postgresql/src/OINODbPostgresql.d.ts +76 -0
  22. package/db-postgresql/src/index.d.ts +1 -0
  23. package/hashid/src/OINOHashid.d.ts +40 -0
  24. package/hashid/src/index.d.ts +1 -0
  25. package/index.d.ts +23 -0
  26. package/package.json +5 -8
  27. package/README.md +0 -190
  28. package/dist/cjs/OINOBenchmark.js +0 -108
  29. package/dist/cjs/OINOHtmlTemplate.js +0 -177
  30. package/dist/cjs/OINOLog.js +0 -151
  31. package/dist/cjs/OINOParser.js +0 -466
  32. package/dist/cjs/OINOResult.js +0 -216
  33. package/dist/cjs/OINOStr.js +0 -265
  34. package/dist/cjs/index.js +0 -42
  35. package/dist/esm/OINOBenchmark.js +0 -104
  36. package/dist/esm/OINOHtmlTemplate.js +0 -173
  37. package/dist/esm/OINOLog.js +0 -146
  38. package/dist/esm/OINOParser.js +0 -462
  39. package/dist/esm/OINOResult.js +0 -211
  40. package/dist/esm/OINOStr.js +0 -261
  41. package/dist/esm/index.js +0 -30
  42. package/src/OINOBenchmark.ts +0 -112
  43. package/src/OINOHtmlTemplate.ts +0 -186
  44. package/src/OINOLog.ts +0 -168
  45. package/src/OINOParser.ts +0 -458
  46. package/src/OINOResult.ts +0 -234
  47. package/src/OINOStr.ts +0 -254
  48. package/src/index.ts +0 -32
  49. /package/{dist/types → common/src}/OINOBenchmark.d.ts +0 -0
  50. /package/{dist/types → common/src}/OINOHtmlTemplate.d.ts +0 -0
  51. /package/{dist/types → common/src}/OINOLog.d.ts +0 -0
  52. /package/{dist/types → common/src}/OINOResult.d.ts +0 -0
  53. /package/{dist/types → common/src}/OINOStr.d.ts +0 -0
package/src/OINOParser.ts DELETED
@@ -1,458 +0,0 @@
1
- /*
2
- * This Source Code Form is subject to the terms of the Mozilla Public
3
- * License, v. 2.0. If a copy of the MPL was not distributed with this
4
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
- */
6
-
7
- import { OINOContentType, OINODbDataModel, OINODbDataField, OINODataRow, OINODbApiRequestParams, OINOStr, OINONumberDataField, OINOLog } from "../../db/src/index.js"
8
-
9
- /**
10
- * Static factory class for easily creating things based on data
11
- *
12
- */
13
- export class OINOParser {
14
- /**
15
- * Create data rows from request body based on the datamodel.
16
- *
17
- * @param datamodel datamodel of the api
18
- * @param data data as a string
19
- * @param requestParams parameters
20
- *
21
- */
22
- static createRows(datamodel:OINODbDataModel, data:string|Buffer|object, requestParams:OINODbApiRequestParams ):OINODataRow[] {
23
- let result:OINODataRow[] = []
24
- if (typeof data == "string") {
25
- result = this.createRowsFromText(datamodel, data, requestParams)
26
-
27
- } else if (data instanceof Buffer) {
28
- result = this.createRowsFromBlob(datamodel, data, requestParams)
29
-
30
- } else if (typeof data == "object") {
31
- result = [this.createRowFromObject(datamodel, data)]
32
- }
33
- return result
34
- }
35
-
36
- /**
37
- * Create data rows from request body based on the datamodel.
38
- *
39
- * @param datamodel datamodel of the api
40
- * @param data data as a string
41
- * @param requestParams parameters
42
- *
43
- */
44
- static createRowsFromText(datamodel:OINODbDataModel, data:string, requestParams:OINODbApiRequestParams ):OINODataRow[] {
45
- if ((requestParams.requestType == OINOContentType.json) || (requestParams.requestType == undefined)) {
46
- return this._createRowFromJson(datamodel, data)
47
-
48
- } else if (requestParams.requestType == OINOContentType.csv) {
49
- return this._createRowFromCsv(datamodel, data)
50
-
51
- } else if (requestParams.requestType == OINOContentType.formdata) {
52
- return this._createRowFromFormdata(datamodel, Buffer.from(data, "utf8"), requestParams.multipartBoundary || "")
53
-
54
- } else if (requestParams.requestType == OINOContentType.urlencode) {
55
- return this._createRowFromUrlencoded(datamodel, data)
56
-
57
- } else if (requestParams.requestType == OINOContentType.html) {
58
- OINOLog.error("HTML can't be used as an input content type!", {contentType:OINOContentType.html})
59
- return []
60
- } else {
61
- OINOLog.error("Unrecognized input content type!", {contentType:requestParams.requestType})
62
- return []
63
- }
64
- }
65
- /**
66
- * Create data rows from request body based on the datamodel.
67
- *
68
- * @param datamodel datamodel of the api
69
- * @param data data as an Buffer
70
- * @param requestParams parameters
71
- *
72
- */
73
- static createRowsFromBlob(datamodel:OINODbDataModel, data:Buffer, requestParams:OINODbApiRequestParams ):OINODataRow[] {
74
- if ((requestParams.requestType == OINOContentType.json) || (requestParams.requestType == undefined)) {
75
- return this._createRowFromJson(datamodel, data.toString()) // JSON is always a string
76
-
77
- } else if (requestParams.requestType == OINOContentType.csv) {
78
- return this._createRowFromCsv(datamodel, data.toString()) // binary data has to be base64 encoded so it's a string
79
-
80
- } else if (requestParams.requestType == OINOContentType.formdata) {
81
- return this._createRowFromFormdata(datamodel, data, requestParams.multipartBoundary || "")
82
-
83
- } else if (requestParams.requestType == OINOContentType.urlencode) {
84
- return this._createRowFromUrlencoded(datamodel, data.toString()) // data is urlencoded so it's a string
85
-
86
- } else if (requestParams.requestType == OINOContentType.html) {
87
- OINOLog.error("HTML can't be used as an input content type!", {contentType:OINOContentType.html})
88
- return []
89
- } else {
90
- OINOLog.error("Unrecognized input content type!", {contentType:requestParams.requestType})
91
- return []
92
- }
93
- }
94
-
95
- /**
96
- * Create one data row from javascript object based on the datamodel.
97
- * NOTE! Data assumed to be unserialized i.e. of the native type (string, number, boolean, Buffer)
98
- *
99
- * @param datamodel datamodel of the api
100
- * @param data data as javascript object
101
- *
102
- */
103
- static createRowFromObject(datamodel:OINODbDataModel, data:any):OINODataRow {
104
- const fields:OINODbDataField[] = datamodel.fields
105
- let result:OINODataRow = new Array(fields.length)
106
- for (let i=0; i < fields.length; i++) {
107
- result[i] = data[fields[i].name]
108
- }
109
- return result
110
- }
111
-
112
- private static _findCsvLineEnd(csvData:string, start:number):number {
113
- const n:number = csvData.length
114
- if (start >= n) {
115
- return start
116
- }
117
- let end:number = start
118
- let quote_open:boolean = false
119
- while (end<n) {
120
- if (csvData[end] == "\"") {
121
- if (!quote_open) {
122
- quote_open = true
123
- } else if ((end < n-1) && (csvData[end+1] == "\"")) {
124
- end++
125
- } else {
126
- quote_open = false
127
- }
128
- } else if ((!quote_open) && (csvData[end] == "\r")) {
129
- return end
130
- }
131
- end++
132
- }
133
- return n
134
- }
135
-
136
- private static _parseCsvLine(csvLine:string):(string|null|undefined)[] {
137
- let result:(string|null|undefined)[] = []
138
- const n:number = csvLine.length
139
- let start:number = 0
140
- let end:number = 0
141
- let quote_open:boolean = false
142
- let has_quotes:boolean = false
143
- let has_escaped_quotes = false
144
- let found_field = false
145
- while (end<n) {
146
- if (csvLine[end] == "\"") {
147
- if (!quote_open) {
148
- quote_open = true
149
- } else if ((end < n-1) && (csvLine[end+1] == "\"")) {
150
- end++
151
- has_escaped_quotes = true
152
- } else {
153
- has_quotes = true
154
- quote_open = false
155
- }
156
- }
157
- if ((!quote_open) && ((end == n-1) || (csvLine[end] == ","))) {
158
- found_field = true
159
- if (end == n-1) {
160
- end++
161
- }
162
- }
163
- if (found_field) {
164
- // console.log("OINODB_csvParseLine: next field=" + csvLine.substring(start,end) + ", start="+start+", end="+end)
165
- let field_str:string|undefined|null
166
- if (has_quotes) {
167
- field_str = csvLine.substring(start+1,end-1)
168
- } else if (start == end) {
169
- field_str = undefined
170
- } else {
171
- field_str = csvLine.substring(start,end)
172
- if (field_str == "null") {
173
- field_str = null
174
- }
175
- }
176
- result.push(field_str)
177
- has_quotes = false
178
- has_escaped_quotes = true
179
- found_field = false
180
- start = end+1
181
- }
182
- end++
183
- }
184
- return result
185
- }
186
-
187
- private static _createRowFromCsv(datamodel:OINODbDataModel, data:string):OINODataRow[] {
188
- let result:OINODataRow[] = []
189
- const n = data.length
190
- let start:number = 0
191
- let end:number = this._findCsvLineEnd(data, start)
192
- const header_str = data.substring(start, end)
193
- const headers:(string|null|undefined)[] = this._parseCsvLine(header_str)
194
- let field_to_header_mapping:number[] = new Array(datamodel.fields.length)
195
- let headers_found:boolean = false
196
- for (let i=0; i<field_to_header_mapping.length; i++) {
197
- field_to_header_mapping[i] = headers.indexOf(datamodel.fields[i].name)
198
- headers_found = headers_found || (field_to_header_mapping[i] >= 0)
199
- }
200
- // OINOLog.debug("createRowFromCsv", {headers:headers, field_to_header_mapping:field_to_header_mapping})
201
- if (!headers_found) {
202
- return result
203
- }
204
- start = end + 1
205
- end = start
206
- while (end < n) {
207
- while ((start < n) && ((data[start] == "\r") || (data[start] == "\n"))) {
208
- start++
209
- }
210
- if (start >= n) {
211
- return result
212
- }
213
- end = this._findCsvLineEnd(data, start)
214
- const row_data:(string|null|undefined)[] = this._parseCsvLine(data.substring(start, end))
215
- const row:OINODataRow = new Array(field_to_header_mapping.length)
216
- let has_data:boolean = false
217
- for (let i=0; i<datamodel.fields.length; i++) {
218
- const field:OINODbDataField = datamodel.fields[i]
219
- let j:number = field_to_header_mapping[i]
220
- let value:string|null|undefined = row_data[j]
221
- if ((value === undefined) || (value === null)) { // null/undefined-decoding built into the parser
222
- row[i] = value
223
-
224
- } else if ((j >= 0) && (j < row_data.length)) {
225
- value = OINOStr.decode(value, OINOContentType.csv)
226
- if (value && (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) && (field instanceof OINONumberDataField) && (datamodel.api.hashid)) {
227
- value = datamodel.api.hashid.decode(value)
228
- }
229
- row[i] = field.deserializeCell(value)
230
-
231
- } else {
232
- row[i] = undefined
233
- }
234
- has_data = has_data || (row[i] !== undefined)
235
- }
236
- // console.log("createRowFromCsv: next row=" + row)
237
- if (has_data) {
238
- result.push(row)
239
- } else {
240
- OINOLog.warning("createRowFromCsv: empty row skipped")
241
- }
242
- start = end
243
- end = start
244
- }
245
-
246
- return result
247
- }
248
-
249
- private static _createRowFromJsonObj(obj:any, datamodel:OINODbDataModel):OINODataRow|undefined {
250
- // console.log("createRowFromJsonObj: obj=" + JSON.stringify(obj))
251
- const fields:OINODbDataField[] = datamodel.fields
252
- let result:OINODataRow = new Array(fields.length)
253
- let has_data:boolean = false
254
- // console.log("createRowFromJsonObj: " + result)
255
- for (let i=0; i < fields.length; i++) {
256
- const field = fields[i]
257
- let value:any = obj[field.name]
258
- // console.log("createRowFromJsonObj: key=" + field.name + ", val=" + val)
259
- if ((value === null) || (value === undefined)) { // must be checed first as null is an object
260
- result[i] = value
261
-
262
- } else if (Array.isArray(value) || typeof value === "object") {
263
- result[i] = JSON.stringify(value).replaceAll("\"","\\\"") // only single level deep objects, rest is handled as JSON-strings
264
-
265
- } else if (typeof value === "string") {
266
- value = OINOStr.decode(value, OINOContentType.json)
267
- if (value && (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) && (field instanceof OINONumberDataField) && (datamodel.api.hashid)) {
268
- value = datamodel.api.hashid.decode(value)
269
- }
270
- result[i] = field.deserializeCell(value)
271
-
272
- } else {
273
- result[i] = value // value types are passed as-is
274
- }
275
- has_data = has_data || (result[i] !== undefined)
276
- // console.log("createRowFromJsonObj: result["+i+"]=" + result[i])
277
- }
278
- // console.log("createRowFromJsonObj: " + result)
279
- if (has_data) {
280
- return result
281
- } else {
282
- OINOLog.warning("createRowFromJsonObj: empty row skipped")
283
- return undefined
284
- }
285
- }
286
-
287
- private static _createRowFromJson(datamodel:OINODbDataModel, data:string):OINODataRow[] {
288
- let result:OINODataRow[] = []
289
- // console.log("OINORowFactoryJson: data=" + data)
290
- const obj:object = JSON.parse(data)
291
- if (Array.isArray(obj)) {
292
- obj.forEach(row => {
293
- const data_row = this._createRowFromJsonObj(row, datamodel)
294
- if (data_row !== undefined) {
295
- result.push(data_row)
296
- }
297
- })
298
-
299
- } else {
300
- const data_row = this._createRowFromJsonObj(obj, datamodel)
301
- if (data_row !== undefined) {
302
- result.push(data_row)
303
- }
304
- }
305
- return result
306
- }
307
-
308
- private static _findMultipartBoundary(formData:Buffer, multipartBoundary:string, start:number):number {
309
- let n:number = formData.indexOf(multipartBoundary, start)
310
- if (n >= 0) {
311
- n += multipartBoundary.length + 2
312
- } else {
313
- n = formData.length
314
- }
315
- return n
316
- }
317
-
318
- private static _parseMultipartLine(data:Buffer, start:number):string {
319
- let line_end:number = data.indexOf('\r\n', start)
320
- if (line_end >= start) {
321
- return data.subarray(start, line_end).toString()
322
- } else {
323
- return ''
324
- }
325
- }
326
-
327
- private static _multipartHeaderRegex:RegExp = /Content-Disposition\: (form-data|file); name=\"([^\"]+)\"(; filename=.*)?/i
328
-
329
- private static _createRowFromFormdata(datamodel:OINODbDataModel, data:Buffer, multipartBoundary:string):OINODataRow[] {
330
- let result:OINODataRow[] = []
331
- try {
332
- const n = data.length
333
- let start:number = this._findMultipartBoundary(data, multipartBoundary, 0)
334
- let end:number = this._findMultipartBoundary(data, multipartBoundary, start)
335
- // OINOLog.debug("createRowFromFormdata: enter", {start:start, end:end, multipartBoundary:multipartBoundary})
336
- const row:OINODataRow = new Array(datamodel.fields.length)
337
- let has_data:boolean = false
338
- while (end < n) {
339
- // OINOLog.debug("createRowFromFormdata: next block", {start:start, end:end, block:data.substring(start, end)})
340
- let block_ok:boolean = true
341
- let l:string = this._parseMultipartLine(data, start)
342
- // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
343
- start += l.length+2
344
- const header_matches = OINOParser._multipartHeaderRegex.exec(l)
345
- if (!header_matches) {
346
- OINOLog.warning("OINODbFactory.createRowFromFormdata: unsupported block skipped!", {header_line:l})
347
- block_ok = false
348
-
349
- } else {
350
- const field_name = header_matches[2]
351
- const is_file = header_matches[3] != null
352
- let is_base64:boolean = false
353
- const field_index:number = datamodel.findFieldIndexByName(field_name)
354
- // OINOLog.debug("createRowFromFormdata: header", {field_name:field_name, field_index:field_index, is_file:is_file, is_base64:is_base64})
355
- if (field_index < 0) {
356
- OINOLog.warning("OINODbFactory.createRowFromFormdata: form field not found and skipped!", {field_name:field_name})
357
- block_ok = false
358
-
359
- } else {
360
- const field:OINODbDataField = datamodel.fields[field_index]
361
- l = this._parseMultipartLine(data, start)
362
- // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
363
- while (block_ok && (l != '')) {
364
- if (l.startsWith('Content-Type:') && (l.indexOf('multipart/mixed')>=0)) {
365
- OINOLog.warning("OINODbFactory.createRowFromFormdata: mixed multipart files not supported and skipped!", {header_line:l})
366
- block_ok = false
367
- } else if (l.startsWith('Content-Transfer-Encoding:') && (l.indexOf('BASE64')>=0)) {
368
- is_base64 = true
369
- }
370
- start += l.length+2
371
- l = this._parseMultipartLine(data, start)
372
- // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
373
- }
374
- start += 2
375
- if (!block_ok) {
376
- OINOLog.warning("OINODbFactory.createRowFromFormdata: invalid block skipped", {field_name:field_name})
377
- } else if (start + multipartBoundary.length + 2 >= end) {
378
- // OINOLog.debug("OINODbFactory.createRowFromFormdata: null value", {field_name:field_name})
379
- row[field_index] = null
380
-
381
- } else if (is_file) {
382
- if (is_base64) {
383
- const value = this._parseMultipartLine(data, start).trim()
384
- row[field_index] = field.deserializeCell(OINOStr.decode(value, OINOContentType.formdata))
385
- } else {
386
- const e = this._findMultipartBoundary(data, multipartBoundary, start)
387
- const value = data.subarray(start, e-2)
388
- row[field_index] = value
389
- }
390
- // console.log("OINODbFactory.createRowFromFormdata: file field", {field_name:field_name, value:row[field_index]})
391
- } else {
392
- let value:string = OINOStr.decode(this._parseMultipartLine(data, start).trim(), OINOContentType.formdata)
393
- // OINOLog.debug("OINODbFactory.createRowFromFormdata: parse form field", {field_name:field_name, value:value})
394
- if (value && (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) && (field instanceof OINONumberDataField) && (datamodel.api.hashid)) {
395
- value = datamodel.api.hashid.decode(value)
396
- }
397
- row[field_index] = field.deserializeCell(value)
398
- }
399
- has_data = has_data || (row[field_index] !== undefined)
400
- }
401
- }
402
- start = end
403
- end = this._findMultipartBoundary(data, multipartBoundary, start)
404
- }
405
- // OINOLog.debug("createRowFromFormdata: next row", {row:row})
406
- if (has_data) {
407
- result.push(row)
408
- } else {
409
- OINOLog.warning("createRowFromFormdata: empty row skipped")
410
- }
411
- } catch (e:any) {
412
- OINOLog.error("createRowFromFormdata: error parsing formdata", {exception:e.message})
413
- }
414
- return result
415
- }
416
- private static _createRowFromUrlencoded(datamodel:OINODbDataModel, data:string):OINODataRow[] {
417
- // OINOLog.debug("createRowFromUrlencoded: enter", {data:data})
418
- let result:OINODataRow[] = []
419
- const row:OINODataRow = new Array(datamodel.fields.length)
420
- let has_data:boolean = false
421
- const data_parts:string[] = data.trim().split('&')
422
- try {
423
- for (let i=0; i<data_parts.length; i++) {
424
- const param_parts = data_parts[i].split('=')
425
- // OINOLog.debug("createRowFromUrlencoded: next param", {param_parts:param_parts})
426
- if (param_parts.length == 2) {
427
- const key=OINOStr.decodeUrlencode(param_parts[0]) || ""
428
- const field_index:number = datamodel.findFieldIndexByName(key)
429
- if (field_index < 0) {
430
- OINOLog.info("createRowFromUrlencoded: param field not found", {field:key})
431
-
432
- } else {
433
- const field:OINODbDataField = datamodel.fields[field_index]
434
- let value:string=OINOStr.decode(param_parts[1], OINOContentType.urlencode)
435
- if (value && (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) && (field instanceof OINONumberDataField) && (datamodel.api.hashid)) {
436
- value = datamodel.api.hashid.decode(value)
437
- }
438
- row[field_index] = field.deserializeCell(value)
439
- has_data = has_data || (row[field_index] !== undefined)
440
- }
441
- }
442
-
443
- // const value = requestParams[]
444
-
445
- }
446
- if (has_data) {
447
- result.push(row)
448
- } else {
449
- OINOLog.warning("createRowFromUrlencoded: empty row skipped")
450
- }
451
- } catch (e:any) {
452
- OINOLog.error("createRowFromUrlencoded: error parsing urlencoded data", {exception:e.message})
453
- }
454
- // console.log("createRowFromUrlencoded: next row=" + row)
455
- return result
456
- }
457
-
458
- }
package/src/OINOResult.ts DELETED
@@ -1,234 +0,0 @@
1
- /*
2
- * This Source Code Form is subject to the terms of the Mozilla Public
3
- * License, v. 2.0. If a copy of the MPL was not distributed with this
4
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
- */
6
-
7
- import { createHash, Hash } from "node:crypto";
8
- import { OINO_DEBUG_PREFIX, OINO_ERROR_PREFIX, OINO_INFO_PREFIX, OINO_WARNING_PREFIX } from ".";
9
-
10
- /**
11
- * OINO API request result object with returned data and/or http status code/message and
12
- * error / warning messages.
13
- *
14
- */
15
- export class OINOResult {
16
- /** Wheter request was successfully executed */
17
- success: boolean
18
-
19
- /** HTTP status code */
20
- statusCode: number;
21
-
22
- /** HTTP status message */
23
- statusMessage: string;
24
-
25
- /** Error / warning messages */
26
- messages: string[];
27
-
28
- /**
29
- * Constructor of OINOResult.
30
- *
31
- */
32
- constructor () {
33
- this.success = true
34
- this.statusCode = 200
35
- this.statusMessage = "OK"
36
- this.messages = []
37
- }
38
-
39
- /**
40
- * Copy values from different result.
41
- *
42
- * @param result source value
43
- */
44
- copy(result: OINOResult) {
45
- this.success = result.success
46
- this.statusCode = result.statusCode
47
- this.statusMessage = result.statusMessage
48
- this.messages = result.messages.slice()
49
- }
50
-
51
- /**
52
- * Set HTTP OK status (does not reset messages).
53
- *
54
- */
55
- setOk() {
56
- this.success = true
57
- this.statusCode = 200
58
- this.statusMessage = "OK"
59
- }
60
-
61
- /**
62
- * Set HTTP error status using given code and message. Returns self reference for chaining.
63
- *
64
- * @param statusCode HTTP status code
65
- * @param statusMessage HTTP status message
66
- * @param operation operation where error occured
67
- *
68
- */
69
- setError(statusCode:number, statusMessage:string, operation:string):OINOResult {
70
- this.success = false
71
- this.statusCode = statusCode
72
- if (this.statusMessage != "OK") {
73
- this.messages.push(this.statusMessage) // latest error becomes status, but if there was something non-trivial, add it to the messages
74
- }
75
- if (statusMessage.startsWith(OINO_ERROR_PREFIX)) {
76
- this.statusMessage = statusMessage
77
- } else {
78
- this.statusMessage = OINO_ERROR_PREFIX + " (" + operation + "): " + statusMessage
79
- }
80
- return this
81
- }
82
-
83
- /**
84
- * Add warning message. Returns self reference for chaining.
85
- *
86
- * @param message HTTP status message
87
- * @param operation operation where warning occured
88
- *
89
- */
90
- addWarning(message:string, operation:string):OINOResult {
91
- message = message.trim()
92
- if (message) {
93
- this.messages.push(OINO_WARNING_PREFIX + " (" + operation + "): " + message)
94
- }
95
- return this
96
- }
97
-
98
- /**
99
- * Add info message. Returns self reference for chaining.
100
- *
101
- * @param message HTTP status message
102
- * @param operation operation where info occured
103
- *
104
- */
105
- addInfo(message:string, operation:string):OINOResult {
106
- message = message.trim()
107
- if (message) {
108
- this.messages.push(OINO_INFO_PREFIX + " (" + operation + "): " + message)
109
- }
110
- return this
111
- }
112
-
113
- /**
114
- * Add debug message. Returns self reference for chaining.
115
- *
116
- * @param message HTTP status message
117
- * @param operation operation where debug occured
118
- *
119
- */
120
- addDebug(message:string, operation:string):OINOResult {
121
- message = message.trim()
122
- if (message) {
123
- this.messages.push(OINO_DEBUG_PREFIX + " (" + operation + "): " + message)
124
- }
125
- return this
126
- }
127
-
128
- /**
129
- * Copy given messages to HTTP headers.
130
- *
131
- * @param headers HTTP headers
132
- * @param copyErrors wether error messages should be copied (default true)
133
- * @param copyWarnings wether warning messages should be copied (default false)
134
- * @param copyInfos wether info messages should be copied (default false)
135
- * @param copyDebug wether debug messages should be copied (default false)
136
- *
137
- */
138
- copyMessagesToHeaders(headers:Headers, copyErrors:boolean = true, copyWarnings:boolean = false, copyInfos:boolean = false, copyDebug:boolean = false) {
139
- let j=1
140
- for(let i=0; i<this.messages.length; i++) {
141
- const message = this.messages[i].replaceAll("\r", " ").replaceAll("\n", " ")
142
- if (copyErrors && message.startsWith(OINO_ERROR_PREFIX)) {
143
- headers.append('X-OINO-MESSAGE-'+j, message)
144
- j++
145
- }
146
- if (copyWarnings && message.startsWith(OINO_WARNING_PREFIX)) {
147
- headers.append('X-OINO-MESSAGE-'+j, message)
148
- j++
149
- }
150
- if (copyInfos && message.startsWith(OINO_INFO_PREFIX)) {
151
- headers.append('X-OINO-MESSAGE-'+j, message)
152
- j++
153
- }
154
- if (copyDebug && message.startsWith(OINO_DEBUG_PREFIX)) {
155
- headers.append('X-OINO-MESSAGE-'+j, message)
156
- j++
157
- }
158
- }
159
- }
160
-
161
- /**
162
- * Print result for logging.
163
- *
164
- */
165
- printLog() {
166
- return "OINOResult: statusCode=" + this.statusCode + ", statusMessage=" + this.statusMessage + ", messages=[" + this.messages.join(", ") + "]"
167
- }
168
- }
169
-
170
- /**
171
- * Specialized result for HTTP responses.
172
- */
173
- export class OINOHttpResult extends OINOResult {
174
- private _etag:string
175
-
176
- /** HTTP body data */
177
- readonly body: string
178
-
179
- /** HTTP cache expiration value */
180
- expires: number
181
-
182
- /** HTTP cache last-modified value */
183
- lastModified: number
184
-
185
- /**
186
- * Constructor for a `OINOHttpResult`
187
- *
188
- * @param body HTTP body
189
- *
190
- */
191
- constructor(body:string) {
192
- super()
193
- this.body = body
194
- this.expires = 0
195
- this.lastModified = 0
196
- this._etag = ""
197
- }
198
-
199
- /**
200
- * Get the ETag value for the body opportunistically, i.e. don't calculate until requested and reuse value.
201
- *
202
- */
203
- getEtag():string {
204
- if (this._etag == "") {
205
- const hash:Hash = createHash("sha256")
206
- this._etag = hash.update(this.body).digest("hex")
207
- }
208
- return this._etag
209
- }
210
-
211
- /**
212
- * Get a Response object from the result values.
213
- *
214
- * @param headers HTTP headers (overrides existing values)
215
- */
216
- getResponse(headers?:Record<string, string>):Response {
217
- const result:Response = new Response(this.body, {status:this.statusCode, statusText: this.statusMessage, headers: headers})
218
- result.headers.set('Content-Length', this.body.length.toString())
219
- if (this.lastModified > 0) {
220
- result.headers.set('Last-Modified', new Date(this.lastModified).toUTCString())
221
- }
222
- if (this.expires >= 0) {
223
- result.headers.set('Expires', Math.round(this.expires).toString())
224
- if (this.expires == 0) {
225
- result.headers.set('Pragma', 'no-cache')
226
- }
227
- }
228
- result.headers.set("ETag", this.getEtag())
229
- return result
230
- }
231
-
232
-
233
-
234
- }