@oino-ts/db 0.19.0 → 0.20.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/OINODb.js +19 -1
- package/dist/cjs/OINODbApi.js +18 -15
- package/dist/cjs/OINODbDataModel.js +14 -3
- package/dist/cjs/index.js +1 -1
- package/dist/esm/OINODb.js +20 -2
- package/dist/esm/OINODbApi.js +18 -15
- package/dist/esm/OINODbDataModel.js +14 -3
- package/dist/esm/index.js +1 -1
- package/dist/types/OINODb.d.ts +16 -1
- package/dist/types/OINODbDataModel.d.ts +1 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +4 -4
- package/src/OINODb.ts +27 -1
- package/src/OINODbApi.test.ts +7 -2
- package/src/OINODbApi.ts +17 -15
- package/src/OINODbDataModel.ts +16 -4
- package/src/index.ts +4 -2
package/dist/cjs/OINODb.js
CHANGED
|
@@ -55,6 +55,23 @@ class OINODb {
|
|
|
55
55
|
result += ";";
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Print SQL select statement with DB specific formatting.
|
|
60
|
+
*
|
|
61
|
+
* @param tableName - The name of the table to select from.
|
|
62
|
+
* @param columns - The columns to be selected.
|
|
63
|
+
* @param values - The values to be inserted.
|
|
64
|
+
* @param returnIdFields - the id fields to return if returnIds is true (if supported by the database)
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
printSqlInsert(tableName, columns, values, returnIdFields) {
|
|
68
|
+
let result = "INSERT INTO " + tableName + " (" + columns + ") VALUES (" + values + ")";
|
|
69
|
+
if (returnIdFields) {
|
|
70
|
+
result += " RETURNING " + returnIdFields.join(",");
|
|
71
|
+
}
|
|
72
|
+
result += ";";
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
58
75
|
}
|
|
59
76
|
exports.OINODb = OINODb;
|
|
60
77
|
/**
|
|
@@ -65,7 +82,7 @@ exports.OINODb = OINODb;
|
|
|
65
82
|
* `OINODbDataSet` will serve it out consistently.
|
|
66
83
|
*
|
|
67
84
|
*/
|
|
68
|
-
class OINODbDataSet {
|
|
85
|
+
class OINODbDataSet extends common_1.OINOResult {
|
|
69
86
|
_data;
|
|
70
87
|
/** Error messages */
|
|
71
88
|
messages;
|
|
@@ -77,6 +94,7 @@ class OINODbDataSet {
|
|
|
77
94
|
*
|
|
78
95
|
*/
|
|
79
96
|
constructor(data, messages = []) {
|
|
97
|
+
super();
|
|
80
98
|
this._data = data;
|
|
81
99
|
this.messages = messages;
|
|
82
100
|
}
|
package/dist/cjs/OINODbApi.js
CHANGED
|
@@ -17,7 +17,7 @@ class OINODbApiRequest extends common_1.OINOHttpRequest {
|
|
|
17
17
|
constructor(init) {
|
|
18
18
|
super(init);
|
|
19
19
|
this.rowId = init?.rowId || "";
|
|
20
|
-
this.rowData = init?.rowData || null;
|
|
20
|
+
this.rowData = init?.rowData || null; // rowData is not compatible with OINOHttpRequest body so it's not automatically set, caller can set both if needed
|
|
21
21
|
this.sqlParams = init?.sqlParams || {};
|
|
22
22
|
if (init?.filter) {
|
|
23
23
|
if (init.filter instanceof index_js_1.OINODbSqlFilter) {
|
|
@@ -348,8 +348,8 @@ class OINODbApi {
|
|
|
348
348
|
sql = this.datamodel.printSqlSelect(rowId, request.sqlParams || {});
|
|
349
349
|
common_1.OINOLog.debug("@oino-ts/db", "OINODbApi", "_doGet", "Print SQL", { sql: sql });
|
|
350
350
|
const sql_res = await this.db.sqlSelect(sql);
|
|
351
|
-
if (sql_res.
|
|
352
|
-
result.setError(500, sql_res.
|
|
351
|
+
if (sql_res.success == false) {
|
|
352
|
+
result.setError(500, sql_res.statusText, "DoGet");
|
|
353
353
|
if (this._debugOnError) {
|
|
354
354
|
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut");
|
|
355
355
|
}
|
|
@@ -366,7 +366,7 @@ class OINODbApi {
|
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
-
async _doPost(result, rows) {
|
|
369
|
+
async _doPost(result, rows, request) {
|
|
370
370
|
let sql = "";
|
|
371
371
|
try {
|
|
372
372
|
for (let i = 0; i < rows.length; i++) {
|
|
@@ -384,13 +384,16 @@ class OINODbApi {
|
|
|
384
384
|
else if (result.success) {
|
|
385
385
|
common_1.OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPost", "Print SQL", { sql: sql });
|
|
386
386
|
const sql_res = await this.db.sqlExec(sql);
|
|
387
|
-
if (sql_res.
|
|
388
|
-
result.setError(500, sql_res.
|
|
387
|
+
if (sql_res.success == false) {
|
|
388
|
+
result.setError(500, sql_res.statusText, "DoPost");
|
|
389
389
|
if (this._debugOnError) {
|
|
390
|
-
result.addDebug("OINO POST MESSAGES [" + sql_res.
|
|
390
|
+
result.addDebug("OINO POST MESSAGES [" + sql_res.statusText + "]", "DoPost");
|
|
391
391
|
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost");
|
|
392
392
|
}
|
|
393
393
|
}
|
|
394
|
+
else if (this.params.returnInsertedIds) {
|
|
395
|
+
result.data = new index_js_1.OINODbModelSet(this.datamodel, sql_res, request.sqlParams); // return the inserted ids as data
|
|
396
|
+
}
|
|
394
397
|
}
|
|
395
398
|
}
|
|
396
399
|
catch (e) {
|
|
@@ -421,10 +424,10 @@ class OINODbApi {
|
|
|
421
424
|
else if (result.success) {
|
|
422
425
|
common_1.OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPut", "Print SQL", { sql: sql });
|
|
423
426
|
const sql_res = await this.db.sqlExec(sql);
|
|
424
|
-
if (sql_res.
|
|
425
|
-
result.setError(500, sql_res.
|
|
427
|
+
if (sql_res.success == false) {
|
|
428
|
+
result.setError(500, sql_res.statusText, "DoPut");
|
|
426
429
|
if (this._debugOnError) {
|
|
427
|
-
result.addDebug("OINO PUT MESSAGES [" + sql_res.
|
|
430
|
+
result.addDebug("OINO PUT MESSAGES [" + sql_res.statusText + "]", "DoPut");
|
|
428
431
|
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut");
|
|
429
432
|
}
|
|
430
433
|
}
|
|
@@ -434,7 +437,7 @@ class OINODbApi {
|
|
|
434
437
|
result.setError(500, "Unhandled exception: " + e.message, "DoPut");
|
|
435
438
|
common_1.OINOLog.exception("@oino-ts/db", "OINODbApi", "_doPut", "exception in put request", { message: e.message, stack: e.stack });
|
|
436
439
|
if (this._debugOnError) {
|
|
437
|
-
result.addDebug("OINO
|
|
440
|
+
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut");
|
|
438
441
|
}
|
|
439
442
|
}
|
|
440
443
|
}
|
|
@@ -461,10 +464,10 @@ class OINODbApi {
|
|
|
461
464
|
else if (result.success) {
|
|
462
465
|
common_1.OINOLog.debug("@oino-ts/db", "OINODbApi", "_doDelete", "Print SQL", { sql: sql });
|
|
463
466
|
const sql_res = await this.db.sqlExec(sql);
|
|
464
|
-
if (sql_res.
|
|
465
|
-
result.setError(500, sql_res.
|
|
467
|
+
if (sql_res.success == false) {
|
|
468
|
+
result.setError(500, sql_res.statusText, "DoDelete");
|
|
466
469
|
if (this._debugOnError) {
|
|
467
|
-
result.addDebug("OINO DELETE MESSAGES [" + sql_res.
|
|
470
|
+
result.addDebug("OINO DELETE MESSAGES [" + sql_res.statusText + "]", "DoDelete");
|
|
468
471
|
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete");
|
|
469
472
|
}
|
|
470
473
|
}
|
|
@@ -550,7 +553,7 @@ class OINODbApi {
|
|
|
550
553
|
}
|
|
551
554
|
else {
|
|
552
555
|
try {
|
|
553
|
-
await this._doPost(result, rows);
|
|
556
|
+
await this._doPost(result, rows, request);
|
|
554
557
|
}
|
|
555
558
|
catch (e) {
|
|
556
559
|
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest");
|
|
@@ -67,7 +67,7 @@ class OINODbDataModel {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
// console.log("_printSqlInsertColumnsAndValues: columns=" + columns + ", values=" + values)
|
|
70
|
-
return
|
|
70
|
+
return [columns, values];
|
|
71
71
|
}
|
|
72
72
|
_printSqlUpdateValues(row) {
|
|
73
73
|
let result = "";
|
|
@@ -109,6 +109,15 @@ class OINODbDataModel {
|
|
|
109
109
|
}
|
|
110
110
|
return "(" + result + ")";
|
|
111
111
|
}
|
|
112
|
+
_printSqlPrimaryKeyColumns() {
|
|
113
|
+
let result = [];
|
|
114
|
+
for (let f of this.fields) {
|
|
115
|
+
if (f.fieldParams.isPrimaryKey) {
|
|
116
|
+
result.push(this.api.db.printSqlColumnname(f.name));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
112
121
|
/**
|
|
113
122
|
* Add a field to the datamodel.
|
|
114
123
|
*
|
|
@@ -255,8 +264,10 @@ class OINODbDataModel {
|
|
|
255
264
|
*
|
|
256
265
|
*/
|
|
257
266
|
printSqlInsert(row) {
|
|
258
|
-
|
|
259
|
-
|
|
267
|
+
const table_name = this.api.db.printSqlTablename(this.api.params.tableName);
|
|
268
|
+
const [columns, values] = this._printSqlInsertColumnsAndValues(row);
|
|
269
|
+
const return_fields = this.api.params.returnInsertedIds ? this._printSqlPrimaryKeyColumns() : undefined;
|
|
270
|
+
return this.api.db.printSqlInsert(table_name, columns, values, return_fields);
|
|
260
271
|
}
|
|
261
272
|
/**
|
|
262
273
|
* Print SQL insert statement from one data row.
|
package/dist/cjs/index.js
CHANGED
|
@@ -42,6 +42,6 @@ Object.defineProperty(exports, "OINODbParser", { enumerable: true, get: function
|
|
|
42
42
|
/** Empty row instance */
|
|
43
43
|
exports.OINODB_EMPTY_ROW = [];
|
|
44
44
|
/** Empty row array instance */
|
|
45
|
-
exports.OINODB_EMPTY_ROWS = [
|
|
45
|
+
exports.OINODB_EMPTY_ROWS = [];
|
|
46
46
|
/** Constant for undefined values */
|
|
47
47
|
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/OINODb.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 { OINO_ERROR_PREFIX } from "@oino-ts/common";
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINOResult } from "@oino-ts/common";
|
|
7
7
|
import { OINODB_EMPTY_ROW } from "./index.js";
|
|
8
8
|
/**
|
|
9
9
|
* Base class for database abstraction, implementing methods for connecting, making queries and parsing/formatting data
|
|
@@ -52,6 +52,23 @@ export class OINODb {
|
|
|
52
52
|
result += ";";
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Print SQL select statement with DB specific formatting.
|
|
57
|
+
*
|
|
58
|
+
* @param tableName - The name of the table to select from.
|
|
59
|
+
* @param columns - The columns to be selected.
|
|
60
|
+
* @param values - The values to be inserted.
|
|
61
|
+
* @param returnIdFields - the id fields to return if returnIds is true (if supported by the database)
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
printSqlInsert(tableName, columns, values, returnIdFields) {
|
|
65
|
+
let result = "INSERT INTO " + tableName + " (" + columns + ") VALUES (" + values + ")";
|
|
66
|
+
if (returnIdFields) {
|
|
67
|
+
result += " RETURNING " + returnIdFields.join(",");
|
|
68
|
+
}
|
|
69
|
+
result += ";";
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
55
72
|
}
|
|
56
73
|
/**
|
|
57
74
|
* Base class for SQL results that can be asynchronously iterated (but
|
|
@@ -61,7 +78,7 @@ export class OINODb {
|
|
|
61
78
|
* `OINODbDataSet` will serve it out consistently.
|
|
62
79
|
*
|
|
63
80
|
*/
|
|
64
|
-
export class OINODbDataSet {
|
|
81
|
+
export class OINODbDataSet extends OINOResult {
|
|
65
82
|
_data;
|
|
66
83
|
/** Error messages */
|
|
67
84
|
messages;
|
|
@@ -73,6 +90,7 @@ export class OINODbDataSet {
|
|
|
73
90
|
*
|
|
74
91
|
*/
|
|
75
92
|
constructor(data, messages = []) {
|
|
93
|
+
super();
|
|
76
94
|
this._data = data;
|
|
77
95
|
this.messages = messages;
|
|
78
96
|
}
|
package/dist/esm/OINODbApi.js
CHANGED
|
@@ -14,7 +14,7 @@ export class OINODbApiRequest extends OINOHttpRequest {
|
|
|
14
14
|
constructor(init) {
|
|
15
15
|
super(init);
|
|
16
16
|
this.rowId = init?.rowId || "";
|
|
17
|
-
this.rowData = init?.rowData || null;
|
|
17
|
+
this.rowData = init?.rowData || null; // rowData is not compatible with OINOHttpRequest body so it's not automatically set, caller can set both if needed
|
|
18
18
|
this.sqlParams = init?.sqlParams || {};
|
|
19
19
|
if (init?.filter) {
|
|
20
20
|
if (init.filter instanceof OINODbSqlFilter) {
|
|
@@ -342,8 +342,8 @@ export class OINODbApi {
|
|
|
342
342
|
sql = this.datamodel.printSqlSelect(rowId, request.sqlParams || {});
|
|
343
343
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doGet", "Print SQL", { sql: sql });
|
|
344
344
|
const sql_res = await this.db.sqlSelect(sql);
|
|
345
|
-
if (sql_res.
|
|
346
|
-
result.setError(500, sql_res.
|
|
345
|
+
if (sql_res.success == false) {
|
|
346
|
+
result.setError(500, sql_res.statusText, "DoGet");
|
|
347
347
|
if (this._debugOnError) {
|
|
348
348
|
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut");
|
|
349
349
|
}
|
|
@@ -360,7 +360,7 @@ export class OINODbApi {
|
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
|
-
async _doPost(result, rows) {
|
|
363
|
+
async _doPost(result, rows, request) {
|
|
364
364
|
let sql = "";
|
|
365
365
|
try {
|
|
366
366
|
for (let i = 0; i < rows.length; i++) {
|
|
@@ -378,13 +378,16 @@ export class OINODbApi {
|
|
|
378
378
|
else if (result.success) {
|
|
379
379
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPost", "Print SQL", { sql: sql });
|
|
380
380
|
const sql_res = await this.db.sqlExec(sql);
|
|
381
|
-
if (sql_res.
|
|
382
|
-
result.setError(500, sql_res.
|
|
381
|
+
if (sql_res.success == false) {
|
|
382
|
+
result.setError(500, sql_res.statusText, "DoPost");
|
|
383
383
|
if (this._debugOnError) {
|
|
384
|
-
result.addDebug("OINO POST MESSAGES [" + sql_res.
|
|
384
|
+
result.addDebug("OINO POST MESSAGES [" + sql_res.statusText + "]", "DoPost");
|
|
385
385
|
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost");
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
|
+
else if (this.params.returnInsertedIds) {
|
|
389
|
+
result.data = new OINODbModelSet(this.datamodel, sql_res, request.sqlParams); // return the inserted ids as data
|
|
390
|
+
}
|
|
388
391
|
}
|
|
389
392
|
}
|
|
390
393
|
catch (e) {
|
|
@@ -415,10 +418,10 @@ export class OINODbApi {
|
|
|
415
418
|
else if (result.success) {
|
|
416
419
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPut", "Print SQL", { sql: sql });
|
|
417
420
|
const sql_res = await this.db.sqlExec(sql);
|
|
418
|
-
if (sql_res.
|
|
419
|
-
result.setError(500, sql_res.
|
|
421
|
+
if (sql_res.success == false) {
|
|
422
|
+
result.setError(500, sql_res.statusText, "DoPut");
|
|
420
423
|
if (this._debugOnError) {
|
|
421
|
-
result.addDebug("OINO PUT MESSAGES [" + sql_res.
|
|
424
|
+
result.addDebug("OINO PUT MESSAGES [" + sql_res.statusText + "]", "DoPut");
|
|
422
425
|
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut");
|
|
423
426
|
}
|
|
424
427
|
}
|
|
@@ -428,7 +431,7 @@ export class OINODbApi {
|
|
|
428
431
|
result.setError(500, "Unhandled exception: " + e.message, "DoPut");
|
|
429
432
|
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doPut", "exception in put request", { message: e.message, stack: e.stack });
|
|
430
433
|
if (this._debugOnError) {
|
|
431
|
-
result.addDebug("OINO
|
|
434
|
+
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut");
|
|
432
435
|
}
|
|
433
436
|
}
|
|
434
437
|
}
|
|
@@ -455,10 +458,10 @@ export class OINODbApi {
|
|
|
455
458
|
else if (result.success) {
|
|
456
459
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doDelete", "Print SQL", { sql: sql });
|
|
457
460
|
const sql_res = await this.db.sqlExec(sql);
|
|
458
|
-
if (sql_res.
|
|
459
|
-
result.setError(500, sql_res.
|
|
461
|
+
if (sql_res.success == false) {
|
|
462
|
+
result.setError(500, sql_res.statusText, "DoDelete");
|
|
460
463
|
if (this._debugOnError) {
|
|
461
|
-
result.addDebug("OINO DELETE MESSAGES [" + sql_res.
|
|
464
|
+
result.addDebug("OINO DELETE MESSAGES [" + sql_res.statusText + "]", "DoDelete");
|
|
462
465
|
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete");
|
|
463
466
|
}
|
|
464
467
|
}
|
|
@@ -544,7 +547,7 @@ export class OINODbApi {
|
|
|
544
547
|
}
|
|
545
548
|
else {
|
|
546
549
|
try {
|
|
547
|
-
await this._doPost(result, rows);
|
|
550
|
+
await this._doPost(result, rows, request);
|
|
548
551
|
}
|
|
549
552
|
catch (e) {
|
|
550
553
|
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest");
|
|
@@ -64,7 +64,7 @@ export class OINODbDataModel {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
// console.log("_printSqlInsertColumnsAndValues: columns=" + columns + ", values=" + values)
|
|
67
|
-
return
|
|
67
|
+
return [columns, values];
|
|
68
68
|
}
|
|
69
69
|
_printSqlUpdateValues(row) {
|
|
70
70
|
let result = "";
|
|
@@ -106,6 +106,15 @@ export class OINODbDataModel {
|
|
|
106
106
|
}
|
|
107
107
|
return "(" + result + ")";
|
|
108
108
|
}
|
|
109
|
+
_printSqlPrimaryKeyColumns() {
|
|
110
|
+
let result = [];
|
|
111
|
+
for (let f of this.fields) {
|
|
112
|
+
if (f.fieldParams.isPrimaryKey) {
|
|
113
|
+
result.push(this.api.db.printSqlColumnname(f.name));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
109
118
|
/**
|
|
110
119
|
* Add a field to the datamodel.
|
|
111
120
|
*
|
|
@@ -252,8 +261,10 @@ export class OINODbDataModel {
|
|
|
252
261
|
*
|
|
253
262
|
*/
|
|
254
263
|
printSqlInsert(row) {
|
|
255
|
-
|
|
256
|
-
|
|
264
|
+
const table_name = this.api.db.printSqlTablename(this.api.params.tableName);
|
|
265
|
+
const [columns, values] = this._printSqlInsertColumnsAndValues(row);
|
|
266
|
+
const return_fields = this.api.params.returnInsertedIds ? this._printSqlPrimaryKeyColumns() : undefined;
|
|
267
|
+
return this.api.db.printSqlInsert(table_name, columns, values, return_fields);
|
|
257
268
|
}
|
|
258
269
|
/**
|
|
259
270
|
* Print SQL insert statement from one data row.
|
package/dist/esm/index.js
CHANGED
|
@@ -11,6 +11,6 @@ export { OINODbParser } from "./OINODbParser.js";
|
|
|
11
11
|
/** Empty row instance */
|
|
12
12
|
export const OINODB_EMPTY_ROW = [];
|
|
13
13
|
/** Empty row array instance */
|
|
14
|
-
export const OINODB_EMPTY_ROWS = [
|
|
14
|
+
export const OINODB_EMPTY_ROWS = [];
|
|
15
15
|
/** Constant for undefined values */
|
|
16
16
|
export const 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/types/OINODb.d.ts
CHANGED
|
@@ -26,6 +26,11 @@ export declare abstract class OINODb {
|
|
|
26
26
|
*
|
|
27
27
|
*/
|
|
28
28
|
abstract validate(): Promise<OINOResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Disconnect from database.
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
abstract disconnect(): Promise<void>;
|
|
29
34
|
/**
|
|
30
35
|
* Print a table name using database specific SQL escaping.
|
|
31
36
|
*
|
|
@@ -99,6 +104,16 @@ export declare abstract class OINODb {
|
|
|
99
104
|
*
|
|
100
105
|
*/
|
|
101
106
|
printSqlSelect(tableName: string, columnNames: string, whereCondition: string, orderCondition: string, limitCondition: string, groupByCondition: string): string;
|
|
107
|
+
/**
|
|
108
|
+
* Print SQL select statement with DB specific formatting.
|
|
109
|
+
*
|
|
110
|
+
* @param tableName - The name of the table to select from.
|
|
111
|
+
* @param columns - The columns to be selected.
|
|
112
|
+
* @param values - The values to be inserted.
|
|
113
|
+
* @param returnIdFields - the id fields to return if returnIds is true (if supported by the database)
|
|
114
|
+
*
|
|
115
|
+
*/
|
|
116
|
+
printSqlInsert(tableName: string, columns: string, values: string, returnIdFields?: string[]): string;
|
|
102
117
|
}
|
|
103
118
|
/**
|
|
104
119
|
* Base class for SQL results that can be asynchronously iterated (but
|
|
@@ -108,7 +123,7 @@ export declare abstract class OINODb {
|
|
|
108
123
|
* `OINODbDataSet` will serve it out consistently.
|
|
109
124
|
*
|
|
110
125
|
*/
|
|
111
|
-
export declare abstract class OINODbDataSet {
|
|
126
|
+
export declare abstract class OINODbDataSet extends OINOResult {
|
|
112
127
|
private _data;
|
|
113
128
|
/** Error messages */
|
|
114
129
|
readonly messages: string[];
|
package/dist/types/index.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ export type OINODbApiParams = {
|
|
|
44
44
|
hashidStaticIds?: boolean;
|
|
45
45
|
/** Name of field that has the modified field */
|
|
46
46
|
cacheModifiedField?: string;
|
|
47
|
+
/** Return inserted id values */
|
|
48
|
+
returnInsertedIds?: boolean;
|
|
47
49
|
};
|
|
48
50
|
/**
|
|
49
51
|
* Database class (constructor) type
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oino-ts/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "OINO TS library package for publishing an SQL database tables as a REST API.",
|
|
5
5
|
"author": "Matias Kiviniemi (pragmatta)",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"module": "./dist/esm/index.js",
|
|
20
20
|
"types": "./dist/types/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@oino-ts/common": "0.
|
|
22
|
+
"@oino-ts/common": "0.20.0",
|
|
23
23
|
"oino-ts": "file:.."
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@oino-ts/types": "0.
|
|
26
|
+
"@oino-ts/types": "0.20.0",
|
|
27
27
|
"@types/bun": "^1.1.14",
|
|
28
|
-
"@types/node": "^20.
|
|
28
|
+
"@types/node": "^20.20.00",
|
|
29
29
|
"typescript": "~5.9.0"
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
package/src/OINODb.ts
CHANGED
|
@@ -43,6 +43,12 @@ export abstract class OINODb {
|
|
|
43
43
|
*/
|
|
44
44
|
abstract validate(): Promise<OINOResult>
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Disconnect from database.
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
abstract disconnect(): Promise<void>
|
|
51
|
+
|
|
46
52
|
/**
|
|
47
53
|
* Print a table name using database specific SQL escaping.
|
|
48
54
|
*
|
|
@@ -140,6 +146,25 @@ export abstract class OINODb {
|
|
|
140
146
|
result += ";"
|
|
141
147
|
return result;
|
|
142
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Print SQL select statement with DB specific formatting.
|
|
152
|
+
*
|
|
153
|
+
* @param tableName - The name of the table to select from.
|
|
154
|
+
* @param columns - The columns to be selected.
|
|
155
|
+
* @param values - The values to be inserted.
|
|
156
|
+
* @param returnIdFields - the id fields to return if returnIds is true (if supported by the database)
|
|
157
|
+
*
|
|
158
|
+
*/
|
|
159
|
+
printSqlInsert(tableName:string, columns:string, values:string, returnIdFields?:string[]): string {
|
|
160
|
+
let result = "INSERT INTO " + tableName + " (" + columns + ") VALUES (" + values + ")"
|
|
161
|
+
if (returnIdFields) {
|
|
162
|
+
result += " RETURNING " + returnIdFields.join(",")
|
|
163
|
+
}
|
|
164
|
+
result += ";"
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
|
|
143
168
|
}
|
|
144
169
|
|
|
145
170
|
/**
|
|
@@ -151,7 +176,7 @@ export abstract class OINODb {
|
|
|
151
176
|
*
|
|
152
177
|
*/
|
|
153
178
|
|
|
154
|
-
export abstract class OINODbDataSet {
|
|
179
|
+
export abstract class OINODbDataSet extends OINOResult {
|
|
155
180
|
private _data: unknown;
|
|
156
181
|
|
|
157
182
|
/** Error messages */
|
|
@@ -165,6 +190,7 @@ export abstract class OINODbDataSet {
|
|
|
165
190
|
*
|
|
166
191
|
*/
|
|
167
192
|
constructor(data: unknown, messages: string[] = []) {
|
|
193
|
+
super();
|
|
168
194
|
this._data = data;
|
|
169
195
|
this.messages = messages;
|
|
170
196
|
}
|
package/src/OINODbApi.test.ts
CHANGED
|
@@ -65,7 +65,7 @@ const API_TESTS:OINOTestParams[] = [
|
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
name: "API 3",
|
|
68
|
-
apiParams: { apiName: "Employees", tableName: "Employees", hashidKey: "12345678901234567890123456789012", hashidStaticIds:true },
|
|
68
|
+
apiParams: { apiName: "Employees", tableName: "Employees", hashidKey: "12345678901234567890123456789012", hashidStaticIds:true, returnInsertedIds:true },
|
|
69
69
|
sqlParams: { filter: OINODbSqlFilter.parse("(TitleOfCourtesy)-eq(Ms.)"), order: OINODbSqlOrder.parse("LastName asc"), limit: OINODbSqlLimit.parse("5") },
|
|
70
70
|
postRow: [99, "LastName", "FirstName", "Title", "TitleOfCourtesy", new Date("2024-04-06"), new Date("2024-04-07"), "Address", "City", "Region", 12345, "EU", "123 456 7890", "9876", Buffer.from("0001020304", "hex"), "Line1\nLine2", 1, "http://accweb/emmployees/lastnamefirstname.bmp"],
|
|
71
71
|
putRow: [99, "LastName2", "FirstName2", null, "TitleOfCourtesy2", new Date("2023-04-06"), new Date("2023-04-07"), "Address2", "City2", "Region2", 54321, "EU2", "234 567 8901", "8765", Buffer.from("0506070809", "hex"), "Line3\nLine4", 1, "http://accweb/emmployees/lastnamefirstname.bmp"],
|
|
@@ -260,7 +260,12 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
260
260
|
expect(encodeResult((await api.doApiRequest(post_request_with_id)))).toMatchSnapshot("POST")
|
|
261
261
|
})
|
|
262
262
|
await test(target_name + target_db + target_table + target_group + " insert", async () => {
|
|
263
|
-
|
|
263
|
+
const post_res = await api.doApiRequest(post_request)
|
|
264
|
+
if (testParams.apiParams.returnInsertedIds) {
|
|
265
|
+
expect(encodeData(await post_res.data?.writeString())).toMatchSnapshot("POST RETURN ID")
|
|
266
|
+
} else {
|
|
267
|
+
expect(encodeResult(post_res)).toMatchSnapshot("POST")
|
|
268
|
+
}
|
|
264
269
|
expect(encodeData(await (await api.doApiRequest(get_request_with_rowid)).data?.writeString())).toMatchSnapshot("GET JSON")
|
|
265
270
|
expect(encodeData(await (await api.doApiRequest(get_request_with_rowid)).data?.writeString(OINOContentType.csv))).toMatchSnapshot("GET CSV")
|
|
266
271
|
})
|
package/src/OINODbApi.ts
CHANGED
|
@@ -30,7 +30,7 @@ export class OINODbApiRequest extends OINOHttpRequest {
|
|
|
30
30
|
constructor (init: OINODbApiRequestInit) {
|
|
31
31
|
super(init)
|
|
32
32
|
this.rowId = init?.rowId || ""
|
|
33
|
-
this.rowData = init?.rowData || null
|
|
33
|
+
this.rowData = init?.rowData || null // rowData is not compatible with OINOHttpRequest body so it's not automatically set, caller can set both if needed
|
|
34
34
|
this.sqlParams = init?.sqlParams || {}
|
|
35
35
|
|
|
36
36
|
if (init?.filter) {
|
|
@@ -369,8 +369,8 @@ export class OINODbApi {
|
|
|
369
369
|
sql = this.datamodel.printSqlSelect(rowId, request.sqlParams || {})
|
|
370
370
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doGet", "Print SQL", {sql:sql})
|
|
371
371
|
const sql_res:OINODbDataSet = await this.db.sqlSelect(sql)
|
|
372
|
-
if (sql_res.
|
|
373
|
-
result.setError(500, sql_res.
|
|
372
|
+
if (sql_res.success == false) {
|
|
373
|
+
result.setError(500, sql_res.statusText, "DoGet")
|
|
374
374
|
if (this._debugOnError) {
|
|
375
375
|
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut")
|
|
376
376
|
}
|
|
@@ -386,7 +386,7 @@ export class OINODbApi {
|
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
private async _doPost(result:OINODbApiResult, rows:OINODataRow[]):Promise<void> {
|
|
389
|
+
private async _doPost(result:OINODbApiResult, rows:OINODataRow[], request:OINODbApiRequest):Promise<void> {
|
|
390
390
|
let sql:string = ""
|
|
391
391
|
try {
|
|
392
392
|
for (let i=0; i<rows.length; i++) {
|
|
@@ -404,12 +404,14 @@ export class OINODbApi {
|
|
|
404
404
|
} else if (result.success) {
|
|
405
405
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPost", "Print SQL", {sql:sql})
|
|
406
406
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
407
|
-
if (sql_res.
|
|
408
|
-
result.setError(500, sql_res.
|
|
407
|
+
if (sql_res.success == false) {
|
|
408
|
+
result.setError(500, sql_res.statusText, "DoPost")
|
|
409
409
|
if (this._debugOnError) {
|
|
410
|
-
result.addDebug("OINO POST MESSAGES [" + sql_res.
|
|
410
|
+
result.addDebug("OINO POST MESSAGES [" + sql_res.statusText + "]", "DoPost")
|
|
411
411
|
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
412
412
|
}
|
|
413
|
+
} else if (this.params.returnInsertedIds) {
|
|
414
|
+
result.data = new OINODbModelSet(this.datamodel, sql_res, request.sqlParams) // return the inserted ids as data
|
|
413
415
|
}
|
|
414
416
|
}
|
|
415
417
|
} catch (e:any) {
|
|
@@ -441,10 +443,10 @@ export class OINODbApi {
|
|
|
441
443
|
} else if (result.success) {
|
|
442
444
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPut", "Print SQL", {sql:sql})
|
|
443
445
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
444
|
-
if (sql_res.
|
|
445
|
-
result.setError(500, sql_res.
|
|
446
|
+
if (sql_res.success == false) {
|
|
447
|
+
result.setError(500, sql_res.statusText, "DoPut")
|
|
446
448
|
if (this._debugOnError) {
|
|
447
|
-
result.addDebug("OINO PUT MESSAGES [" + sql_res.
|
|
449
|
+
result.addDebug("OINO PUT MESSAGES [" + sql_res.statusText + "]", "DoPut")
|
|
448
450
|
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut")
|
|
449
451
|
}
|
|
450
452
|
}
|
|
@@ -453,7 +455,7 @@ export class OINODbApi {
|
|
|
453
455
|
result.setError(500, "Unhandled exception: " + e.message, "DoPut")
|
|
454
456
|
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doPut", "exception in put request", {message:e.message, stack:e.stack})
|
|
455
457
|
if (this._debugOnError) {
|
|
456
|
-
result.addDebug("OINO
|
|
458
|
+
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut")
|
|
457
459
|
}
|
|
458
460
|
}
|
|
459
461
|
}
|
|
@@ -480,10 +482,10 @@ export class OINODbApi {
|
|
|
480
482
|
|
|
481
483
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doDelete", "Print SQL", {sql:sql})
|
|
482
484
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
483
|
-
if (sql_res.
|
|
484
|
-
result.setError(500, sql_res.
|
|
485
|
+
if (sql_res.success == false) {
|
|
486
|
+
result.setError(500, sql_res.statusText, "DoDelete")
|
|
485
487
|
if (this._debugOnError) {
|
|
486
|
-
result.addDebug("OINO DELETE MESSAGES [" + sql_res.
|
|
488
|
+
result.addDebug("OINO DELETE MESSAGES [" + sql_res.statusText + "]", "DoDelete")
|
|
487
489
|
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
488
490
|
}
|
|
489
491
|
}
|
|
@@ -570,7 +572,7 @@ export class OINODbApi {
|
|
|
570
572
|
|
|
571
573
|
} else {
|
|
572
574
|
try {
|
|
573
|
-
await this._doPost(result, rows)
|
|
575
|
+
await this._doPost(result, rows, request)
|
|
574
576
|
|
|
575
577
|
} catch (e:any) {
|
|
576
578
|
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest")
|
package/src/OINODbDataModel.ts
CHANGED
|
@@ -53,7 +53,7 @@ export class OINODbDataModel {
|
|
|
53
53
|
return result.substring(0, result.length-1)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
private _printSqlInsertColumnsAndValues(row: OINODataRow): string {
|
|
56
|
+
private _printSqlInsertColumnsAndValues(row: OINODataRow): [string, string] {
|
|
57
57
|
let columns: string = "";
|
|
58
58
|
let values: string = "";
|
|
59
59
|
for (let i=0; i< this.fields.length; i++) {
|
|
@@ -70,7 +70,7 @@ export class OINODbDataModel {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
// console.log("_printSqlInsertColumnsAndValues: columns=" + columns + ", values=" + values)
|
|
73
|
-
return
|
|
73
|
+
return [ columns, values ]
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
private _printSqlUpdateValues(row: OINODataRow): string {
|
|
@@ -115,6 +115,16 @@ export class OINODbDataModel {
|
|
|
115
115
|
return "(" + result + ")";
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
private _printSqlPrimaryKeyColumns(): string[] {
|
|
119
|
+
let result: string[] = []
|
|
120
|
+
for (let f of this.fields) {
|
|
121
|
+
if (f.fieldParams.isPrimaryKey) {
|
|
122
|
+
result.push(this.api.db.printSqlColumnname(f.name))
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
/**
|
|
119
129
|
* Add a field to the datamodel.
|
|
120
130
|
*
|
|
@@ -263,8 +273,10 @@ export class OINODbDataModel {
|
|
|
263
273
|
*
|
|
264
274
|
*/
|
|
265
275
|
printSqlInsert(row: OINODataRow): string {
|
|
266
|
-
|
|
267
|
-
|
|
276
|
+
const table_name = this.api.db.printSqlTablename(this.api.params.tableName)
|
|
277
|
+
const [columns, values] = this._printSqlInsertColumnsAndValues(row)
|
|
278
|
+
const return_fields = this.api.params.returnInsertedIds ? this._printSqlPrimaryKeyColumns() : undefined
|
|
279
|
+
return this.api.db.printSqlInsert(table_name, columns, values, return_fields);
|
|
268
280
|
}
|
|
269
281
|
|
|
270
282
|
/**
|
package/src/index.ts
CHANGED
|
@@ -43,7 +43,9 @@ export type OINODbApiParams = {
|
|
|
43
43
|
/** Make hashids static per row/table */
|
|
44
44
|
hashidStaticIds?: boolean,
|
|
45
45
|
/** Name of field that has the modified field */
|
|
46
|
-
cacheModifiedField?:string
|
|
46
|
+
cacheModifiedField?:string,
|
|
47
|
+
/** Return inserted id values */
|
|
48
|
+
returnInsertedIds?: boolean
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/**
|
|
@@ -107,7 +109,7 @@ export type OINODataRow = Array<OINODataCell>
|
|
|
107
109
|
/** Empty row instance */
|
|
108
110
|
export const OINODB_EMPTY_ROW:OINODataRow = []
|
|
109
111
|
/** Empty row array instance */
|
|
110
|
-
export const OINODB_EMPTY_ROWS:OINODataRow[] = [
|
|
112
|
+
export const OINODB_EMPTY_ROWS:OINODataRow[] = []
|
|
111
113
|
/** Constant for undefined values */
|
|
112
114
|
export const 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)
|
|
113
115
|
|