@oino-ts/db 0.21.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/OINODb.js +6 -144
- package/dist/cjs/OINODbApi.js +50 -318
- package/dist/cjs/OINODbConfig.js +10 -10
- package/dist/cjs/OINODbConstants.js +10 -0
- package/dist/cjs/OINODbDataField.js +28 -70
- package/dist/cjs/OINODbDataModel.js +29 -143
- package/dist/cjs/OINODbFactory.js +2 -2
- package/dist/cjs/OINODbModelSet.js +23 -23
- package/dist/cjs/OINODbQueryParams.js +201 -0
- package/dist/cjs/index.js +12 -41
- package/dist/esm/OINODb.js +6 -142
- package/dist/esm/OINODbApi.js +49 -314
- package/dist/esm/OINODbConstants.js +7 -0
- package/dist/esm/OINODbDataModel.js +29 -143
- package/dist/esm/OINODbFactory.js +1 -1
- package/dist/esm/OINODbQueryParams.js +194 -0
- package/dist/esm/index.js +4 -14
- package/dist/types/OINODb.d.ts +6 -173
- package/dist/types/OINODbApi.d.ts +18 -104
- package/dist/types/OINODbConstants.d.ts +23 -0
- package/dist/types/OINODbDataModel.d.ts +7 -61
- package/dist/types/OINODbFactory.d.ts +5 -2
- package/dist/types/OINODbQueryParams.d.ts +72 -0
- package/dist/types/index.d.ts +4 -108
- package/package.json +37 -37
- package/src/OINODb.ts +99 -348
- package/src/OINODbApi.test.ts +507 -498
- package/src/OINODbApi.ts +389 -667
- package/src/OINODbConstants.ts +32 -0
- package/src/OINODbDataModel.ts +191 -307
- package/src/OINODbFactory.ts +73 -68
- package/src/OINODbQueryParams.ts +203 -0
- package/src/index.ts +6 -118
- package/src/OINODbConfig.ts +0 -98
- package/src/OINODbDataField.ts +0 -405
- package/src/OINODbModelSet.ts +0 -353
- package/src/OINODbParser.ts +0 -438
- package/src/OINODbSqlParams.ts +0 -593
- package/src/OINODbSwagger.ts +0 -209
package/dist/esm/OINODbApi.js
CHANGED
|
@@ -3,277 +3,18 @@
|
|
|
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 {
|
|
7
|
-
import { OINOLog, OINOResult, OINOHttpRequest, OINOBenchmark, OINOHtmlTemplate, OINOContentType, OINO_ERROR_PREFIX } from "@oino-ts/common";
|
|
8
|
-
import { OINODbDataModel, OINOStringDataField, OINODbModelSet, OINODbConfig, OINONumberDataField, OINODbParser, OINODatetimeDataField, OINODbSqlAggregate, OINODbSqlSelect, OINODbSqlFilter, OINODbSqlOrder, OINODbSqlLimit, OINODbSqlBooleanOperation } from "./index.js";
|
|
9
|
-
import { OINOHashid } from "@oino-ts/hashid";
|
|
10
|
-
export class OINODbApiRequest extends OINOHttpRequest {
|
|
11
|
-
rowId;
|
|
12
|
-
rowData;
|
|
13
|
-
sqlParams;
|
|
14
|
-
constructor(init) {
|
|
15
|
-
super(init);
|
|
16
|
-
this.rowId = init?.rowId || "";
|
|
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
|
-
this.sqlParams = init?.sqlParams || {};
|
|
19
|
-
if (init?.filter) {
|
|
20
|
-
if (init.filter instanceof OINODbSqlFilter) {
|
|
21
|
-
this.sqlParams.filter = init.filter;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
this.sqlParams.filter = OINODbSqlFilter.parse(init.filter);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (!this.sqlParams.filter) {
|
|
28
|
-
const filter_params = this.url?.searchParams.getAll(OINODbConfig.OINODB_SQL_FILTER_PARAM) || [];
|
|
29
|
-
for (let i = 0; i < filter_params.length; i++) {
|
|
30
|
-
const f = OINODbSqlFilter.parse(filter_params[i]);
|
|
31
|
-
if (i > 0) {
|
|
32
|
-
this.sqlParams.filter = OINODbSqlFilter.combine(this.sqlParams.filter, OINODbSqlBooleanOperation.and, f);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
this.sqlParams.filter = f;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (init?.order) {
|
|
40
|
-
if (init.order instanceof OINODbSqlOrder) {
|
|
41
|
-
this.sqlParams.order = init.order;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
this.sqlParams.order = OINODbSqlOrder.parse(init.order);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
if (!this.sqlParams.order) {
|
|
48
|
-
const order_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_ORDER_PARAM);
|
|
49
|
-
if (order_param) {
|
|
50
|
-
this.sqlParams.order = OINODbSqlOrder.parse(order_param);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
if (init?.limit) {
|
|
54
|
-
if (init.limit instanceof OINODbSqlLimit) {
|
|
55
|
-
this.sqlParams.limit = init.limit;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
this.sqlParams.limit = OINODbSqlLimit.parse(init.limit);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (!this.sqlParams.limit) {
|
|
62
|
-
const limit_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_LIMIT_PARAM);
|
|
63
|
-
if (limit_param) {
|
|
64
|
-
this.sqlParams.limit = OINODbSqlLimit.parse(limit_param);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (init?.aggregate) {
|
|
68
|
-
if (init.aggregate instanceof OINODbSqlAggregate) {
|
|
69
|
-
this.sqlParams.aggregate = init.aggregate;
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
this.sqlParams.aggregate = OINODbSqlAggregate.parse(init.aggregate);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
if (!this.sqlParams.aggregate) {
|
|
76
|
-
const aggregate_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_AGGREGATE_PARAM);
|
|
77
|
-
if (aggregate_param) {
|
|
78
|
-
this.sqlParams.aggregate = OINODbSqlAggregate.parse(aggregate_param);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (init?.select) {
|
|
82
|
-
if (init.select instanceof OINODbSqlSelect) {
|
|
83
|
-
this.sqlParams.select = init.select;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.sqlParams.select = OINODbSqlSelect.parse(init.select);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (!this.sqlParams.select) {
|
|
90
|
-
const select_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_SELECT_PARAM);
|
|
91
|
-
if (select_param) {
|
|
92
|
-
this.sqlParams.select = OINODbSqlSelect.parse(select_param);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
static async fromFetchRequest(request, rowId, rowData, sqlParams) {
|
|
97
|
-
return new OINODbApiRequest({
|
|
98
|
-
url: new URL(request.url),
|
|
99
|
-
method: request.method,
|
|
100
|
-
headers: Object.fromEntries(request.headers),
|
|
101
|
-
rowId: rowId,
|
|
102
|
-
rowData: rowData ?? Buffer.from(await request.arrayBuffer()),
|
|
103
|
-
sqlParams: sqlParams
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
static fromHttpRequest(request, rowId, rowData, sqlParams) {
|
|
107
|
-
return new OINODbApiRequest({
|
|
108
|
-
url: typeof request.url === "string" ? new URL(request.url) : request.url,
|
|
109
|
-
method: request.method,
|
|
110
|
-
headers: Object.fromEntries(request.headers),
|
|
111
|
-
rowId: rowId,
|
|
112
|
-
rowData: rowData ?? request.bodyAsBuffer(),
|
|
113
|
-
requestType: request.requestType,
|
|
114
|
-
responseType: request.responseType,
|
|
115
|
-
multipartBoundary: request.multipartBoundary,
|
|
116
|
-
lastModified: request.lastModified,
|
|
117
|
-
sqlParams: sqlParams
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* OINO API request result object with returned data and/or http status code/message and
|
|
123
|
-
* error / warning messages.
|
|
124
|
-
*
|
|
125
|
-
*/
|
|
126
|
-
export class OINODbApiResult extends OINOResult {
|
|
127
|
-
/** DbApi request params */
|
|
128
|
-
request;
|
|
129
|
-
/** Returned data if any */
|
|
130
|
-
data;
|
|
131
|
-
/**
|
|
132
|
-
* Constructor of OINODbApiResult.
|
|
133
|
-
*
|
|
134
|
-
* @param request DbApi request parameters
|
|
135
|
-
* @param data result data
|
|
136
|
-
*
|
|
137
|
-
*/
|
|
138
|
-
constructor(request, data) {
|
|
139
|
-
super();
|
|
140
|
-
this.request = request;
|
|
141
|
-
this.data = data;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Creates a HTTP Response from API results.
|
|
145
|
-
*
|
|
146
|
-
* @param headers Headers to include in the response
|
|
147
|
-
*
|
|
148
|
-
*/
|
|
149
|
-
async writeApiResponse(headers = {}) {
|
|
150
|
-
let response = null;
|
|
151
|
-
if (this.success && this.data) {
|
|
152
|
-
const body = await this.data.writeString(this.request.responseType);
|
|
153
|
-
response = new Response(body, { status: this.status, statusText: this.statusText, headers: headers });
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
response = new Response(JSON.stringify(this, null, 3), { status: this.status, statusText: this.statusText, headers: headers });
|
|
157
|
-
}
|
|
158
|
-
for (let i = 0; i < this.messages.length; i++) {
|
|
159
|
-
response.headers.set('X-OINO-MESSAGE-' + i, this.messages[i]);
|
|
160
|
-
}
|
|
161
|
-
return Promise.resolve(response);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Specialized HTML template that can render ´OINODbApiResult´.
|
|
166
|
-
*
|
|
167
|
-
*/
|
|
168
|
-
export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
169
|
-
/** Locale validation regex */
|
|
170
|
-
static LOCALE_REGEX = /^(\w\w)(\-\w\w)?$/;
|
|
171
|
-
/** Locale formatter */
|
|
172
|
-
_locale;
|
|
173
|
-
_numberDecimals = -1;
|
|
174
|
-
/**
|
|
175
|
-
* Constructor of OINODbHtmlTemplate.
|
|
176
|
-
*
|
|
177
|
-
* @param template HTML template string
|
|
178
|
-
* @param numberDecimals Number of decimals to use for numbers, -1 for no formatting
|
|
179
|
-
* @param dateLocaleStr Datetime format string, either "iso" for ISO8601 or "default" for system default or valid locale string
|
|
180
|
-
* @param dateLocaleStyle Datetime format style, either "short/medium/long/full" or Intl.DateTimeFormat options
|
|
181
|
-
*
|
|
182
|
-
*/
|
|
183
|
-
constructor(template, numberDecimals = -1, dateLocaleStr = "", dateLocaleStyle = "") {
|
|
184
|
-
super(template);
|
|
185
|
-
let locale_opts;
|
|
186
|
-
if ((dateLocaleStyle == null) || (dateLocaleStyle == "")) {
|
|
187
|
-
locale_opts = { dateStyle: "medium", timeStyle: "medium" };
|
|
188
|
-
}
|
|
189
|
-
else if (typeof dateLocaleStyle == "string") {
|
|
190
|
-
locale_opts = { dateStyle: dateLocaleStyle, timeStyle: dateLocaleStyle };
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
locale_opts = dateLocaleStyle;
|
|
194
|
-
}
|
|
195
|
-
this._locale = null;
|
|
196
|
-
this._numberDecimals = numberDecimals;
|
|
197
|
-
if ((dateLocaleStr != null) && (dateLocaleStr != "") && OINODbHtmlTemplate.LOCALE_REGEX.test(dateLocaleStr)) {
|
|
198
|
-
try {
|
|
199
|
-
this._locale = new Intl.DateTimeFormat(dateLocaleStr, locale_opts);
|
|
200
|
-
}
|
|
201
|
-
catch (e) { }
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Creates HTML Response from API modelset.
|
|
206
|
-
*
|
|
207
|
-
* @param modelset OINO API dataset
|
|
208
|
-
* @param overrideValues values to override in the data
|
|
209
|
-
*
|
|
210
|
-
*/
|
|
211
|
-
async renderFromDbData(modelset, overrideValues) {
|
|
212
|
-
OINOBenchmark.startMetric("OINOHtmlTemplate", "renderFromDbData");
|
|
213
|
-
let html = "";
|
|
214
|
-
const dataset = modelset.dataset;
|
|
215
|
-
const datamodel = modelset.datamodel;
|
|
216
|
-
const api = modelset.datamodel.api;
|
|
217
|
-
const modified_index = datamodel.findFieldIndexByName(api.params.cacheModifiedField || "");
|
|
218
|
-
let last_modified = this.modified;
|
|
219
|
-
while (!dataset.isEof()) {
|
|
220
|
-
const row = dataset.getRow();
|
|
221
|
-
if (modified_index >= 0) {
|
|
222
|
-
last_modified = Math.max(last_modified, new Date(row[modified_index]).getTime());
|
|
223
|
-
}
|
|
224
|
-
let row_id_seed = datamodel.getRowPrimarykeyValues(row).join(' ');
|
|
225
|
-
let primary_key_values = [];
|
|
226
|
-
this.clearVariables();
|
|
227
|
-
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, "");
|
|
228
|
-
for (let i = 0; i < datamodel.fields.length; i++) {
|
|
229
|
-
const f = datamodel.fields[i];
|
|
230
|
-
let value;
|
|
231
|
-
if ((f instanceof OINODatetimeDataField) && (this._locale != null)) {
|
|
232
|
-
value = f.serializeCellWithLocale(row[i], this._locale);
|
|
233
|
-
}
|
|
234
|
-
else if ((f instanceof OINONumberDataField) && (this._numberDecimals >= 0) && (typeof row[i] === "number")) {
|
|
235
|
-
// console.debug("renderFromDbData number decimals", { field: f.name, value: row[i], type: typeof row[i] });
|
|
236
|
-
value = row[i].toFixed(this._numberDecimals);
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
value = f.serializeCell(row[i]);
|
|
240
|
-
}
|
|
241
|
-
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
242
|
-
if (value && (f instanceof OINONumberDataField) && (datamodel.api.hashid)) {
|
|
243
|
-
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed);
|
|
244
|
-
}
|
|
245
|
-
if (f.fieldParams.isPrimaryKey) {
|
|
246
|
-
primary_key_values.push(value || "");
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
this.setVariableFromValue(f.name, value || "");
|
|
250
|
-
}
|
|
251
|
-
this.setVariableFromProperties(overrideValues);
|
|
252
|
-
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values));
|
|
253
|
-
html += this._renderHtml() + "\r\n";
|
|
254
|
-
await dataset.next();
|
|
255
|
-
}
|
|
256
|
-
this.modified = last_modified;
|
|
257
|
-
const result = this._createHttpResult(html);
|
|
258
|
-
OINOBenchmark.endMetric("OINOHtmlTemplate", "renderFromDbData");
|
|
259
|
-
return result;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
6
|
+
import { OINOApi, OINOLog, OINOBenchmark, OINOApiRequest, OINOApiResult, OINOContentType, OINOStringDataField, OINOConfig, OINOModelSet, OINOParser, OINO_ERROR_PREFIX } from "@oino-ts/common";
|
|
262
7
|
/**
|
|
263
8
|
* API class with method to process HTTP REST requests.
|
|
264
9
|
*
|
|
265
10
|
*/
|
|
266
|
-
export class OINODbApi {
|
|
267
|
-
/**
|
|
268
|
-
_debugOnError = false;
|
|
269
|
-
/** API database reference */
|
|
11
|
+
export class OINODbApi extends OINOApi {
|
|
12
|
+
/** DB reference */
|
|
270
13
|
db;
|
|
271
|
-
/**
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
|
|
275
|
-
/** API hashid */
|
|
276
|
-
hashid;
|
|
14
|
+
/** DB parameters reference */
|
|
15
|
+
dbParams;
|
|
16
|
+
/** DB datamodel reference */
|
|
17
|
+
dbDatamodel = null;
|
|
277
18
|
/**
|
|
278
19
|
* Constructor of API object.
|
|
279
20
|
* NOTE! OINODb.initDatamodel must be called if created manually instead of the factory.
|
|
@@ -283,23 +24,22 @@ export class OINODbApi {
|
|
|
283
24
|
*
|
|
284
25
|
*/
|
|
285
26
|
constructor(db, params) {
|
|
27
|
+
super(db, params);
|
|
286
28
|
if (!params.tableName) {
|
|
287
|
-
throw new Error(OINO_ERROR_PREFIX + ":
|
|
29
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINOApiParams needs to define a table name!");
|
|
288
30
|
}
|
|
289
31
|
this.db = db;
|
|
290
|
-
this.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
this.hashid = null;
|
|
297
|
-
}
|
|
32
|
+
this.dbParams = params;
|
|
33
|
+
}
|
|
34
|
+
initializeDatamodel(datamodel) {
|
|
35
|
+
this.dbDatamodel = datamodel;
|
|
36
|
+
this.datamodel = datamodel;
|
|
37
|
+
this.initialized = true;
|
|
298
38
|
}
|
|
299
39
|
_validateRow(result, row, requirePrimaryKey) {
|
|
300
40
|
let field;
|
|
301
|
-
for (let i = 0; i < this.
|
|
302
|
-
field = this.
|
|
41
|
+
for (let i = 0; i < this.dbDatamodel.fields.length; i++) {
|
|
42
|
+
field = this.dbDatamodel.fields[i];
|
|
303
43
|
const val = row[i];
|
|
304
44
|
if ((val === null) && ((field.fieldParams.isNotNull) || (field.fieldParams.isPrimaryKey))) { // null is a valid SQL value except if it's not allowed
|
|
305
45
|
result.setError(405, "Field '" + field.name + "' is not allowed to be NULL!", "ValidateRowValues");
|
|
@@ -307,14 +47,14 @@ export class OINODbApi {
|
|
|
307
47
|
else if ((val === undefined) && (requirePrimaryKey) && (field.fieldParams.isPrimaryKey) && (!field.fieldParams.isAutoInc)) {
|
|
308
48
|
result.setError(405, "Primary key '" + field.name + "' is not autoinc and missing from the data!", "ValidateRowValues");
|
|
309
49
|
}
|
|
310
|
-
else if ((val !== undefined) && (this.
|
|
50
|
+
else if ((val !== undefined) && (this.dbParams.failOnUpdateOnAutoinc) && (field.fieldParams.isAutoInc)) {
|
|
311
51
|
result.setError(405, "Autoinc field '" + field.name + "' can't be updated!", "ValidateRowValues");
|
|
312
52
|
}
|
|
313
53
|
else {
|
|
314
54
|
if ((field instanceof OINOStringDataField) && ((field.maxLength > 0))) {
|
|
315
55
|
const str_val = val?.toString() || "";
|
|
316
56
|
if (str_val.length > field.maxLength) {
|
|
317
|
-
if (this.
|
|
57
|
+
if (this.dbParams.failOnOversizedValues) {
|
|
318
58
|
result.setError(405, "Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and can't be set!", "ValidateRowValues");
|
|
319
59
|
}
|
|
320
60
|
else {
|
|
@@ -334,7 +74,7 @@ export class OINODbApi {
|
|
|
334
74
|
rows = data;
|
|
335
75
|
}
|
|
336
76
|
else if (data != null) {
|
|
337
|
-
rows =
|
|
77
|
+
rows = OINOParser.createRows(this.datamodel, data, request.requestType, request.multipartBoundary);
|
|
338
78
|
}
|
|
339
79
|
}
|
|
340
80
|
catch (e) {
|
|
@@ -345,7 +85,7 @@ export class OINODbApi {
|
|
|
345
85
|
async _doGet(result, rowId, request) {
|
|
346
86
|
let sql = "";
|
|
347
87
|
try {
|
|
348
|
-
sql = this.
|
|
88
|
+
sql = this.dbDatamodel.printSqlSelect(rowId, request.queryParams || {});
|
|
349
89
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doGet", "Print SQL", { sql: sql });
|
|
350
90
|
const sql_res = await this.db.sqlSelect(sql);
|
|
351
91
|
if (sql_res.success == false) {
|
|
@@ -355,7 +95,7 @@ export class OINODbApi {
|
|
|
355
95
|
}
|
|
356
96
|
}
|
|
357
97
|
else {
|
|
358
|
-
result.data = new
|
|
98
|
+
result.data = new OINOModelSet(this.datamodel, sql_res, request.queryParams);
|
|
359
99
|
}
|
|
360
100
|
}
|
|
361
101
|
catch (e) {
|
|
@@ -370,11 +110,11 @@ export class OINODbApi {
|
|
|
370
110
|
let sql = "";
|
|
371
111
|
try {
|
|
372
112
|
for (let i = 0; i < rows.length; i++) {
|
|
373
|
-
this._validateRow(result, rows[i], this.
|
|
113
|
+
this._validateRow(result, rows[i], this.dbParams.failOnInsertWithoutKey || false);
|
|
374
114
|
if (result.success) {
|
|
375
|
-
sql += this.
|
|
115
|
+
sql += this.dbDatamodel.printSqlInsert(rows[i]);
|
|
376
116
|
}
|
|
377
|
-
else if (this.
|
|
117
|
+
else if (this.dbParams.failOnAnyInvalidRows == false) {
|
|
378
118
|
result.setOk(); // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
379
119
|
}
|
|
380
120
|
}
|
|
@@ -391,8 +131,8 @@ export class OINODbApi {
|
|
|
391
131
|
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost");
|
|
392
132
|
}
|
|
393
133
|
}
|
|
394
|
-
else if (this.
|
|
395
|
-
result.data = new
|
|
134
|
+
else if (this.dbParams.returnInsertedIds) {
|
|
135
|
+
result.data = new OINOModelSet(this.datamodel, sql_res, request.queryParams); // return the inserted ids as data
|
|
396
136
|
}
|
|
397
137
|
}
|
|
398
138
|
}
|
|
@@ -409,12 +149,12 @@ export class OINODbApi {
|
|
|
409
149
|
try {
|
|
410
150
|
// this._validateRowValues(result, row, false)
|
|
411
151
|
for (let i = 0; i < rows.length; i++) {
|
|
412
|
-
const row_id = id ||
|
|
413
|
-
this._validateRow(result, rows[i], this.
|
|
152
|
+
const row_id = id || OINOConfig.printOINOId(this.dbDatamodel.getRowPrimarykeyValues(rows[i], this.hashid != null));
|
|
153
|
+
this._validateRow(result, rows[i], this.dbParams.failOnInsertWithoutKey || false);
|
|
414
154
|
if (result.success) {
|
|
415
|
-
sql += this.
|
|
155
|
+
sql += this.dbDatamodel.printSqlUpdate(row_id, rows[i]);
|
|
416
156
|
}
|
|
417
|
-
else if (this.
|
|
157
|
+
else if (this.dbParams.failOnAnyInvalidRows == false) {
|
|
418
158
|
result.setOk(); // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
419
159
|
}
|
|
420
160
|
}
|
|
@@ -446,17 +186,17 @@ export class OINODbApi {
|
|
|
446
186
|
try {
|
|
447
187
|
if (rows != null) {
|
|
448
188
|
for (let i = 0; i < rows.length; i++) {
|
|
449
|
-
const row_id =
|
|
189
|
+
const row_id = OINOConfig.printOINOId(this.dbDatamodel.getRowPrimarykeyValues(rows[i], this.hashid != null));
|
|
450
190
|
if (row_id) {
|
|
451
|
-
sql += this.
|
|
191
|
+
sql += this.dbDatamodel.printSqlDelete(row_id);
|
|
452
192
|
}
|
|
453
|
-
else if (this.
|
|
193
|
+
else if (this.dbParams.failOnAnyInvalidRows == false) {
|
|
454
194
|
result.setOk(); // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
455
195
|
}
|
|
456
196
|
}
|
|
457
197
|
}
|
|
458
198
|
else if (id) {
|
|
459
|
-
sql = this.
|
|
199
|
+
sql = this.dbDatamodel.printSqlDelete(id);
|
|
460
200
|
}
|
|
461
201
|
if ((sql == "") && result.success) {
|
|
462
202
|
result.setError(405, "No valid rows for DELETE!", "DoDelete"); // only set error if there are multiple rows and no valid sql was created
|
|
@@ -481,14 +221,6 @@ export class OINODbApi {
|
|
|
481
221
|
}
|
|
482
222
|
}
|
|
483
223
|
}
|
|
484
|
-
/**
|
|
485
|
-
* Enable or disable debug output on errors.
|
|
486
|
-
*
|
|
487
|
-
* @param debugOnError true to enable debug output on errors, false to disable
|
|
488
|
-
*/
|
|
489
|
-
setDebugOnError(debugOnError) {
|
|
490
|
-
this._debugOnError = debugOnError;
|
|
491
|
-
}
|
|
492
224
|
/**
|
|
493
225
|
* Method for handling a HTTP REST request with GET, POST, PUT, DELETE corresponding to
|
|
494
226
|
* SQL select, insert, update and delete.
|
|
@@ -496,11 +228,11 @@ export class OINODbApi {
|
|
|
496
228
|
* @param request OINO HTTP request object containing all parameters of the REST request
|
|
497
229
|
* @param rowId URL id of the REST request
|
|
498
230
|
* @param rowData HTTP body data as either serialized string or unserialized JS object or OINODataRow-array or Buffer/Uint8Array binary data
|
|
499
|
-
* @param
|
|
231
|
+
* @param queryParams SQL parameters for the REST request
|
|
500
232
|
*
|
|
501
233
|
*/
|
|
502
|
-
async doHttpRequest(request, rowId, rowData,
|
|
503
|
-
const api_request =
|
|
234
|
+
async doHttpRequest(request, rowId, rowData, queryParams) {
|
|
235
|
+
const api_request = OINOApiRequest.fromHttpRequest(request, rowId, rowData, queryParams);
|
|
504
236
|
return this.doApiRequest(api_request);
|
|
505
237
|
}
|
|
506
238
|
/**
|
|
@@ -510,17 +242,20 @@ export class OINODbApi {
|
|
|
510
242
|
* @param method HTTP method of the REST request
|
|
511
243
|
* @param rowId URL id of the REST request
|
|
512
244
|
* @param rowData HTTP body data as either serialized string or unserialized JS object or OINODataRow-array or Buffer/Uint8Array binary data
|
|
513
|
-
* @param
|
|
245
|
+
* @param queryParams SQL parameters for the REST request
|
|
514
246
|
* @param contentType content type of the HTTP body data, default is JSON
|
|
515
247
|
*
|
|
516
248
|
*/
|
|
517
|
-
async doRequest(method, rowId, rowData,
|
|
518
|
-
return this.doApiRequest(new
|
|
249
|
+
async doRequest(method, rowId, rowData, queryParams, contentType = OINOContentType.json) {
|
|
250
|
+
return this.doApiRequest(new OINOApiRequest({ method: method, rowId: rowId, rowData: rowData, queryParams: queryParams, requestType: contentType }));
|
|
519
251
|
}
|
|
520
252
|
async doApiRequest(request) {
|
|
253
|
+
if (this.initialized == false) {
|
|
254
|
+
throw new Error(OINO_ERROR_PREFIX + ": API is not initialized yet!");
|
|
255
|
+
}
|
|
521
256
|
OINOBenchmark.startMetric("OINODbApi", "doRequest." + request.method);
|
|
522
257
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "doRequest", "Request", { method: request.method, id: request.rowId, data: request.rowData });
|
|
523
|
-
let result = new
|
|
258
|
+
let result = new OINOApiResult(request);
|
|
524
259
|
let rows = [];
|
|
525
260
|
if ((request.method == "POST") || (request.method == "PUT")) {
|
|
526
261
|
rows = this._parseData(result, request);
|
|
@@ -587,8 +322,8 @@ export class OINODbApi {
|
|
|
587
322
|
* @param rowData HTTP body data as either serialized string or unserialized JS object or OINODataRow-array or Buffer/Uint8Array binary data
|
|
588
323
|
*
|
|
589
324
|
*/
|
|
590
|
-
async doBatchUpdate(method, rowId, rowData,
|
|
591
|
-
return this.doApiRequest(new
|
|
325
|
+
async doBatchUpdate(method, rowId, rowData, queryParams) {
|
|
326
|
+
return this.doApiRequest(new OINOApiRequest({ method: method, rowId: rowId, rowData: rowData, queryParams: queryParams }));
|
|
592
327
|
}
|
|
593
328
|
/**
|
|
594
329
|
* Method for handling a HTTP REST request with batch update using PUT or DELETE methods.
|
|
@@ -596,9 +331,9 @@ export class OINODbApi {
|
|
|
596
331
|
* @param request HTTP URL parameters as key-value-pairs
|
|
597
332
|
*
|
|
598
333
|
*/
|
|
599
|
-
async
|
|
334
|
+
async doBatchApiRequest(request) {
|
|
600
335
|
OINOLog.debug("@oino-ts/db", "OINODbApi", "doBatchUpdate", "Request", { request: request, data: request.rowData });
|
|
601
|
-
let result = new
|
|
336
|
+
let result = new OINOApiResult(request);
|
|
602
337
|
if ((request.method != "PUT") && (request.method != "DELETE")) {
|
|
603
338
|
result.setError(500, "Batch update only supports PUT and DELETE methods!", "DoBatchUpdate");
|
|
604
339
|
return Promise.resolve(result);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
/** Constant for undefined values */
|
|
7
|
+
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)
|