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