@oino-ts/db 0.3.4 → 0.4.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/dist/cjs/OINODbApi.js +43 -2
- package/dist/cjs/OINODbConfig.js +2 -0
- package/dist/cjs/OINODbDataField.js +23 -0
- package/dist/cjs/OINODbDataModel.js +12 -5
- package/dist/cjs/OINODbFactory.js +5 -2
- package/dist/cjs/OINODbModelSet.js +17 -1
- package/dist/cjs/OINODbSqlParams.js +73 -9
- package/dist/cjs/index.js +4 -1
- package/dist/esm/OINODbApi.js +44 -3
- package/dist/esm/OINODbConfig.js +2 -0
- package/dist/esm/OINODbDataField.js +23 -0
- package/dist/esm/OINODbDataModel.js +13 -6
- package/dist/esm/OINODbFactory.js +5 -2
- package/dist/esm/OINODbModelSet.js +17 -1
- package/dist/esm/OINODbSqlParams.js +72 -9
- package/dist/esm/index.js +3 -1
- package/dist/types/OINODb.d.ts +7 -0
- package/dist/types/OINODbApi.d.ts +13 -0
- package/dist/types/OINODbConfig.d.ts +2 -0
- package/dist/types/OINODbDataField.d.ts +8 -0
- package/dist/types/OINODbModelSet.d.ts +5 -2
- package/dist/types/OINODbSqlParams.d.ts +42 -2
- package/dist/types/index.d.ts +6 -2
- package/package.json +3 -3
- package/src/OINODb.ts +8 -0
- package/src/OINODbApi.test.ts +17 -1
- package/src/OINODbApi.ts +42 -3
- package/src/OINODbConfig.ts +3 -0
- package/src/OINODbDataField.ts +24 -0
- package/src/OINODbDataModel.ts +12 -6
- package/src/OINODbFactory.ts +5 -2
- package/src/OINODbModelSet.ts +19 -2
- package/src/OINODbSqlParams.ts +76 -9
- package/src/index.ts +6 -2
package/dist/cjs/OINODbApi.js
CHANGED
|
@@ -59,6 +59,41 @@ exports.OINODbApiResult = OINODbApiResult;
|
|
|
59
59
|
*
|
|
60
60
|
*/
|
|
61
61
|
class OINODbHtmlTemplate extends index_js_1.OINOHtmlTemplate {
|
|
62
|
+
/** Datetime format string */
|
|
63
|
+
localeStr;
|
|
64
|
+
/** Locale formatter */
|
|
65
|
+
_locale;
|
|
66
|
+
/**
|
|
67
|
+
* Constructor of OINODbHtmlTemplate.
|
|
68
|
+
*
|
|
69
|
+
* @param template HTML template string
|
|
70
|
+
* @param localeStr Datetime format string, either "iso" for ISO8601 or "default" for system default or valid locale string
|
|
71
|
+
* @param localeStyle Datetime format style, either "short/medium/long/full" or Intl.DateTimeFormat options
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
constructor(template, localeStr = "iso", localeStyle = "medium") {
|
|
75
|
+
super(template);
|
|
76
|
+
const supported_locales = Intl.DateTimeFormat.supportedLocalesOf([localeStr]);
|
|
77
|
+
let locale_opts;
|
|
78
|
+
if (typeof localeStyle == "string") {
|
|
79
|
+
locale_opts = { dateStyle: localeStyle, timeStyle: localeStyle };
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
locale_opts = localeStyle;
|
|
83
|
+
}
|
|
84
|
+
if ((localeStr == "iso") || (localeStr == "") || (supported_locales.length == 0)) {
|
|
85
|
+
this._locale = null;
|
|
86
|
+
this.localeStr = "iso";
|
|
87
|
+
}
|
|
88
|
+
else if (localeStr == "default") {
|
|
89
|
+
this._locale = new Intl.DateTimeFormat(undefined, locale_opts);
|
|
90
|
+
this.localeStr = "default";
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
this.localeStr = supported_locales[0];
|
|
94
|
+
this._locale = new Intl.DateTimeFormat(supported_locales[0], locale_opts);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
62
97
|
/**
|
|
63
98
|
* Creates HTML Response from API modelset.
|
|
64
99
|
*
|
|
@@ -88,7 +123,13 @@ class OINODbHtmlTemplate extends index_js_1.OINOHtmlTemplate {
|
|
|
88
123
|
// let html_row:string = this.template.replaceAll('###' + OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###')
|
|
89
124
|
for (let i = 0; i < datamodel.fields.length; i++) {
|
|
90
125
|
const f = datamodel.fields[i];
|
|
91
|
-
let value
|
|
126
|
+
let value;
|
|
127
|
+
if ((this._locale != null) && (f instanceof index_js_1.OINODatetimeDataField)) {
|
|
128
|
+
value = f.serializeCellWithLocale(row[i], this._locale);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
value = f.serializeCell(row[i]);
|
|
132
|
+
}
|
|
92
133
|
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
93
134
|
if (value && (f instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
|
|
94
135
|
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed);
|
|
@@ -195,7 +236,7 @@ class OINODbApi {
|
|
|
195
236
|
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut");
|
|
196
237
|
}
|
|
197
238
|
else {
|
|
198
|
-
result.data = new index_js_1.OINODbModelSet(this.datamodel, sql_res);
|
|
239
|
+
result.data = new index_js_1.OINODbModelSet(this.datamodel, sql_res, params.sqlParams);
|
|
199
240
|
}
|
|
200
241
|
}
|
|
201
242
|
catch (e) {
|
package/dist/cjs/OINODbConfig.js
CHANGED
|
@@ -16,6 +16,8 @@ class OINODbConfig {
|
|
|
16
16
|
static OINODB_SQL_LIMIT_PARAM = "oinosqllimit";
|
|
17
17
|
/** Name of the OINODbSqlAggregate-parameter in request */
|
|
18
18
|
static OINODB_SQL_AGGREGATE_PARAM = "oinosqlaggregate";
|
|
19
|
+
/** Name of the OINODbSqlSelect-parameter in request */
|
|
20
|
+
static OINODB_SQL_SELECT_PARAM = "oinosqlselect";
|
|
19
21
|
/**
|
|
20
22
|
* Set the name of the OINO ID field
|
|
21
23
|
* @param idField name of the OINO ID field
|
|
@@ -347,6 +347,29 @@ class OINODatetimeDataField extends OINODbDataField {
|
|
|
347
347
|
return cellVal.toString();
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Serialize cell value in the given content format.
|
|
352
|
+
*
|
|
353
|
+
* @param cellVal cell value
|
|
354
|
+
* @param locale locale-object to format datetimes with
|
|
355
|
+
*
|
|
356
|
+
*/
|
|
357
|
+
serializeCellWithLocale(cellVal, locale) {
|
|
358
|
+
// OINOLog.debug("OINODatetimeDataField.serializeCell", {cellVal:cellVal, type:typeof(cellVal)})
|
|
359
|
+
if (typeof (cellVal) == "string") {
|
|
360
|
+
cellVal = this.db.parseSqlValueAsCell(cellVal, this.sqlType);
|
|
361
|
+
// OINOLog.debug("OINODatetimeDataField.serializeCell parsed", {cellVal:cellVal, type:typeof(cellVal)})
|
|
362
|
+
}
|
|
363
|
+
if ((cellVal === null) || (cellVal === undefined)) {
|
|
364
|
+
return cellVal;
|
|
365
|
+
}
|
|
366
|
+
else if (cellVal instanceof Date) {
|
|
367
|
+
return locale.format(cellVal);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
return cellVal.toString();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
350
373
|
/**
|
|
351
374
|
* Parce cell value from string using field type specific formatting rules.
|
|
352
375
|
*
|
|
@@ -37,10 +37,16 @@ class OINODbDataModel {
|
|
|
37
37
|
async initialize() {
|
|
38
38
|
await this.api.db.initializeApiDatamodel(this.api);
|
|
39
39
|
}
|
|
40
|
-
_printSqlColumnNames() {
|
|
40
|
+
_printSqlColumnNames(select) {
|
|
41
41
|
let result = "";
|
|
42
42
|
for (let i = 0; i < this.fields.length; i++) {
|
|
43
|
-
|
|
43
|
+
const f = this.fields[i];
|
|
44
|
+
if (select?.isSelected(f) === false) { // if a field is not selected, we include a constant and correct fieldname instead so that dimensions of the data don't change but no unnecessary data is fetched
|
|
45
|
+
result += f.db.printSqlString(index_js_1.OINODB_UNDEFINED) + " as " + f.printSqlColumnName() + ",";
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
result += f.printSqlColumnName() + ",";
|
|
49
|
+
}
|
|
44
50
|
}
|
|
45
51
|
return result.substring(0, result.length - 1);
|
|
46
52
|
}
|
|
@@ -219,17 +225,18 @@ class OINODbDataModel {
|
|
|
219
225
|
printSqlSelect(id, params) {
|
|
220
226
|
let column_names = "";
|
|
221
227
|
if (params.aggregate) {
|
|
222
|
-
column_names = params.aggregate.printSqlColumnNames(this);
|
|
228
|
+
column_names = params.aggregate.printSqlColumnNames(this, params.select);
|
|
223
229
|
}
|
|
224
230
|
else {
|
|
225
|
-
column_names = this._printSqlColumnNames();
|
|
231
|
+
column_names = this._printSqlColumnNames(params.select);
|
|
226
232
|
}
|
|
233
|
+
// OINOLog.debug("OINODbDataModel.printSqlSelect", {column_names:column_names})
|
|
227
234
|
const order_sql = params.order?.toSql(this) || "";
|
|
228
235
|
const limit_sql = params.limit?.toSql(this) || "";
|
|
229
236
|
const filter_sql = params.filter?.toSql(this) || "";
|
|
230
237
|
const aggregate_sql = params.aggregate?.toSql(this) || "";
|
|
231
238
|
let where_sql = "";
|
|
232
|
-
// OINOLog.debug("OINODbDataModel.printSqlSelect", {
|
|
239
|
+
// OINOLog.debug("OINODbDataModel.printSqlSelect", {order_sql:order_sql, limit_sql:limit_sql, filter_sql:filter_sql, aggregate_sql:aggregate_sql})
|
|
233
240
|
if ((id != null) && (id != "") && (filter_sql != "")) {
|
|
234
241
|
where_sql = this._printSqlPrimaryKeyCondition(id) + " AND " + filter_sql;
|
|
235
242
|
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.OINODbFactory = void 0;
|
|
9
9
|
const index_js_1 = require("./index.js");
|
|
10
|
-
const OINODbSqlParams_js_1 = require("./OINODbSqlParams.js");
|
|
11
10
|
/**
|
|
12
11
|
* Static factory class for easily creating things based on data
|
|
13
12
|
*
|
|
@@ -75,7 +74,11 @@ class OINODbFactory {
|
|
|
75
74
|
}
|
|
76
75
|
const aggregate = url.searchParams.get(index_js_1.OINODbConfig.OINODB_SQL_AGGREGATE_PARAM);
|
|
77
76
|
if (aggregate) {
|
|
78
|
-
sql_params.aggregate =
|
|
77
|
+
sql_params.aggregate = index_js_1.OINODbSqlAggregate.parse(aggregate);
|
|
78
|
+
}
|
|
79
|
+
const select = url.searchParams.get(index_js_1.OINODbConfig.OINODB_SQL_SELECT_PARAM);
|
|
80
|
+
if (select) {
|
|
81
|
+
sql_params.select = index_js_1.OINODbSqlSelect.parse(select);
|
|
79
82
|
}
|
|
80
83
|
let result = { sqlParams: sql_params };
|
|
81
84
|
const content_type = request.headers.get("content-type");
|
|
@@ -19,6 +19,8 @@ class OINODbModelSet {
|
|
|
19
19
|
datamodel;
|
|
20
20
|
/** Reference to data set */
|
|
21
21
|
dataset;
|
|
22
|
+
/** SQL parameters */
|
|
23
|
+
sqlParams;
|
|
22
24
|
/** Collection of errors */
|
|
23
25
|
errors;
|
|
24
26
|
/**
|
|
@@ -26,10 +28,12 @@ class OINODbModelSet {
|
|
|
26
28
|
*
|
|
27
29
|
* @param datamodel data model
|
|
28
30
|
* @param dataset data set
|
|
31
|
+
* @param sqlParams SQL parameters
|
|
29
32
|
*/
|
|
30
|
-
constructor(datamodel, dataset) {
|
|
33
|
+
constructor(datamodel, dataset, sqlParams) {
|
|
31
34
|
this.datamodel = datamodel;
|
|
32
35
|
this.dataset = dataset;
|
|
36
|
+
this.sqlParams = sqlParams;
|
|
33
37
|
this.errors = this.dataset.messages;
|
|
34
38
|
}
|
|
35
39
|
_encodeAndHashFieldValue(field, value, contentType, primaryKeyValues, rowIdSeed) {
|
|
@@ -54,6 +58,9 @@ class OINODbModelSet {
|
|
|
54
58
|
let json_row = "";
|
|
55
59
|
for (let i = 0; i < fields.length; i++) {
|
|
56
60
|
const f = fields[i];
|
|
61
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
57
64
|
let value = f.serializeCell(row[i]);
|
|
58
65
|
if (value === undefined) {
|
|
59
66
|
// OINOLog.info("OINODbModelSet._writeRowJson: undefined value skipped", {field_name:f.name})
|
|
@@ -109,6 +116,9 @@ class OINODbModelSet {
|
|
|
109
116
|
let csv_row = "";
|
|
110
117
|
for (let i = 0; i < fields.length; i++) {
|
|
111
118
|
const f = fields[i];
|
|
119
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
112
122
|
let value = f.serializeCell(row[i]);
|
|
113
123
|
if (value == null) {
|
|
114
124
|
csv_row += "," + index_js_1.OINOStr.encode(value, index_js_1.OINOContentType.csv); // either null or undefined
|
|
@@ -157,6 +167,9 @@ class OINODbModelSet {
|
|
|
157
167
|
let result = "";
|
|
158
168
|
for (let i = 0; i < fields.length; i++) {
|
|
159
169
|
const f = fields[i];
|
|
170
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
160
173
|
let value = f.serializeCell(row[i]);
|
|
161
174
|
let formdata_block = "";
|
|
162
175
|
let is_file = (f instanceof index_js_1.OINOBlobDataField);
|
|
@@ -196,6 +209,9 @@ class OINODbModelSet {
|
|
|
196
209
|
let urlencode_row = "";
|
|
197
210
|
for (let i = 0; i < fields.length; i++) {
|
|
198
211
|
const f = fields[i];
|
|
212
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
199
215
|
let value = f.serializeCell(row[i]);
|
|
200
216
|
if ((value === undefined)) { // || (value === null)) {
|
|
201
217
|
// console.log("OINODbModelSet._writeRowUrlencode undefined field value:" + fields[i].name)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.OINODbSqlAggregate = exports.OINODbSqlAggregateFunctions = exports.OINODbSqlLimit = exports.OINODbSqlOrder = exports.OINODbSqlFilter = exports.OINODbSqlComparison = exports.OINODbSqlBooleanOperation = void 0;
|
|
8
|
+
exports.OINODbSqlSelect = exports.OINODbSqlAggregate = exports.OINODbSqlAggregateFunctions = exports.OINODbSqlLimit = exports.OINODbSqlOrder = exports.OINODbSqlFilter = exports.OINODbSqlComparison = exports.OINODbSqlBooleanOperation = void 0;
|
|
9
9
|
const index_js_1 = require("./index.js");
|
|
10
10
|
const OINO_FIELD_NAME_CHARS = "\\w\\s\\-\\_\\#\\¤";
|
|
11
11
|
/**
|
|
@@ -410,29 +410,93 @@ class OINODbSqlAggregate {
|
|
|
410
410
|
result += dataModel.fields[i].printSqlColumnName() + ",";
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
-
|
|
413
|
+
// OINOLog.debug("OINODbSqlAggregate.toSql", {result:result})
|
|
414
414
|
return result.substring(0, result.length - 1);
|
|
415
415
|
}
|
|
416
416
|
/**
|
|
417
417
|
* Print non-aggregated fields as SQL GROUP BY-condition based on the datamodel of the API.
|
|
418
418
|
*
|
|
419
419
|
* @param dataModel data model (and database) to use for formatting of values
|
|
420
|
+
* @param select what fields to select
|
|
420
421
|
*
|
|
421
422
|
*/
|
|
422
|
-
printSqlColumnNames(dataModel) {
|
|
423
|
+
printSqlColumnNames(dataModel, select) {
|
|
423
424
|
let result = "";
|
|
424
425
|
for (let i = 0; i < dataModel.fields.length; i++) {
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
result += this._functions[aggregate_index] + "(" + col_name + ") as " + col_name + ",";
|
|
426
|
+
const f = dataModel.fields[i];
|
|
427
|
+
if (select?.isSelected(f) == false) { // if a field is not selected, we include a constant and correct fieldname instead so that dimensions of the data don't change but no unnecessary data is fetched
|
|
428
|
+
result += f.db.printSqlString(index_js_1.OINODB_UNDEFINED) + " as " + f.printSqlColumnName() + ",";
|
|
429
429
|
}
|
|
430
430
|
else {
|
|
431
|
-
|
|
431
|
+
const aggregate_index = this._fields.indexOf(f.name);
|
|
432
|
+
const col_name = f.printSqlColumnName();
|
|
433
|
+
if (aggregate_index >= 0) {
|
|
434
|
+
result += this._functions[aggregate_index] + "(" + col_name + ") as " + col_name + ",";
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
result += col_name + ",";
|
|
438
|
+
}
|
|
432
439
|
}
|
|
433
440
|
}
|
|
434
|
-
|
|
441
|
+
// OINOLog.debug("OINODbSqlAggregate.printSqlColumnNames", {result:result})
|
|
435
442
|
return result.substring(0, result.length - 1);
|
|
436
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Does filter contain any valid conditions.
|
|
446
|
+
*
|
|
447
|
+
* @param field field to check if it is aggregated
|
|
448
|
+
*/
|
|
449
|
+
isAggregated(field) {
|
|
450
|
+
return (this._fields.includes(field.name));
|
|
451
|
+
}
|
|
437
452
|
}
|
|
438
453
|
exports.OINODbSqlAggregate = OINODbSqlAggregate;
|
|
454
|
+
/**
|
|
455
|
+
* Class for ordering select results on a number of columns.
|
|
456
|
+
*
|
|
457
|
+
*/
|
|
458
|
+
class OINODbSqlSelect {
|
|
459
|
+
_columns;
|
|
460
|
+
/**
|
|
461
|
+
* Constructor for `OINODbSqlSelect`.
|
|
462
|
+
*
|
|
463
|
+
* @param columns array of columns to select
|
|
464
|
+
*
|
|
465
|
+
*/
|
|
466
|
+
constructor(columns) {
|
|
467
|
+
// OINOLog.debug("OINODbSqlSelect.constructor", {columns:columns})
|
|
468
|
+
this._columns = columns;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Constructor for `OINODbSqlSelect` as parser of http parameter.
|
|
472
|
+
*
|
|
473
|
+
* @param columns comma separatef string selected columns from HTTP-request
|
|
474
|
+
*
|
|
475
|
+
*/
|
|
476
|
+
static parse(columns) {
|
|
477
|
+
if (columns == "") {
|
|
478
|
+
return new OINODbSqlSelect([]);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
return new OINODbSqlSelect(columns.split(','));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Does select contain any valid columns.
|
|
486
|
+
*
|
|
487
|
+
*/
|
|
488
|
+
isEmpty() {
|
|
489
|
+
return (this._columns.length == 0);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Does select include given column.
|
|
493
|
+
*
|
|
494
|
+
* @param field field to check if it is selected
|
|
495
|
+
*
|
|
496
|
+
*/
|
|
497
|
+
isSelected(field) {
|
|
498
|
+
// OINOLog.debug("OINODbSqlSelect.isSelected", {column:column, columns:this._columns})
|
|
499
|
+
return ((this._columns.length == 0) || (field.fieldParams.isPrimaryKey == true) || (this._columns.includes(field.name)));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
exports.OINODbSqlSelect = OINODbSqlSelect;
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OINODB_EMPTY_ROWS = exports.OINODB_EMPTY_ROW = exports.OINODbParser = exports.OINODbSwagger = exports.OINODbFactory = exports.OINODbConfig = exports.OINODbSqlAggregateFunctions = exports.OINODbSqlAggregate = exports.OINODbSqlBooleanOperation = exports.OINODbSqlLimit = exports.OINODbSqlComparison = exports.OINODbSqlOrder = exports.OINODbSqlFilter = exports.OINODb = exports.OINODbMemoryDataSet = exports.OINODbDataSet = exports.OINODatetimeDataField = exports.OINOBlobDataField = exports.OINOStringDataField = exports.OINONumberDataField = exports.OINOBooleanDataField = exports.OINODbDataField = exports.OINODbModelSet = exports.OINODbDataModel = exports.OINODbApi = exports.OINODbHtmlTemplate = exports.OINODbApiResult = exports.OINOHtmlTemplate = exports.OINOHttpResult = exports.OINOResult = exports.OINOConsoleLog = exports.OINOLogLevel = exports.OINOLog = exports.OINOBenchmark = exports.OINOStr = exports.OINO_DEBUG_PREFIX = exports.OINO_INFO_PREFIX = exports.OINO_WARNING_PREFIX = exports.OINO_ERROR_PREFIX = exports.OINOContentType = void 0;
|
|
3
|
+
exports.OINODB_UNDEFINED = exports.OINODB_EMPTY_ROWS = exports.OINODB_EMPTY_ROW = exports.OINODbParser = exports.OINODbSwagger = exports.OINODbFactory = exports.OINODbConfig = exports.OINODbSqlSelect = exports.OINODbSqlAggregateFunctions = exports.OINODbSqlAggregate = exports.OINODbSqlBooleanOperation = exports.OINODbSqlLimit = exports.OINODbSqlComparison = exports.OINODbSqlOrder = exports.OINODbSqlFilter = exports.OINODb = exports.OINODbMemoryDataSet = exports.OINODbDataSet = exports.OINODatetimeDataField = exports.OINOBlobDataField = exports.OINOStringDataField = exports.OINONumberDataField = exports.OINOBooleanDataField = exports.OINODbDataField = exports.OINODbModelSet = exports.OINODbDataModel = exports.OINODbApi = exports.OINODbHtmlTemplate = exports.OINODbApiResult = exports.OINOHtmlTemplate = exports.OINOHttpResult = exports.OINOResult = exports.OINOConsoleLog = exports.OINOLogLevel = exports.OINOLog = exports.OINOBenchmark = exports.OINOStr = exports.OINO_DEBUG_PREFIX = exports.OINO_INFO_PREFIX = exports.OINO_WARNING_PREFIX = exports.OINO_ERROR_PREFIX = exports.OINOContentType = void 0;
|
|
4
4
|
const common_1 = require("@oino-ts/common");
|
|
5
5
|
Object.defineProperty(exports, "OINOContentType", { enumerable: true, get: function () { return common_1.OINOContentType; } });
|
|
6
6
|
var common_2 = require("@oino-ts/common");
|
|
@@ -43,6 +43,7 @@ Object.defineProperty(exports, "OINODbSqlLimit", { enumerable: true, get: functi
|
|
|
43
43
|
Object.defineProperty(exports, "OINODbSqlBooleanOperation", { enumerable: true, get: function () { return OINODbSqlParams_js_1.OINODbSqlBooleanOperation; } });
|
|
44
44
|
Object.defineProperty(exports, "OINODbSqlAggregate", { enumerable: true, get: function () { return OINODbSqlParams_js_1.OINODbSqlAggregate; } });
|
|
45
45
|
Object.defineProperty(exports, "OINODbSqlAggregateFunctions", { enumerable: true, get: function () { return OINODbSqlParams_js_1.OINODbSqlAggregateFunctions; } });
|
|
46
|
+
Object.defineProperty(exports, "OINODbSqlSelect", { enumerable: true, get: function () { return OINODbSqlParams_js_1.OINODbSqlSelect; } });
|
|
46
47
|
var OINODbConfig_js_1 = require("./OINODbConfig.js");
|
|
47
48
|
Object.defineProperty(exports, "OINODbConfig", { enumerable: true, get: function () { return OINODbConfig_js_1.OINODbConfig; } });
|
|
48
49
|
var OINODbFactory_js_1 = require("./OINODbFactory.js");
|
|
@@ -55,3 +56,5 @@ Object.defineProperty(exports, "OINODbParser", { enumerable: true, get: function
|
|
|
55
56
|
exports.OINODB_EMPTY_ROW = [];
|
|
56
57
|
/** Empty row array instance */
|
|
57
58
|
exports.OINODB_EMPTY_ROWS = [exports.OINODB_EMPTY_ROW];
|
|
59
|
+
/** Constant for undefined values */
|
|
60
|
+
exports.OINODB_UNDEFINED = ""; // original idea was to have a defined literal that get's swapped back to undefined, but current implementation just leaves it out at serialization (so value does not matter)
|
package/dist/esm/OINODbApi.js
CHANGED
|
@@ -3,7 +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 { OINODbDataModel, OINOStringDataField, OINO_ERROR_PREFIX, OINODbModelSet, OINOBenchmark, OINODbConfig, OINOHtmlTemplate, OINONumberDataField, OINODbParser } from "./index.js";
|
|
6
|
+
import { OINODbDataModel, OINOStringDataField, OINO_ERROR_PREFIX, OINODbModelSet, OINOBenchmark, OINODbConfig, OINOHtmlTemplate, OINONumberDataField, OINODbParser, OINODatetimeDataField } from "./index.js";
|
|
7
7
|
import { OINOResult } from "@oino-ts/common";
|
|
8
8
|
import { OINOHashid } from "@oino-ts/hashid";
|
|
9
9
|
const API_EMPTY_PARAMS = { sqlParams: {} };
|
|
@@ -55,6 +55,41 @@ export class OINODbApiResult extends OINOResult {
|
|
|
55
55
|
*
|
|
56
56
|
*/
|
|
57
57
|
export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
58
|
+
/** Datetime format string */
|
|
59
|
+
localeStr;
|
|
60
|
+
/** Locale formatter */
|
|
61
|
+
_locale;
|
|
62
|
+
/**
|
|
63
|
+
* Constructor of OINODbHtmlTemplate.
|
|
64
|
+
*
|
|
65
|
+
* @param template HTML template string
|
|
66
|
+
* @param localeStr Datetime format string, either "iso" for ISO8601 or "default" for system default or valid locale string
|
|
67
|
+
* @param localeStyle Datetime format style, either "short/medium/long/full" or Intl.DateTimeFormat options
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
constructor(template, localeStr = "iso", localeStyle = "medium") {
|
|
71
|
+
super(template);
|
|
72
|
+
const supported_locales = Intl.DateTimeFormat.supportedLocalesOf([localeStr]);
|
|
73
|
+
let locale_opts;
|
|
74
|
+
if (typeof localeStyle == "string") {
|
|
75
|
+
locale_opts = { dateStyle: localeStyle, timeStyle: localeStyle };
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
locale_opts = localeStyle;
|
|
79
|
+
}
|
|
80
|
+
if ((localeStr == "iso") || (localeStr == "") || (supported_locales.length == 0)) {
|
|
81
|
+
this._locale = null;
|
|
82
|
+
this.localeStr = "iso";
|
|
83
|
+
}
|
|
84
|
+
else if (localeStr == "default") {
|
|
85
|
+
this._locale = new Intl.DateTimeFormat(undefined, locale_opts);
|
|
86
|
+
this.localeStr = "default";
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.localeStr = supported_locales[0];
|
|
90
|
+
this._locale = new Intl.DateTimeFormat(supported_locales[0], locale_opts);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
58
93
|
/**
|
|
59
94
|
* Creates HTML Response from API modelset.
|
|
60
95
|
*
|
|
@@ -84,7 +119,13 @@ export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
|
84
119
|
// let html_row:string = this.template.replaceAll('###' + OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###')
|
|
85
120
|
for (let i = 0; i < datamodel.fields.length; i++) {
|
|
86
121
|
const f = datamodel.fields[i];
|
|
87
|
-
let value
|
|
122
|
+
let value;
|
|
123
|
+
if ((this._locale != null) && (f instanceof OINODatetimeDataField)) {
|
|
124
|
+
value = f.serializeCellWithLocale(row[i], this._locale);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
value = f.serializeCell(row[i]);
|
|
128
|
+
}
|
|
88
129
|
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
89
130
|
if (value && (f instanceof OINONumberDataField) && (datamodel.api.hashid)) {
|
|
90
131
|
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed);
|
|
@@ -190,7 +231,7 @@ export class OINODbApi {
|
|
|
190
231
|
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut");
|
|
191
232
|
}
|
|
192
233
|
else {
|
|
193
|
-
result.data = new OINODbModelSet(this.datamodel, sql_res);
|
|
234
|
+
result.data = new OINODbModelSet(this.datamodel, sql_res, params.sqlParams);
|
|
194
235
|
}
|
|
195
236
|
}
|
|
196
237
|
catch (e) {
|
package/dist/esm/OINODbConfig.js
CHANGED
|
@@ -13,6 +13,8 @@ export class OINODbConfig {
|
|
|
13
13
|
static OINODB_SQL_LIMIT_PARAM = "oinosqllimit";
|
|
14
14
|
/** Name of the OINODbSqlAggregate-parameter in request */
|
|
15
15
|
static OINODB_SQL_AGGREGATE_PARAM = "oinosqlaggregate";
|
|
16
|
+
/** Name of the OINODbSqlSelect-parameter in request */
|
|
17
|
+
static OINODB_SQL_SELECT_PARAM = "oinosqlselect";
|
|
16
18
|
/**
|
|
17
19
|
* Set the name of the OINO ID field
|
|
18
20
|
* @param idField name of the OINO ID field
|
|
@@ -339,6 +339,29 @@ export class OINODatetimeDataField extends OINODbDataField {
|
|
|
339
339
|
return cellVal.toString();
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Serialize cell value in the given content format.
|
|
344
|
+
*
|
|
345
|
+
* @param cellVal cell value
|
|
346
|
+
* @param locale locale-object to format datetimes with
|
|
347
|
+
*
|
|
348
|
+
*/
|
|
349
|
+
serializeCellWithLocale(cellVal, locale) {
|
|
350
|
+
// OINOLog.debug("OINODatetimeDataField.serializeCell", {cellVal:cellVal, type:typeof(cellVal)})
|
|
351
|
+
if (typeof (cellVal) == "string") {
|
|
352
|
+
cellVal = this.db.parseSqlValueAsCell(cellVal, this.sqlType);
|
|
353
|
+
// OINOLog.debug("OINODatetimeDataField.serializeCell parsed", {cellVal:cellVal, type:typeof(cellVal)})
|
|
354
|
+
}
|
|
355
|
+
if ((cellVal === null) || (cellVal === undefined)) {
|
|
356
|
+
return cellVal;
|
|
357
|
+
}
|
|
358
|
+
else if (cellVal instanceof Date) {
|
|
359
|
+
return locale.format(cellVal);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
return cellVal.toString();
|
|
363
|
+
}
|
|
364
|
+
}
|
|
342
365
|
/**
|
|
343
366
|
* Parce cell value from string using field type specific formatting rules.
|
|
344
367
|
*
|
|
@@ -3,7 +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 { OINO_ERROR_PREFIX, OINODbConfig, OINONumberDataField } from "./index.js";
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINODbConfig, OINONumberDataField, OINODB_UNDEFINED } from "./index.js";
|
|
7
7
|
/**
|
|
8
8
|
* OINO Datamodel object for representing one database table and it's columns.
|
|
9
9
|
*
|
|
@@ -34,10 +34,16 @@ export class OINODbDataModel {
|
|
|
34
34
|
async initialize() {
|
|
35
35
|
await this.api.db.initializeApiDatamodel(this.api);
|
|
36
36
|
}
|
|
37
|
-
_printSqlColumnNames() {
|
|
37
|
+
_printSqlColumnNames(select) {
|
|
38
38
|
let result = "";
|
|
39
39
|
for (let i = 0; i < this.fields.length; i++) {
|
|
40
|
-
|
|
40
|
+
const f = this.fields[i];
|
|
41
|
+
if (select?.isSelected(f) === false) { // if a field is not selected, we include a constant and correct fieldname instead so that dimensions of the data don't change but no unnecessary data is fetched
|
|
42
|
+
result += f.db.printSqlString(OINODB_UNDEFINED) + " as " + f.printSqlColumnName() + ",";
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
result += f.printSqlColumnName() + ",";
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
return result.substring(0, result.length - 1);
|
|
43
49
|
}
|
|
@@ -216,17 +222,18 @@ export class OINODbDataModel {
|
|
|
216
222
|
printSqlSelect(id, params) {
|
|
217
223
|
let column_names = "";
|
|
218
224
|
if (params.aggregate) {
|
|
219
|
-
column_names = params.aggregate.printSqlColumnNames(this);
|
|
225
|
+
column_names = params.aggregate.printSqlColumnNames(this, params.select);
|
|
220
226
|
}
|
|
221
227
|
else {
|
|
222
|
-
column_names = this._printSqlColumnNames();
|
|
228
|
+
column_names = this._printSqlColumnNames(params.select);
|
|
223
229
|
}
|
|
230
|
+
// OINOLog.debug("OINODbDataModel.printSqlSelect", {column_names:column_names})
|
|
224
231
|
const order_sql = params.order?.toSql(this) || "";
|
|
225
232
|
const limit_sql = params.limit?.toSql(this) || "";
|
|
226
233
|
const filter_sql = params.filter?.toSql(this) || "";
|
|
227
234
|
const aggregate_sql = params.aggregate?.toSql(this) || "";
|
|
228
235
|
let where_sql = "";
|
|
229
|
-
// OINOLog.debug("OINODbDataModel.printSqlSelect", {
|
|
236
|
+
// OINOLog.debug("OINODbDataModel.printSqlSelect", {order_sql:order_sql, limit_sql:limit_sql, filter_sql:filter_sql, aggregate_sql:aggregate_sql})
|
|
230
237
|
if ((id != null) && (id != "") && (filter_sql != "")) {
|
|
231
238
|
where_sql = this._printSqlPrimaryKeyCondition(id) + " AND " + filter_sql;
|
|
232
239
|
}
|
|
@@ -3,8 +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 { OINODbApi, OINOContentType, OINODbSqlFilter, OINODbConfig, OINODbSqlOrder, OINODbSqlLimit } from "./index.js";
|
|
7
|
-
import { OINODbSqlAggregate } from "./OINODbSqlParams.js";
|
|
6
|
+
import { OINODbApi, OINOContentType, OINODbSqlFilter, OINODbConfig, OINODbSqlOrder, OINODbSqlLimit, OINODbSqlAggregate, OINODbSqlSelect } from "./index.js";
|
|
8
7
|
/**
|
|
9
8
|
* Static factory class for easily creating things based on data
|
|
10
9
|
*
|
|
@@ -74,6 +73,10 @@ export class OINODbFactory {
|
|
|
74
73
|
if (aggregate) {
|
|
75
74
|
sql_params.aggregate = OINODbSqlAggregate.parse(aggregate);
|
|
76
75
|
}
|
|
76
|
+
const select = url.searchParams.get(OINODbConfig.OINODB_SQL_SELECT_PARAM);
|
|
77
|
+
if (select) {
|
|
78
|
+
sql_params.select = OINODbSqlSelect.parse(select);
|
|
79
|
+
}
|
|
77
80
|
let result = { sqlParams: sql_params };
|
|
78
81
|
const content_type = request.headers.get("content-type");
|
|
79
82
|
if (content_type == OINOContentType.csv) {
|
|
@@ -16,6 +16,8 @@ export class OINODbModelSet {
|
|
|
16
16
|
datamodel;
|
|
17
17
|
/** Reference to data set */
|
|
18
18
|
dataset;
|
|
19
|
+
/** SQL parameters */
|
|
20
|
+
sqlParams;
|
|
19
21
|
/** Collection of errors */
|
|
20
22
|
errors;
|
|
21
23
|
/**
|
|
@@ -23,10 +25,12 @@ export class OINODbModelSet {
|
|
|
23
25
|
*
|
|
24
26
|
* @param datamodel data model
|
|
25
27
|
* @param dataset data set
|
|
28
|
+
* @param sqlParams SQL parameters
|
|
26
29
|
*/
|
|
27
|
-
constructor(datamodel, dataset) {
|
|
30
|
+
constructor(datamodel, dataset, sqlParams) {
|
|
28
31
|
this.datamodel = datamodel;
|
|
29
32
|
this.dataset = dataset;
|
|
33
|
+
this.sqlParams = sqlParams;
|
|
30
34
|
this.errors = this.dataset.messages;
|
|
31
35
|
}
|
|
32
36
|
_encodeAndHashFieldValue(field, value, contentType, primaryKeyValues, rowIdSeed) {
|
|
@@ -51,6 +55,9 @@ export class OINODbModelSet {
|
|
|
51
55
|
let json_row = "";
|
|
52
56
|
for (let i = 0; i < fields.length; i++) {
|
|
53
57
|
const f = fields[i];
|
|
58
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
54
61
|
let value = f.serializeCell(row[i]);
|
|
55
62
|
if (value === undefined) {
|
|
56
63
|
// OINOLog.info("OINODbModelSet._writeRowJson: undefined value skipped", {field_name:f.name})
|
|
@@ -106,6 +113,9 @@ export class OINODbModelSet {
|
|
|
106
113
|
let csv_row = "";
|
|
107
114
|
for (let i = 0; i < fields.length; i++) {
|
|
108
115
|
const f = fields[i];
|
|
116
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
109
119
|
let value = f.serializeCell(row[i]);
|
|
110
120
|
if (value == null) {
|
|
111
121
|
csv_row += "," + OINOStr.encode(value, OINOContentType.csv); // either null or undefined
|
|
@@ -154,6 +164,9 @@ export class OINODbModelSet {
|
|
|
154
164
|
let result = "";
|
|
155
165
|
for (let i = 0; i < fields.length; i++) {
|
|
156
166
|
const f = fields[i];
|
|
167
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
157
170
|
let value = f.serializeCell(row[i]);
|
|
158
171
|
let formdata_block = "";
|
|
159
172
|
let is_file = (f instanceof OINOBlobDataField);
|
|
@@ -193,6 +206,9 @@ export class OINODbModelSet {
|
|
|
193
206
|
let urlencode_row = "";
|
|
194
207
|
for (let i = 0; i < fields.length; i++) {
|
|
195
208
|
const f = fields[i];
|
|
209
|
+
if (this.sqlParams?.select?.isSelected(f) === false) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
196
212
|
let value = f.serializeCell(row[i]);
|
|
197
213
|
if ((value === undefined)) { // || (value === null)) {
|
|
198
214
|
// console.log("OINODbModelSet._writeRowUrlencode undefined field value:" + fields[i].name)
|