@oino-ts/common 0.21.1 → 1.0.0

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 (72) hide show
  1. package/README.md +183 -0
  2. package/dist/cjs/OINOApi.js +322 -0
  3. package/dist/cjs/OINOBenchmark.js +3 -4
  4. package/dist/cjs/OINOConfig.js +104 -0
  5. package/dist/cjs/OINOConstants.js +42 -0
  6. package/dist/cjs/OINODataField.js +346 -0
  7. package/dist/cjs/OINODataModel.js +182 -0
  8. package/dist/cjs/OINODataSource.js +165 -0
  9. package/dist/cjs/OINOFormatter.js +6 -5
  10. package/dist/cjs/OINOHtmlTemplate.js +21 -18
  11. package/dist/cjs/OINOModelSet.js +333 -0
  12. package/dist/cjs/OINOParser.js +448 -0
  13. package/dist/cjs/OINOQueryParams.js +434 -0
  14. package/dist/cjs/OINORequest.js +21 -13
  15. package/dist/cjs/OINOResult.js +13 -12
  16. package/dist/cjs/OINOStr.js +11 -11
  17. package/dist/cjs/OINOSwagger.js +205 -0
  18. package/dist/cjs/index.js +57 -39
  19. package/dist/esm/OINOApi.js +315 -0
  20. package/dist/esm/OINOBenchmark.js +3 -4
  21. package/dist/esm/OINOConfig.js +100 -0
  22. package/dist/esm/OINOConstants.js +39 -0
  23. package/dist/esm/OINODataField.js +337 -0
  24. package/dist/esm/OINODataModel.js +178 -0
  25. package/dist/esm/OINODataSource.js +159 -0
  26. package/dist/esm/OINOFormatter.js +2 -1
  27. package/dist/esm/OINOHtmlTemplate.js +4 -1
  28. package/dist/esm/OINOModelSet.js +329 -0
  29. package/dist/esm/OINOParser.js +444 -0
  30. package/dist/esm/OINOQueryParams.js +426 -0
  31. package/dist/esm/OINORequest.js +9 -1
  32. package/dist/esm/OINOResult.js +2 -1
  33. package/dist/esm/OINOStr.js +1 -1
  34. package/dist/esm/OINOSwagger.js +201 -0
  35. package/dist/esm/index.js +14 -32
  36. package/dist/types/OINOApi.d.ts +191 -0
  37. package/dist/types/OINOBenchmark.d.ts +1 -1
  38. package/dist/types/OINOConfig.d.ts +63 -0
  39. package/dist/types/OINOConstants.d.ts +51 -0
  40. package/dist/types/OINODataField.d.ts +209 -0
  41. package/dist/types/OINODataModel.d.ts +78 -0
  42. package/dist/types/OINODataSource.d.ts +184 -0
  43. package/dist/types/OINOHtmlTemplate.d.ts +1 -1
  44. package/dist/types/OINOModelSet.d.ts +64 -0
  45. package/dist/types/OINOParser.d.ts +42 -0
  46. package/dist/types/OINOQueryParams.d.ts +270 -0
  47. package/dist/types/OINORequest.d.ts +4 -1
  48. package/dist/types/OINOResult.d.ts +1 -1
  49. package/dist/types/OINOStr.d.ts +1 -1
  50. package/dist/types/OINOSwagger.d.ts +25 -0
  51. package/dist/types/index.d.ts +14 -31
  52. package/package.json +32 -32
  53. package/src/OINOApi.ts +429 -0
  54. package/src/OINOBenchmark.ts +323 -324
  55. package/src/OINOConfig.ts +113 -0
  56. package/src/OINOConstants.ts +59 -0
  57. package/src/OINODataField.ts +371 -0
  58. package/src/OINODataModel.ts +187 -0
  59. package/src/OINODataSource.ts +280 -0
  60. package/src/OINOFormatter.ts +166 -165
  61. package/src/OINOHeaders.ts +51 -51
  62. package/src/OINOHtmlTemplate.test.ts +114 -114
  63. package/src/OINOHtmlTemplate.ts +225 -222
  64. package/src/OINOLog.ts +292 -292
  65. package/src/OINOModelSet.ts +359 -0
  66. package/src/OINOParser.ts +441 -0
  67. package/src/OINOQueryParams.ts +449 -0
  68. package/src/OINORequest.ts +204 -196
  69. package/src/OINOResult.ts +331 -330
  70. package/src/OINOStr.ts +254 -254
  71. package/src/OINOSwagger.ts +213 -0
  72. package/src/index.ts +18 -38
