@oino-ts/db 0.3.3 → 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.
Files changed (39) hide show
  1. package/dist/cjs/OINODb.js +3 -3
  2. package/dist/cjs/OINODbApi.js +43 -2
  3. package/dist/cjs/OINODbConfig.js +2 -0
  4. package/dist/cjs/OINODbDataField.js +23 -0
  5. package/dist/cjs/OINODbDataModel.js +12 -5
  6. package/dist/cjs/OINODbFactory.js +5 -2
  7. package/dist/cjs/OINODbModelSet.js +17 -1
  8. package/dist/cjs/OINODbSqlParams.js +76 -11
  9. package/dist/cjs/index.js +4 -1
  10. package/dist/esm/OINODb.js +3 -3
  11. package/dist/esm/OINODbApi.js +44 -3
  12. package/dist/esm/OINODbConfig.js +2 -0
  13. package/dist/esm/OINODbDataField.js +23 -0
  14. package/dist/esm/OINODbDataModel.js +13 -6
  15. package/dist/esm/OINODbFactory.js +5 -2
  16. package/dist/esm/OINODbModelSet.js +17 -1
  17. package/dist/esm/OINODbSqlParams.js +75 -11
  18. package/dist/esm/index.js +3 -1
  19. package/dist/types/OINODb.d.ts +7 -0
  20. package/dist/types/OINODbApi.d.ts +13 -0
  21. package/dist/types/OINODbConfig.d.ts +2 -0
  22. package/dist/types/OINODbDataField.d.ts +8 -0
  23. package/dist/types/OINODbModelSet.d.ts +5 -2
  24. package/dist/types/OINODbSqlParams.d.ts +44 -4
  25. package/dist/types/index.d.ts +6 -2
  26. package/package.json +36 -36
  27. package/src/OINODb.ts +299 -291
  28. package/src/OINODbApi.test.ts +427 -411
  29. package/src/OINODbApi.ts +423 -384
  30. package/src/OINODbConfig.ts +98 -95
  31. package/src/OINODbDataField.ts +406 -382
  32. package/src/OINODbDataModel.ts +295 -289
  33. package/src/OINODbFactory.ts +127 -124
  34. package/src/OINODbModelSet.ts +315 -298
  35. package/src/OINODbParser.ts +457 -457
  36. package/src/OINODbSqlParams.ts +505 -437
  37. package/src/OINODbSwagger.ts +208 -208
  38. package/src/index.ts +134 -130
  39. package/README.md +0 -190
@@ -41,15 +41,15 @@ class OINODb {
41
41
  if (whereCondition != "") {
42
42
  result += " WHERE " + whereCondition;
43
43
  }
44
+ if (groupByCondition != "") {
45
+ result += " GROUP BY " + groupByCondition;
46
+ }
44
47
  if (orderCondition != "") {
45
48
  result += " ORDER BY " + orderCondition;
46
49
  }
47
50
  if (limitCondition != "") {
48
51
  result += " LIMIT " + limitCondition;
49
52
  }
50
- if (groupByCondition != "") {
51
- result += " GROUP BY " + groupByCondition;
52
- }
53
53
  result += ";";
54
54
  // OINOLog.debug("OINODb.printSqlSelect", {result:result})
55
55
  return result;
@@ -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 = f.serializeCell(row[i]);
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) {
@@ -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
- result += this.fields[i].printSqlColumnName() + ",";
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", {id:id, select_sql:result, filter_sql:filter_sql, order_sql:order_sql})
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 = OINODbSqlParams_js_1.OINODbSqlAggregate.parse(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
  /**
@@ -359,12 +359,12 @@ class OINODbSqlAggregate {
359
359
  /**
360
360
  * Constructor for `OINODbSqlAggregate`.
361
361
  *
362
- * @param function aggregate function to use
362
+ * @param functions aggregate function to use
363
363
  * @param fields fields to aggregate
364
364
  *
365
365
  */
366
- constructor(func, fields) {
367
- this._functions = func;
366
+ constructor(functions, fields) {
367
+ this._functions = functions;
368
368
  this._fields = fields;
369
369
  }
370
370
  /**
@@ -410,28 +410,93 @@ class OINODbSqlAggregate {
410
410
  result += dataModel.fields[i].printSqlColumnName() + ",";
411
411
  }
412
412
  }
413
- index_js_1.OINOLog.debug("OINODbSqlAggregate.toSql", { result: result });
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 aggregate_index = this._fields.indexOf(dataModel.fields[i].name);
426
- if (aggregate_index >= 0) {
427
- result += this._functions[aggregate_index] + "(" + dataModel.fields[i].printSqlColumnName() + "),";
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() + ",";
428
429
  }
429
430
  else {
430
- result += dataModel.fields[i].printSqlColumnName() + ",";
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
+ }
431
439
  }
432
440
  }
433
- index_js_1.OINOLog.debug("OINODbSqlAggregate.printSqlColumnNames", { result: result });
441
+ // OINOLog.debug("OINODbSqlAggregate.printSqlColumnNames", {result:result})
434
442
  return result.substring(0, result.length - 1);
435
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
+ }
436
452
  }
437
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)
@@ -38,15 +38,15 @@ export class OINODb {
38
38
  if (whereCondition != "") {
39
39
  result += " WHERE " + whereCondition;
40
40
  }
41
+ if (groupByCondition != "") {
42
+ result += " GROUP BY " + groupByCondition;
43
+ }
41
44
  if (orderCondition != "") {
42
45
  result += " ORDER BY " + orderCondition;
43
46
  }
44
47
  if (limitCondition != "") {
45
48
  result += " LIMIT " + limitCondition;
46
49
  }
47
- if (groupByCondition != "") {
48
- result += " GROUP BY " + groupByCondition;
49
- }
50
50
  result += ";";
51
51
  // OINOLog.debug("OINODb.printSqlSelect", {result:result})
52
52
  return result;
@@ -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 = f.serializeCell(row[i]);
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) {
@@ -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
- result += this.fields[i].printSqlColumnName() + ",";
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", {id:id, select_sql:result, filter_sql:filter_sql, order_sql:order_sql})
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) {