@oino-ts/db 0.17.1 → 0.17.2
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 +9 -0
- package/dist/esm/OINODbApi.js +9 -0
- package/dist/types/OINODbApi.d.ts +1 -0
- package/package.json +37 -37
- package/src/OINODb.ts +321 -321
- package/src/OINODbApi.test.ts +492 -492
- package/src/OINODbApi.ts +611 -602
- package/src/OINODbConfig.ts +98 -98
- package/src/OINODbDataField.ts +403 -403
- package/src/OINODbDataModel.ts +291 -291
- package/src/OINODbFactory.ts +68 -68
- package/src/OINODbModelSet.ts +351 -351
- package/src/OINODbParser.ts +447 -447
- package/src/OINODbSqlParams.ts +592 -592
- package/src/OINODbSwagger.ts +208 -208
- package/src/index.ts +120 -120
package/src/OINODbApi.ts
CHANGED
|
@@ -1,603 +1,612 @@
|
|
|
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
|
-
|
|
7
|
-
import { OINODbApiParams, OINODb, OINODbDataSet, OINODbDataModel, OINODbDataField, OINOStringDataField, OINO_ERROR_PREFIX, OINODataRow, OINODataCell, OINODbModelSet, OINOBenchmark, OINODbConfig, OINOHttpResult, OINOHtmlTemplate, OINONumberDataField, OINODbParser, OINODatetimeDataField, OINODbSqlParams, OINODbSqlAggregate, OINODbSqlSelect, OINODbSqlFilter, OINODbSqlOrder, OINODbSqlLimit } from "./index.js"
|
|
8
|
-
import { OINOLog, OINOResult, OINOHttpRequest, OINOHttpRequestInit } from "@oino-ts/common";
|
|
9
|
-
import { OINOHashid } from "@oino-ts/hashid"
|
|
10
|
-
|
|
11
|
-
export interface OINODbApiRequestInit extends OINOHttpRequestInit {
|
|
12
|
-
rowId?: string
|
|
13
|
-
data?: string|OINODataRow[]|Buffer|Uint8Array|object|null
|
|
14
|
-
sqlParams?: OINODbSqlParams
|
|
15
|
-
filter?: OINODbSqlFilter
|
|
16
|
-
order?: OINODbSqlOrder
|
|
17
|
-
limit?: OINODbSqlLimit
|
|
18
|
-
aggregate?: OINODbSqlAggregate
|
|
19
|
-
select?: OINODbSqlSelect
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class OINODbApiRequest extends OINOHttpRequest {
|
|
23
|
-
readonly rowId:string
|
|
24
|
-
readonly data:string|OINODataRow[]|Buffer|Uint8Array|object|null
|
|
25
|
-
readonly sqlParams:OINODbSqlParams
|
|
26
|
-
|
|
27
|
-
constructor (init: OINODbApiRequestInit) {
|
|
28
|
-
super(init)
|
|
29
|
-
this.rowId = init?.rowId || ""
|
|
30
|
-
this.data = init?.data || null
|
|
31
|
-
this.sqlParams = init?.sqlParams || {}
|
|
32
|
-
|
|
33
|
-
if (init?.filter) {
|
|
34
|
-
this.sqlParams.filter = init.filter
|
|
35
|
-
}
|
|
36
|
-
if (!this.sqlParams.filter) {
|
|
37
|
-
const filter_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_FILTER_PARAM)
|
|
38
|
-
if (filter_param) {
|
|
39
|
-
this.sqlParams.filter = OINODbSqlFilter.parse(filter_param)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (init?.order) {
|
|
43
|
-
this.sqlParams.order = init.order
|
|
44
|
-
}
|
|
45
|
-
if (!this.sqlParams.order) {
|
|
46
|
-
const order_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_ORDER_PARAM)
|
|
47
|
-
if (order_param) {
|
|
48
|
-
this.sqlParams.order = OINODbSqlOrder.parse(order_param)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (init?.limit) {
|
|
52
|
-
this.sqlParams.limit = init.limit
|
|
53
|
-
}
|
|
54
|
-
if (!this.sqlParams.limit) {
|
|
55
|
-
const limit_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_LIMIT_PARAM)
|
|
56
|
-
if (limit_param) {
|
|
57
|
-
this.sqlParams.limit = OINODbSqlLimit.parse(limit_param)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (init?.aggregate) {
|
|
61
|
-
this.sqlParams.aggregate = init.aggregate
|
|
62
|
-
}
|
|
63
|
-
if (!this.sqlParams.aggregate) {
|
|
64
|
-
const aggregate_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_AGGREGATE_PARAM)
|
|
65
|
-
if (aggregate_param) {
|
|
66
|
-
this.sqlParams.aggregate = OINODbSqlAggregate.parse(aggregate_param)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (init?.select) {
|
|
70
|
-
this.sqlParams.select = init.select
|
|
71
|
-
}
|
|
72
|
-
if (!this.sqlParams.select) {
|
|
73
|
-
const select_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_SELECT_PARAM)
|
|
74
|
-
if (select_param) {
|
|
75
|
-
this.sqlParams.select = OINODbSqlSelect.parse(select_param)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
/** API
|
|
247
|
-
readonly
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
* @param
|
|
555
|
-
*
|
|
556
|
-
*/
|
|
557
|
-
async
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
+
|
|
7
|
+
import { OINODbApiParams, OINODb, OINODbDataSet, OINODbDataModel, OINODbDataField, OINOStringDataField, OINO_ERROR_PREFIX, OINODataRow, OINODataCell, OINODbModelSet, OINOBenchmark, OINODbConfig, OINOHttpResult, OINOHtmlTemplate, OINONumberDataField, OINODbParser, OINODatetimeDataField, OINODbSqlParams, OINODbSqlAggregate, OINODbSqlSelect, OINODbSqlFilter, OINODbSqlOrder, OINODbSqlLimit } from "./index.js"
|
|
8
|
+
import { OINOLog, OINOResult, OINOHttpRequest, OINOHttpRequestInit } from "@oino-ts/common";
|
|
9
|
+
import { OINOHashid } from "@oino-ts/hashid"
|
|
10
|
+
|
|
11
|
+
export interface OINODbApiRequestInit extends OINOHttpRequestInit {
|
|
12
|
+
rowId?: string
|
|
13
|
+
data?: string|OINODataRow[]|Buffer|Uint8Array|object|null
|
|
14
|
+
sqlParams?: OINODbSqlParams
|
|
15
|
+
filter?: OINODbSqlFilter
|
|
16
|
+
order?: OINODbSqlOrder
|
|
17
|
+
limit?: OINODbSqlLimit
|
|
18
|
+
aggregate?: OINODbSqlAggregate
|
|
19
|
+
select?: OINODbSqlSelect
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class OINODbApiRequest extends OINOHttpRequest {
|
|
23
|
+
readonly rowId:string
|
|
24
|
+
readonly data:string|OINODataRow[]|Buffer|Uint8Array|object|null
|
|
25
|
+
readonly sqlParams:OINODbSqlParams
|
|
26
|
+
|
|
27
|
+
constructor (init: OINODbApiRequestInit) {
|
|
28
|
+
super(init)
|
|
29
|
+
this.rowId = init?.rowId || ""
|
|
30
|
+
this.data = init?.data || null
|
|
31
|
+
this.sqlParams = init?.sqlParams || {}
|
|
32
|
+
|
|
33
|
+
if (init?.filter) {
|
|
34
|
+
this.sqlParams.filter = init.filter
|
|
35
|
+
}
|
|
36
|
+
if (!this.sqlParams.filter) {
|
|
37
|
+
const filter_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_FILTER_PARAM)
|
|
38
|
+
if (filter_param) {
|
|
39
|
+
this.sqlParams.filter = OINODbSqlFilter.parse(filter_param)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (init?.order) {
|
|
43
|
+
this.sqlParams.order = init.order
|
|
44
|
+
}
|
|
45
|
+
if (!this.sqlParams.order) {
|
|
46
|
+
const order_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_ORDER_PARAM)
|
|
47
|
+
if (order_param) {
|
|
48
|
+
this.sqlParams.order = OINODbSqlOrder.parse(order_param)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (init?.limit) {
|
|
52
|
+
this.sqlParams.limit = init.limit
|
|
53
|
+
}
|
|
54
|
+
if (!this.sqlParams.limit) {
|
|
55
|
+
const limit_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_LIMIT_PARAM)
|
|
56
|
+
if (limit_param) {
|
|
57
|
+
this.sqlParams.limit = OINODbSqlLimit.parse(limit_param)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (init?.aggregate) {
|
|
61
|
+
this.sqlParams.aggregate = init.aggregate
|
|
62
|
+
}
|
|
63
|
+
if (!this.sqlParams.aggregate) {
|
|
64
|
+
const aggregate_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_AGGREGATE_PARAM)
|
|
65
|
+
if (aggregate_param) {
|
|
66
|
+
this.sqlParams.aggregate = OINODbSqlAggregate.parse(aggregate_param)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (init?.select) {
|
|
70
|
+
this.sqlParams.select = init.select
|
|
71
|
+
}
|
|
72
|
+
if (!this.sqlParams.select) {
|
|
73
|
+
const select_param = this.url?.searchParams.get(OINODbConfig.OINODB_SQL_SELECT_PARAM)
|
|
74
|
+
if (select_param) {
|
|
75
|
+
this.sqlParams.select = OINODbSqlSelect.parse(select_param)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
static async fromRequest(request: Request): Promise<OINODbApiRequest> {
|
|
80
|
+
const body = await request.arrayBuffer()
|
|
81
|
+
return new OINODbApiRequest({
|
|
82
|
+
url: new URL(request.url),
|
|
83
|
+
method: request.method,
|
|
84
|
+
headers: Object.fromEntries(request.headers as any),
|
|
85
|
+
data: Buffer.from(body),
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* OINO API request result object with returned data and/or http status code/message and
|
|
92
|
+
* error / warning messages.
|
|
93
|
+
*
|
|
94
|
+
*/
|
|
95
|
+
export class OINODbApiResult extends OINOResult {
|
|
96
|
+
/** DbApi request params */
|
|
97
|
+
request: OINODbApiRequest
|
|
98
|
+
|
|
99
|
+
/** Returned data if any */
|
|
100
|
+
data?: OINODbModelSet;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Constructor of OINODbApiResult.
|
|
104
|
+
*
|
|
105
|
+
* @param request DbApi request parameters
|
|
106
|
+
* @param data result data
|
|
107
|
+
*
|
|
108
|
+
*/
|
|
109
|
+
constructor (request:OINODbApiRequest, data?:OINODbModelSet) {
|
|
110
|
+
super()
|
|
111
|
+
this.request = request
|
|
112
|
+
this.data = data
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Creates a HTTP Response from API results.
|
|
117
|
+
*
|
|
118
|
+
* @param headers Headers to include in the response
|
|
119
|
+
*
|
|
120
|
+
*/
|
|
121
|
+
async writeApiResponse(headers:Record<string, string> = {}):Promise<Response> {
|
|
122
|
+
let response:Response|null = null
|
|
123
|
+
if (this.success && this.data) {
|
|
124
|
+
const body = await this.data.writeString(this.request.responseType)
|
|
125
|
+
response = new Response(body, {status:this.status, statusText: this.statusText, headers: headers })
|
|
126
|
+
} else {
|
|
127
|
+
response = new Response(JSON.stringify(this, null, 3), {status:this.status, statusText: this.statusText, headers: headers })
|
|
128
|
+
}
|
|
129
|
+
for (let i=0; i<this.messages.length; i++) {
|
|
130
|
+
response.headers.set('X-OINO-MESSAGE-' + i, this.messages[i])
|
|
131
|
+
}
|
|
132
|
+
return Promise.resolve(response)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Specialized HTML template that can render ´OINODbApiResult´.
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
141
|
+
/** Locale validation regex */
|
|
142
|
+
static LOCALE_REGEX:RegExp = /^(\w\w)(\-\w\w)?$/
|
|
143
|
+
/** Locale formatter */
|
|
144
|
+
protected _locale:Intl.DateTimeFormat|null
|
|
145
|
+
protected _numberDecimals:number = -1
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Constructor of OINODbHtmlTemplate.
|
|
149
|
+
*
|
|
150
|
+
* @param template HTML template string
|
|
151
|
+
* @param numberDecimals Number of decimals to use for numbers, -1 for no formatting
|
|
152
|
+
* @param dateLocaleStr Datetime format string, either "iso" for ISO8601 or "default" for system default or valid locale string
|
|
153
|
+
* @param dateLocaleStyle Datetime format style, either "short/medium/long/full" or Intl.DateTimeFormat options
|
|
154
|
+
*
|
|
155
|
+
*/
|
|
156
|
+
constructor (template:string, numberDecimals:number=-1, dateLocaleStr:string="", dateLocaleStyle:string|any="") {
|
|
157
|
+
super(template)
|
|
158
|
+
let locale_opts:any
|
|
159
|
+
if ((dateLocaleStyle == null) || (dateLocaleStyle == "")) {
|
|
160
|
+
locale_opts = { dateStyle: "medium", timeStyle: "medium" }
|
|
161
|
+
} else if (typeof dateLocaleStyle == "string") {
|
|
162
|
+
locale_opts = { dateStyle: dateLocaleStyle, timeStyle: dateLocaleStyle }
|
|
163
|
+
} else {
|
|
164
|
+
locale_opts = dateLocaleStyle
|
|
165
|
+
}
|
|
166
|
+
this._locale = null
|
|
167
|
+
this._numberDecimals = numberDecimals
|
|
168
|
+
|
|
169
|
+
if ((dateLocaleStr != null) && (dateLocaleStr != "") && OINODbHtmlTemplate.LOCALE_REGEX.test(dateLocaleStr)) {
|
|
170
|
+
try {
|
|
171
|
+
this._locale = new Intl.DateTimeFormat(dateLocaleStr, locale_opts)
|
|
172
|
+
} catch (e:any) {}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Creates HTML Response from API modelset.
|
|
178
|
+
*
|
|
179
|
+
* @param modelset OINO API dataset
|
|
180
|
+
* @param overrideValues values to override in the data
|
|
181
|
+
*
|
|
182
|
+
*/
|
|
183
|
+
async renderFromDbData(modelset:OINODbModelSet, overrideValues?:any):Promise<OINOHttpResult> {
|
|
184
|
+
OINOBenchmark.startMetric("OINOHtmlTemplate", "renderFromDbData")
|
|
185
|
+
let html:string = ""
|
|
186
|
+
const dataset:OINODbDataSet|undefined = modelset.dataset
|
|
187
|
+
const datamodel:OINODbDataModel = modelset.datamodel
|
|
188
|
+
const api:OINODbApi = modelset.datamodel.api
|
|
189
|
+
const modified_index = datamodel.findFieldIndexByName(api.params.cacheModifiedField || "")
|
|
190
|
+
let last_modified:number = this.modified
|
|
191
|
+
|
|
192
|
+
while (!dataset.isEof()) {
|
|
193
|
+
const row:OINODataRow = dataset.getRow()
|
|
194
|
+
if (modified_index >= 0) {
|
|
195
|
+
last_modified = Math.max(last_modified, new Date(row[modified_index] as Date).getTime())
|
|
196
|
+
}
|
|
197
|
+
let row_id_seed:string = datamodel.getRowPrimarykeyValues(row).join(' ')
|
|
198
|
+
let primary_key_values:string[] = []
|
|
199
|
+
this.clearVariables()
|
|
200
|
+
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, "")
|
|
201
|
+
for (let i=0; i<datamodel.fields.length; i++) {
|
|
202
|
+
const f:OINODbDataField = datamodel.fields[i]
|
|
203
|
+
let value:string|null|undefined
|
|
204
|
+
if ((f instanceof OINODatetimeDataField) && (this._locale != null)) {
|
|
205
|
+
value = f.serializeCellWithLocale(row[i], this._locale)
|
|
206
|
+
|
|
207
|
+
} else if ((f instanceof OINONumberDataField) && (this._numberDecimals >= 0) && (typeof row[i] === "number")) {
|
|
208
|
+
// console.debug("renderFromDbData number decimals", { field: f.name, value: row[i], type: typeof row[i] });
|
|
209
|
+
value = (row[i]! as number).toFixed(this._numberDecimals)
|
|
210
|
+
|
|
211
|
+
} else {
|
|
212
|
+
value = f.serializeCell(row[i])
|
|
213
|
+
}
|
|
214
|
+
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
215
|
+
if (value && (f instanceof OINONumberDataField) && (datamodel.api.hashid)) {
|
|
216
|
+
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed)
|
|
217
|
+
}
|
|
218
|
+
if (f.fieldParams.isPrimaryKey) {
|
|
219
|
+
primary_key_values.push(value || "")
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
this.setVariableFromValue(f.name, value || "")
|
|
223
|
+
}
|
|
224
|
+
this.setVariableFromProperties(overrideValues)
|
|
225
|
+
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values))
|
|
226
|
+
html += this._renderHtml() + "\r\n"
|
|
227
|
+
await dataset.next()
|
|
228
|
+
}
|
|
229
|
+
this.modified = last_modified
|
|
230
|
+
const result:OINOHttpResult = this._createHttpResult(html)
|
|
231
|
+
OINOBenchmark.endMetric("OINOHtmlTemplate", "renderFromDbData")
|
|
232
|
+
return result
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* API class with method to process HTTP REST requests.
|
|
240
|
+
*
|
|
241
|
+
*/
|
|
242
|
+
export class OINODbApi {
|
|
243
|
+
/** Enable debug output on errors */
|
|
244
|
+
private _debugOnError:boolean = false
|
|
245
|
+
|
|
246
|
+
/** API database reference */
|
|
247
|
+
readonly db: OINODb
|
|
248
|
+
|
|
249
|
+
/** API datamodel */
|
|
250
|
+
readonly datamodel: OINODbDataModel
|
|
251
|
+
|
|
252
|
+
/** API parameters */
|
|
253
|
+
readonly params: OINODbApiParams
|
|
254
|
+
|
|
255
|
+
/** API hashid */
|
|
256
|
+
readonly hashid:OINOHashid|null
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Constructor of API object.
|
|
260
|
+
* NOTE! OINODb.initDatamodel must be called if created manually instead of the factory.
|
|
261
|
+
*
|
|
262
|
+
* @param db database for the API
|
|
263
|
+
* @param params parameters for the API
|
|
264
|
+
*
|
|
265
|
+
*/
|
|
266
|
+
constructor (db: OINODb, params:OINODbApiParams) {
|
|
267
|
+
if (!params.tableName) {
|
|
268
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINODbApiParams needs to define a table name!")
|
|
269
|
+
}
|
|
270
|
+
this.db = db
|
|
271
|
+
this.params = params
|
|
272
|
+
this.datamodel = new OINODbDataModel(this)
|
|
273
|
+
if (this.params.hashidKey) {
|
|
274
|
+
this.hashid = new OINOHashid(this.params.hashidKey, this.db.name, this.params.hashidLength, this.params.hashidStaticIds)
|
|
275
|
+
} else {
|
|
276
|
+
this.hashid = null
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private _validateRow(result:OINODbApiResult, row:OINODataRow, requirePrimaryKey:boolean):void {
|
|
281
|
+
let field:OINODbDataField
|
|
282
|
+
for (let i=0; i<this.datamodel.fields.length; i++) {
|
|
283
|
+
field = this.datamodel.fields[i]
|
|
284
|
+
const val:OINODataCell = row[i]
|
|
285
|
+
if ((val === null) && ((field.fieldParams.isNotNull)||(field.fieldParams.isPrimaryKey))) { // null is a valid SQL value except if it's not allowed
|
|
286
|
+
result.setError(405, "Field '" + field.name + "' is not allowed to be NULL!", "ValidateRowValues")
|
|
287
|
+
|
|
288
|
+
} else if ((val === undefined) && (requirePrimaryKey) && (field.fieldParams.isPrimaryKey) && (!field.fieldParams.isAutoInc)) {
|
|
289
|
+
result.setError(405, "Primary key '" + field.name + "' is not autoinc and missing from the data!", "ValidateRowValues")
|
|
290
|
+
|
|
291
|
+
} else if ((val !== undefined) && (this.params.failOnUpdateOnAutoinc) && (field.fieldParams.isAutoInc)) {
|
|
292
|
+
result.setError(405, "Autoinc field '" + field.name + "' can't be updated!", "ValidateRowValues")
|
|
293
|
+
|
|
294
|
+
} else {
|
|
295
|
+
if ((field instanceof OINOStringDataField) && ((field.maxLength > 0))){
|
|
296
|
+
const str_val = val?.toString() || ""
|
|
297
|
+
if (str_val.length > field.maxLength) {
|
|
298
|
+
if (this.params.failOnOversizedValues) {
|
|
299
|
+
result.setError(405, "Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and can't be set!", "ValidateRowValues")
|
|
300
|
+
} else {
|
|
301
|
+
result.addWarning("Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and might truncate or fail.", "ValidateRowValues")
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
//logDebug("OINODbApi.validateHttpValues", {result:result})
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private _parseData(httpResult:OINODbApiResult, request:OINODbApiRequest):OINODataRow[] {
|
|
312
|
+
let rows:OINODataRow[] = []
|
|
313
|
+
try {
|
|
314
|
+
if (Array.isArray(request.data)) {
|
|
315
|
+
rows = request.data as OINODataRow[]
|
|
316
|
+
} else if (request.data != null) {
|
|
317
|
+
rows = OINODbParser.createRows(this.datamodel, request.data, request)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
} catch (e:any) {
|
|
321
|
+
httpResult.setError(400, "Invalid data: " + e.message, "DoRequest")
|
|
322
|
+
}
|
|
323
|
+
return rows
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private async _doGet(result:OINODbApiResult, rowId:string, request:OINODbApiRequest):Promise<void> {
|
|
327
|
+
let sql:string = ""
|
|
328
|
+
try {
|
|
329
|
+
sql = this.datamodel.printSqlSelect(rowId, request.sqlParams || {})
|
|
330
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doGet", "Print SQL", {sql:sql})
|
|
331
|
+
const sql_res:OINODbDataSet = await this.db.sqlSelect(sql)
|
|
332
|
+
if (sql_res.hasErrors()) {
|
|
333
|
+
result.setError(500, sql_res.getFirstError(), "DoGet")
|
|
334
|
+
if (this._debugOnError) {
|
|
335
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut")
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
result.data = new OINODbModelSet(this.datamodel, sql_res, request.sqlParams)
|
|
339
|
+
}
|
|
340
|
+
} catch (e:any) {
|
|
341
|
+
result.setError(500, "Unhandled exception in doGet: " + e.message, "DoGet")
|
|
342
|
+
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doGet", "exception in get request", {message:e.message, stack:e.stack})
|
|
343
|
+
if (this._debugOnError) {
|
|
344
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoGet")
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private async _doPost(result:OINODbApiResult, rows:OINODataRow[]):Promise<void> {
|
|
350
|
+
let sql:string = ""
|
|
351
|
+
try {
|
|
352
|
+
for (let i=0; i<rows.length; i++) {
|
|
353
|
+
this._validateRow(result, rows[i], this.params.failOnInsertWithoutKey||false)
|
|
354
|
+
if (result.success) {
|
|
355
|
+
sql += this.datamodel.printSqlInsert(rows[i])
|
|
356
|
+
|
|
357
|
+
} else if (this.params.failOnAnyInvalidRows == false) {
|
|
358
|
+
result.setOk() // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if ((sql == "") && result.success) {
|
|
362
|
+
result.setError(405, "No valid rows for POST!", "DoPost")
|
|
363
|
+
|
|
364
|
+
} else if (result.success) {
|
|
365
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPost", "Print SQL", {sql:sql})
|
|
366
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
367
|
+
if (sql_res.hasErrors()) {
|
|
368
|
+
result.setError(500, sql_res.getFirstError(), "DoPost")
|
|
369
|
+
if (this._debugOnError) {
|
|
370
|
+
result.addDebug("OINO POST MESSAGES [" + sql_res.messages.join('|') + "]", "DoPost")
|
|
371
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
} catch (e:any) {
|
|
376
|
+
result.setError(500, "Unhandled exception in doPost: " + e.message, "DoPost")
|
|
377
|
+
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doPost", "exception in post request", {message:e.message, stack:e.stack})
|
|
378
|
+
if (this._debugOnError) {
|
|
379
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private async _doPut(result:OINODbApiResult, id:string|null, rows:OINODataRow[]):Promise<void> {
|
|
385
|
+
let sql:string = ""
|
|
386
|
+
try {
|
|
387
|
+
// this._validateRowValues(result, row, false)
|
|
388
|
+
for (let i=0; i<rows.length; i++) {
|
|
389
|
+
const row_id = id || OINODbConfig.printOINOId(this.datamodel.getRowPrimarykeyValues(rows[i], this.hashid != null))
|
|
390
|
+
this._validateRow(result, rows[i], this.params.failOnInsertWithoutKey||false)
|
|
391
|
+
if (result.success) {
|
|
392
|
+
sql += this.datamodel.printSqlUpdate(row_id, rows[i])
|
|
393
|
+
|
|
394
|
+
} else if (this.params.failOnAnyInvalidRows == false) {
|
|
395
|
+
result.setOk() // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if ((sql == "") && result.success) {
|
|
399
|
+
result.setError(405, "No valid rows for PUT!", "DoPut") // only set error if there are multiple rows and no valid sql was created
|
|
400
|
+
|
|
401
|
+
} else if (result.success) {
|
|
402
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doPut", "Print SQL", {sql:sql})
|
|
403
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
404
|
+
if (sql_res.hasErrors()) {
|
|
405
|
+
result.setError(500, sql_res.getFirstError(), "DoPut")
|
|
406
|
+
if (this._debugOnError) {
|
|
407
|
+
result.addDebug("OINO PUT MESSAGES [" + sql_res.messages.join('|') + "]", "DoPut")
|
|
408
|
+
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut")
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
} catch (e:any) {
|
|
413
|
+
result.setError(500, "Unhandled exception: " + e.message, "DoPut")
|
|
414
|
+
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doPut", "exception in put request", {message:e.message, stack:e.stack})
|
|
415
|
+
if (this._debugOnError) {
|
|
416
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPut")
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private async _doDelete(result:OINODbApiResult, id:string|null, rows:OINODataRow[]|null):Promise<void> {
|
|
422
|
+
let sql:string = ""
|
|
423
|
+
try {
|
|
424
|
+
if (rows != null) {
|
|
425
|
+
for (let i=0; i<rows.length; i++) {
|
|
426
|
+
const row_id = OINODbConfig.printOINOId(this.datamodel.getRowPrimarykeyValues(rows[i], this.hashid != null))
|
|
427
|
+
if (row_id) {
|
|
428
|
+
sql += this.datamodel.printSqlDelete(row_id)
|
|
429
|
+
} else if (this.params.failOnAnyInvalidRows == false) {
|
|
430
|
+
result.setOk() // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
} else if (id) {
|
|
434
|
+
sql = this.datamodel.printSqlDelete(id)
|
|
435
|
+
}
|
|
436
|
+
if ((sql == "") && result.success) {
|
|
437
|
+
result.setError(405, "No valid rows for DELETE!", "DoDelete") // only set error if there are multiple rows and no valid sql was created
|
|
438
|
+
|
|
439
|
+
} else if (result.success) {
|
|
440
|
+
|
|
441
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "_doDelete", "Print SQL", {sql:sql})
|
|
442
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
443
|
+
if (sql_res.hasErrors()) {
|
|
444
|
+
result.setError(500, sql_res.getFirstError(), "DoDelete")
|
|
445
|
+
if (this._debugOnError) {
|
|
446
|
+
result.addDebug("OINO DELETE MESSAGES [" + sql_res.messages.join('|') + "]", "DoDelete")
|
|
447
|
+
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} catch (e:any) {
|
|
452
|
+
result.setError(500, "Unhandled exception: " + e.message, "DoDelete")
|
|
453
|
+
OINOLog.exception("@oino-ts/db", "OINODbApi", "_doDelete", "exception in delete request", {message:e.message, stack:e.stack})
|
|
454
|
+
if (this._debugOnError) {
|
|
455
|
+
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Enable or disable debug output on errors.
|
|
462
|
+
*
|
|
463
|
+
* @param debugOnError true to enable debug output on errors, false to disable
|
|
464
|
+
*/
|
|
465
|
+
setDebugOnError(debugOnError:boolean) {
|
|
466
|
+
this._debugOnError = debugOnError
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Method for handling a HTTP REST request with GET, POST, PUT, DELETE corresponding to
|
|
471
|
+
* SQL select, insert, update and delete.
|
|
472
|
+
*
|
|
473
|
+
* @param method HTTP method of the REST request
|
|
474
|
+
* @param rowId URL id of the REST request
|
|
475
|
+
* @param data HTTP body data as either serialized string or unserialized JS object or OINODataRow-array or Buffer/Uint8Array binary data
|
|
476
|
+
* @param sqlParams SQL parameters for the REST request
|
|
477
|
+
*
|
|
478
|
+
*/
|
|
479
|
+
async doRequest(method:string, rowId:string, data:string|OINODataRow[]|Buffer|Uint8Array|object|null, sqlParams:OINODbSqlParams):Promise<OINODbApiResult> {
|
|
480
|
+
return this.runRequest(new OINODbApiRequest({ method: method, rowId: rowId, data: data, sqlParams: sqlParams }))
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Method for handling a HTTP REST request with GET, POST, PUT, DELETE corresponding to
|
|
484
|
+
* SQL select, insert, update and delete.
|
|
485
|
+
*
|
|
486
|
+
* @param request OINO DB API request
|
|
487
|
+
*
|
|
488
|
+
*/
|
|
489
|
+
async runRequest(request:OINODbApiRequest):Promise<OINODbApiResult> {
|
|
490
|
+
OINOBenchmark.startMetric("OINODbApi", "doRequest." + request.method)
|
|
491
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "doRequest", "Request", {method:request.method, id:request.rowId, data:request.data})
|
|
492
|
+
let result:OINODbApiResult = new OINODbApiResult(request)
|
|
493
|
+
let rows:OINODataRow[] = []
|
|
494
|
+
if ((request.method == "POST") || (request.method == "PUT")) {
|
|
495
|
+
rows = this._parseData(result, request)
|
|
496
|
+
}
|
|
497
|
+
if (request.method == "GET") {
|
|
498
|
+
await this._doGet(result, request.rowId, request)
|
|
499
|
+
|
|
500
|
+
} else if (request.method == "PUT") {
|
|
501
|
+
if (!request.rowId) {
|
|
502
|
+
result.setError(400, "HTTP PUT method requires an URL ID for the row that is updated!", "DoRequest")
|
|
503
|
+
|
|
504
|
+
} else if (rows.length != 1) {
|
|
505
|
+
result.setError(400, "HTTP PUT method requires exactly one row in the body data!", "DoRequest")
|
|
506
|
+
|
|
507
|
+
} else {
|
|
508
|
+
try {
|
|
509
|
+
await this._doPut(result, request.rowId, rows)
|
|
510
|
+
|
|
511
|
+
} catch (e:any) {
|
|
512
|
+
result.setError(500, "Unhandled exception in HTTP PUT doRequest: " + e.message, "DoRequest")
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
} else if (request.method == "POST") {
|
|
516
|
+
if (request.rowId) {
|
|
517
|
+
result.setError(400, "HTTP POST method must not have an URL ID as it does not target an existing row but creates a new one!", "DoRequest")
|
|
518
|
+
|
|
519
|
+
} else if (rows.length == 0) {
|
|
520
|
+
result.setError(400, "HTTP POST method requires at least one row in the body data!", "DoRequest")
|
|
521
|
+
|
|
522
|
+
} else {
|
|
523
|
+
try {
|
|
524
|
+
await this._doPost(result, rows)
|
|
525
|
+
|
|
526
|
+
} catch (e:any) {
|
|
527
|
+
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest")
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
} else if (request.method == "DELETE") {
|
|
531
|
+
if (!request.rowId) {
|
|
532
|
+
result.setError(400, "HTTP DELETE method requires an id!", "DoRequest")
|
|
533
|
+
|
|
534
|
+
} else {
|
|
535
|
+
try {
|
|
536
|
+
await this._doDelete(result, request.rowId, null)
|
|
537
|
+
|
|
538
|
+
} catch (e:any) {
|
|
539
|
+
result.setError(500, "Unhandled exception in HTTP DELETE doRequest: " + e.message, "DoRequest")
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
} else {
|
|
543
|
+
result.setError(405, "Unsupported HTTP method '" + request.method + "' for REST request", "DoRequest")
|
|
544
|
+
}
|
|
545
|
+
OINOBenchmark.endMetric("OINODbApi", "doRequest." + request.method)
|
|
546
|
+
return Promise.resolve(result)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Method for handling a HTTP REST request with batch update using PUT or DELETE methods.
|
|
551
|
+
*
|
|
552
|
+
* @param method HTTP method of the REST request
|
|
553
|
+
* @param rowId URL id of the REST request
|
|
554
|
+
* @param data HTTP body data as either serialized string or unserialized JS object or OINODataRow-array or Buffer/Uint8Array binary data
|
|
555
|
+
*
|
|
556
|
+
*/
|
|
557
|
+
async doBatchUpdate(method:string, rowId:string, data:string|OINODataRow[]|Buffer|Uint8Array|object|null, sqlParams?: OINODbSqlParams):Promise<OINODbApiResult> {
|
|
558
|
+
return this.runRequest(new OINODbApiRequest({ method: method, rowId: rowId, data: data, sqlParams: sqlParams }))
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Method for handling a HTTP REST request with batch update using PUT or DELETE methods.
|
|
562
|
+
*
|
|
563
|
+
* @param request HTTP URL parameters as key-value-pairs
|
|
564
|
+
*
|
|
565
|
+
*/
|
|
566
|
+
async runBatchUpdate(request:OINODbApiRequest):Promise<OINODbApiResult> {
|
|
567
|
+
OINOLog.debug("@oino-ts/db", "OINODbApi", "doBatchUpdate", "Request", {request:request, data:request.data})
|
|
568
|
+
let result:OINODbApiResult = new OINODbApiResult(request)
|
|
569
|
+
if ((request.method != "PUT") && (request.method != "DELETE")) {
|
|
570
|
+
result.setError(500, "Batch update only supports PUT and DELETE methods!", "DoBatchUpdate")
|
|
571
|
+
return Promise.resolve(result)
|
|
572
|
+
}
|
|
573
|
+
OINOBenchmark.startMetric("OINODbApi", "doBatchUpdate." + request.method)
|
|
574
|
+
const rows:OINODataRow[] = [] = this._parseData(result, request)
|
|
575
|
+
if (request.method == "PUT") {
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
await this._doPut(result, null, rows)
|
|
579
|
+
|
|
580
|
+
} catch (e:any) {
|
|
581
|
+
result.setError(500, "Unhandled exception in HTTP PUT doRequest: " + e.message, "DoBatchUpdate")
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
} else if (request.method == "DELETE") {
|
|
585
|
+
try {
|
|
586
|
+
await this._doDelete(result, null, rows)
|
|
587
|
+
|
|
588
|
+
} catch (e:any) {
|
|
589
|
+
result.setError(500, "Unhandled exception in HTTP DELETE doRequest: " + e.message, "DoBatchUpdate")
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
OINOBenchmark.endMetric("OINODbApi", "doBatchUpdate." + request.method)
|
|
593
|
+
return Promise.resolve(result)
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Method to check if a field is included in the API params.
|
|
598
|
+
*
|
|
599
|
+
* @param fieldName name of the field
|
|
600
|
+
*
|
|
601
|
+
*/
|
|
602
|
+
|
|
603
|
+
public isFieldIncluded(fieldName:string):boolean {
|
|
604
|
+
const params = this.params
|
|
605
|
+
return (
|
|
606
|
+
((params.excludeFieldPrefix == undefined) || (params.excludeFieldPrefix == "") || (fieldName.startsWith(params.excludeFieldPrefix) == false)) &&
|
|
607
|
+
((params.excludeFields == undefined) || (params.excludeFields.length == 0) || (params.excludeFields.indexOf(fieldName) < 0)) &&
|
|
608
|
+
((params.includeFields == undefined) || (params.includeFields.length == 0) || (params.includeFields.indexOf(fieldName) >= 0))
|
|
609
|
+
)
|
|
610
|
+
}
|
|
611
|
+
|
|
603
612
|
}
|