@@ -0,0 +1,113 @@
1
+ /** Set the name of the OINO ID field (default \_OINOID\_) */
2
+
3
+ export class OINOConfig {
4
+ /** Name of the synthetic OINO ID field */
5
+ static OINO_ID_FIELD:string = "_OINOID_"
6
+ /** Private key separator of the synthetic OINO ID field */
7
+ static OINO_ID_SEPARATOR:string = "_"
8
+ private static OINO_ID_SEPARATOR_ESCAPED:string = "%5F" // url-encoded "_"
9
+
10
+ /** Name of the OINODbQueryFilter-parameter in request */
11
+ static OINO_QUERY_FILTER_PARAM:string = "oinoqueryfilter"
12
+
13
+ /** Name of the OINODbQueryOrder-parameter in request */
14
+ static OINO_QUERY_ORDER_PARAM:string = "oinoqueryorder"
15
+
16
+ /** Name of the OINODbQueryLimit-parameter in request */
17
+ static OINO_QUERY_LIMIT_PARAM:string = "oinoquerylimit"
18
+
19
+ /** Name of the OINODbQueryAggregate-parameter in request */
20
+ static OINO_QUERY_AGGREGATE_PARAM:string = "oinoqueryaggregate"
21
+
22
+ /** Name of the OINODbSqlSelect-parameter in request */
23
+ static OINO_QUERY_SELECT_PARAM:string = "oinoqueryselect"
24
+
25
+ /**
26
+ * Set the name of the OINO ID field
27
+ * @param idField name of the OINO ID field
28
+ */
29
+ static setOinoIdField(idField: string) {
30
+ if (idField) {
31
+ OINOConfig.OINO_ID_FIELD = idField;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Set the separator character of the OINO ID field
37
+ * @param idSeparator character to use as separator of id parts
38
+ */
39
+ static setOinoIdSeparator(idSeparator: string) {
40
+ if (idSeparator && (idSeparator.length == 1)) {
41
+ OINOConfig.OINO_ID_SEPARATOR = idSeparator;
42
+ OINOConfig.OINO_ID_SEPARATOR_ESCAPED = '%' + idSeparator.charCodeAt(0).toString(16).toUpperCase();
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Print OINO ID for primary key values.
48
+ *
49
+ * @param primaryKeys an array of primary key values.
50
+ *
51
+ */
52
+ static printOINOId(primaryKeys:string[]):string {
53
+ let result:string = ""
54
+ for (let i=0; i< primaryKeys.length; i++) {
55
+ if (i > 0) {
56
+ result += OINOConfig.OINO_ID_SEPARATOR
57
+ }
58
+ result += encodeURIComponent(primaryKeys[i] as string).replaceAll(OINOConfig.OINO_ID_SEPARATOR, OINOConfig.OINO_ID_SEPARATOR_ESCAPED) // force encoding of _ and other non-encoded separators
59
+ }
60
+ return result
61
+ }
62
+
63
+ /**
64
+ * Print OINO ID for primary key values.
65
+ *
66
+ * @param oinoid the OINO ID string to parse as primary key values.
67
+ *
68
+ */
69
+ static parseOINOId(oinoid:string):string[] {
70
+ let result:string[] = []
71
+ const parts = oinoid.split(OINOConfig.OINO_ID_SEPARATOR)
72
+ for (const part of parts) {
73
+ result.push(decodeURIComponent(part))
74
+ }
75
+ return result
76
+ }
77
+
78
+ /**
79
+ * Set the name of the OINODbQueryFilter-param field
80
+ *
81
+ * @param sqlFilterParam name of the http parameter with `OINODbQueryFilter` definition
82
+ *
83
+ */
84
+ static setOinoQueryFilterParam(sqlFilterParam: string) {
85
+ if (sqlFilterParam) {
86
+ OINOConfig.OINO_QUERY_FILTER_PARAM = sqlFilterParam;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Set the name of the OINODbQueryOrder-param field
92
+ *
93
+ * @param sqlOrderParam name of the http parameter with `OINODbQueryOrder` definition
94
+ *
95
+ */
96
+ static setOinoQueryOrderParam(sqlOrderParam: string) {
97
+ if (sqlOrderParam) {
98
+ OINOConfig.OINO_QUERY_ORDER_PARAM = sqlOrderParam;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Set the name of the OINODbQueryLimit-param field
104
+ *
105
+ * @param sqlLimitParam name of the http parameter with `OINODbQueryLimit` definition
106
+ *
107
+ */
108
+ static setOinoQueryLimitParam(sqlLimitParam: string) {
109
+ if (sqlLimitParam) {
110
+ OINOConfig.OINO_QUERY_LIMIT_PARAM = sqlLimitParam;
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,59 @@
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 { Buffer } from "node:buffer"
8
+
9
+ /** OINO error message prefix */
10
+ export const OINO_ERROR_PREFIX = "OINO ERROR"
11
+ /** OINO warning message prefix */
12
+ export const OINO_WARNING_PREFIX = "OINO WARNING"
13
+ /** OINO info message prefix */
14
+ export const OINO_INFO_PREFIX = "OINO INFO"
15
+ /** OINO debug message prefix */
16
+ export const OINO_DEBUG_PREFIX = "OINO DEBUG"
17
+ /** Name of the OINOContentType-parameter request */
18
+ export const OINO_REQUEST_TYPE_PARAM = "oinorequesttype"
19
+ /** Name of the OINOContentType-parameter request */
20
+ export const OINO_RESPONSE_TYPE_PARAM = "oinoresponsetype"
21
+ /** Name of the query parameter that triggers a file download response */
22
+ export const OINO_RESPONSE_DOWNLOAD_PARAM = "oinoresponsedownload"
23
+
24
+ /**
25
+ * Supported content format mime-types
26
+ */
27
+ export enum OINOContentType {
28
+ /** JSON encoded data */
29
+ json='application/json',
30
+ /** CSV encoded data */
31
+ csv='text/csv',
32
+ /** Multipart encoded form data */
33
+ formdata='multipart/form-data',
34
+ /** URL encoded form data */
35
+ urlencode='application/x-www-form-urlencoded',
36
+ /** HTML encoded data (output only) */
37
+ html='text/html'
38
+ }
39
+
40
+ /** Field parameters in database */
41
+ export type OINODataFieldParams = {
42
+ /** Is the field a primary key */
43
+ isPrimaryKey: boolean
44
+ /** Is the field a primary key */
45
+ isForeignKey: boolean
46
+ /** Is the field an auto inc type */
47
+ isAutoInc: boolean
48
+ /** Is the field allowed to have null values */
49
+ isNotNull: boolean
50
+ }
51
+
52
+ /** A single column value of a data row */
53
+ export type OINODataCell = string | bigint | number | boolean | Date | Uint8Array | Buffer | null | undefined
54
+ /** A single data row */
55
+ export type OINODataRow = Array<OINODataCell>
56
+ /** Empty row instance */
57
+ export const OINO_EMPTY_ROW:OINODataRow = []
58
+ /** Empty row array instance */
59
+ export const OINO_EMPTY_ROWS:OINODataRow[] = []
@@ -0,0 +1,371 @@
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 { Buffer } from "node:buffer"
8
+ import { OINO_ERROR_PREFIX, OINODataFieldParams, OINODataCell } from "./OINOConstants.js"
9
+ import { OINOLog } from "./OINOLog.js"
10
+ import { OINODataSource } from "./OINODataSource.js"
11
+
12
+ /**
13
+ * Base class for a column of data responsible for appropriatelly serializing/deserializing the data.
14
+ *
15
+ */
16
+ export class OINODataField {
17
+
18
+ /** OINO data source reference*/
19
+ readonly datasource:OINODataSource;
20
+
21
+ /** Name of the field */
22
+ readonly name: string;
23
+
24
+ /** Internal type of field*/
25
+ readonly type: string;
26
+
27
+ /** SQL type of the field */
28
+ readonly nativeType: string;
29
+
30
+ /** Maximum length of the field (or 0) */
31
+ readonly maxLength: number;
32
+
33
+ /** Parameters for the field */
34
+ readonly fieldParams: OINODataFieldParams;
35
+
36
+ /**
37
+ * Constructor for a data field
38
+ *
39
+ * @param datasource OINO data source reference
40
+ * @param name name of the field
41
+ * @param type internal type of the field
42
+ * @param nativeType column type in database
43
+ * @param fieldParams parameters of the field
44
+ * @param maxLength maximum length of the field (or 0)
45
+ *
46
+ */
47
+ constructor(datasource:OINODataSource, name: string, type:string, nativeType: string, fieldParams: OINODataFieldParams, maxLength:number = 0) {
48
+ this.datasource = datasource
49
+ this.name = name
50
+ this.type = type
51
+ this.maxLength = maxLength
52
+ this.nativeType = nativeType
53
+ this.fieldParams = fieldParams
54
+ }
55
+
56
+ /**
57
+ * Serialize cell value in the given content format.
58
+ *
59
+ * @param cellVal cell value
60
+ *
61
+ */
62
+ serializeCell(cellVal: OINODataCell):string|null|undefined {
63
+ cellVal = this.datasource.parseValueAsCell(cellVal, this.nativeType)
64
+ if ((cellVal === null) || (cellVal === undefined)) {
65
+ return cellVal // let content type encoder worry what to do with the value (so not force it to string)
66
+ } else {
67
+ return cellVal.toString()
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Parce cell value from string using field type specific formatting rules.
73
+ *
74
+ * @param value string value
75
+ *
76
+ */
77
+ deserializeCell(value: string|null|undefined): OINODataCell {
78
+ return value
79
+ }
80
+
81
+ /**
82
+ * Print data cell (from deserialization) as SQL-string.
83
+ *
84
+ * @param cellVal cell value
85
+ *
86
+ */
87
+ printCellAsValue(cellVal: OINODataCell):string {
88
+ return this.datasource.printCellAsValue(cellVal, this.nativeType);
89
+ }
90
+
91
+ /**
92
+ * Print name of column as SQL.
93
+ *
94
+ */
95
+ printColumnName():string {
96
+ return this.datasource.printColumnName(this.name)
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Specialised class for a string column.
102
+ *
103
+ */
104
+ export class OINOStringDataField extends OINODataField {
105
+
106
+ /**
107
+ * Constructor for a string data field
108
+ *
109
+ * @param datasource OINO data source reference
110
+ * @param name name of the field
111
+ * @param nativeType column type in database
112
+ * @param fieldParams parameters of the field
113
+ * @param maxLength maximum length of the field (or 0)
114
+ *
115
+ */
116
+ constructor(datasource:OINODataSource, name: string, nativeType: string, fieldParams: OINODataFieldParams, maxLength: number) {
117
+ super(datasource, name, "string", nativeType, fieldParams, maxLength)
118
+ }
119
+
120
+ }
121
+
122
+ /**
123
+ * Specialised class for a boolean column.
124
+ *
125
+ */
126
+ export class OINOBooleanDataField extends OINODataField {
127
+
128
+ /**
129
+ * Constructor for a boolean data field
130
+ *
131
+ * @param datasource OINO data source reference
132
+ * @param name name of the field
133
+ * @param nativeType column type in database
134
+ * @param fieldParams parameters of the field
135
+ *
136
+ */
137
+ constructor(datasource:OINODataSource, name: string, nativeType: string, fieldParams: OINODataFieldParams) {
138
+ super(datasource, name, "boolean", nativeType, fieldParams)
139
+ }
140
+ /**
141
+ * Serialize cell value in the given content format.
142
+ *
143
+ * @param cellVal cell value
144
+ *
145
+ */
146
+ serializeCell(cellVal: OINODataCell):string|null|undefined {
147
+ const parsed_value:string = (this.datasource.parseValueAsCell(cellVal, this.nativeType) || "").toString()
148
+ let result:string
149
+ // console.log("OINOBooleanDataField.serializeCell: parsed_value=" + parsed_value)
150
+ if ((parsed_value == "") || (parsed_value.toLowerCase() == "false") || (parsed_value.match(/^0+$/))) {
151
+ result = "false"
152
+ } else {
153
+ result = "true"
154
+ }
155
+ return result
156
+ }
157
+
158
+ /**
159
+ * Parce cell value from string using field type specific formatting rules.
160
+ *
161
+ * @param value string value
162
+ *
163
+ */
164
+ deserializeCell(value: string|null|undefined): OINODataCell {
165
+ if (value == null || value == "" || value.toString().toLowerCase() == "false" || value == "0") { // TODO: testaa poistaa .toString()
166
+ return false
167
+ } else {
168
+ return true
169
+ }
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Specialised class for a number column.
175
+ *
176
+ */
177
+ export class OINONumberDataField extends OINODataField {
178
+
179
+ /**
180
+ * Constructor for a string data field
181
+ *
182
+ * @param datasource OINO data source reference
183
+ * @param name name of the field
184
+ * @param nativeType column type in database
185
+ * @param fieldParams parameters of the field
186
+ *
187
+ */
188
+ constructor(datasource:OINODataSource, name: string, nativeType: string, fieldParams: OINODataFieldParams) {
189
+ super(datasource, name, "number", nativeType, fieldParams)
190
+ }
191
+
192
+ /**
193
+ * Serialize cell value in the given content format.
194
+ *
195
+ * @param cellVal cell value
196
+ *
197
+ */
198
+ serializeCell(cellVal: OINODataCell):string|null|undefined {
199
+ let result:string|null
200
+ if ((cellVal === null) || (cellVal === undefined) || (cellVal === "")) {
201
+ result = null
202
+ } else {
203
+ result = cellVal.toString()
204
+ }
205
+ return result
206
+ }
207
+
208
+ /**
209
+ * Parce cell value from string using field type specific formatting rules.
210
+ *
211
+ * @param value string value
212
+ *
213
+ */
214
+ deserializeCell(value: string|null|undefined): OINODataCell {
215
+ if (value === undefined) {
216
+ return undefined
217
+ } else if ((value === "") || (value === null)) {
218
+ return null
219
+ } else {
220
+ const result:number = parseFloat(value)
221
+ if (isNaN(result)) {
222
+ OINOLog.error("@oino-ts/db", "OINONumberDataField", "toSql", "Invalid value!", {value:value})
223
+ throw new Error(OINO_ERROR_PREFIX + ": OINONumberDataField.deserializeCell - Invalid value '" + value + "'") // incorrectly formatted data could be a security risk, abort processing
224
+ }
225
+ return result
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Specialised class for a blob column.
232
+ *
233
+ */
234
+ export class OINOBlobDataField extends OINODataField {
235
+
236
+ /**
237
+ * Constructor for a blob data field
238
+ *
239
+ * @param datasource OINO data source reference
240
+ * @param name name of the field
241
+ * @param nativeType column type in database
242
+ * @param fieldParams parameters of the field
243
+ * @param maxLength maximum length of the field (or 0)
244
+ *
245
+ */
246
+ constructor(datasource:OINODataSource, name: string, nativeType: string, fieldParams: OINODataFieldParams, maxLength:number) {
247
+ super(datasource, name, "blob", nativeType, fieldParams, maxLength)
248
+ }
249
+
250
+ /**
251
+ * Serialize cell value in the given content format.
252
+ *
253
+ * @param cellVal cell value
254
+ *
255
+ */
256
+ serializeCell(cellVal: OINODataCell):string|null|undefined {
257
+ // console.log("OINOBlobDataField.serializeCell: cellVal", cellVal, typeof(cellVal))
258
+ if ((cellVal === null) || (cellVal === undefined)) {
259
+ return cellVal
260
+
261
+ } else if (cellVal instanceof Buffer) {
262
+ return cellVal.toString('base64')
263
+
264
+ } else if (cellVal instanceof Uint8Array) {
265
+ return Buffer.from(cellVal).toString('base64')
266
+
267
+ } else {
268
+ return this.datasource.parseValueAsCell(cellVal, this.nativeType)?.toString()
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Parce cell value from string using field type specific formatting rules.
274
+ *
275
+ * @param value string value
276
+ *
277
+ */
278
+ deserializeCell(value: string|null|undefined): OINODataCell {
279
+ if (value == null) {
280
+ return Buffer.alloc(0)
281
+
282
+ } else {
283
+ return Buffer.from(value, 'base64') // Blob-field data is base64 encoded and converted internally to UInt8Array / Buffer
284
+ }
285
+ }
286
+
287
+ }
288
+
289
+ /**
290
+ * Specialised class for a datetime column.
291
+ *
292
+ */
293
+ export class OINODatetimeDataField extends OINODataField {
294
+
295
+ /**
296
+ * Constructor for a string data field
297
+ *
298
+ * @param datasource OINO data source reference
299
+ * @param name name of the field
300
+ * @param nativeType column type in database
301
+ * @param fieldParams parameters of the field
302
+ *
303
+ */
304
+ constructor(datasource:OINODataSource, name: string, nativeType: string, fieldParams: OINODataFieldParams) {
305
+ super(datasource, name, "datetime", nativeType, fieldParams)
306
+ }
307
+
308
+ /**
309
+ * Serialize cell value in the given content format.
310
+ *
311
+ * @param cellVal cell value
312
+ *
313
+ */
314
+ serializeCell(cellVal: OINODataCell): string|null|undefined {
315
+ if (typeof(cellVal) == "string") {
316
+ cellVal = this.datasource.parseValueAsCell(cellVal, this.nativeType)
317
+ }
318
+ if ((cellVal === null) || (cellVal === undefined)) {
319
+ return cellVal
320
+
321
+ } else if (cellVal instanceof Date) {
322
+ return cellVal.toISOString()
323
+
324
+ } else {
325
+ return cellVal.toString()
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Serialize cell value in the given content format.
331
+ *
332
+ * @param cellVal cell value
333
+ * @param locale locale-object to format datetimes with
334
+ *
335
+ */
336
+ serializeCellWithLocale(cellVal: OINODataCell, locale:Intl.DateTimeFormat): string|null|undefined {
337
+ if (typeof(cellVal) == "string") {
338
+ cellVal = this.datasource.parseValueAsCell(cellVal, this.nativeType)
339
+ }
340
+ if ((cellVal === null) || (cellVal === undefined)) {
341
+ return cellVal
342
+
343
+ } else if (cellVal instanceof Date) {
344
+ return locale.format(cellVal)
345
+
346
+ } else {
347
+ return cellVal.toString()
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Parce cell value from string using field type specific formatting rules.
353
+ *
354
+ * @param value string value
355
+ *
356
+ */
357
+ deserializeCell(value: string|null|undefined): OINODataCell {
358
+ if ((value === null) || (value === undefined)) {
359
+ return value
360
+ } else {
361
+ return new Date(value)
362
+ }
363
+ }
364
+
365
+ }
366
+
367
+ /**
368
+ * Callback to filter data fields
369
+ * @param field fields to filter
370
+ */
371
+ export type OINODataFieldFilter = (field:OINODataField) => Boolean