@xuda.io/xuda-dbs-plugin-xuda 1.0.94 → 1.0.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/studio.mjs +1215 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/xuda-dbs-plugin-xuda",
3
- "version": "1.0.94",
3
+ "version": "1.0.96",
4
4
  "description": "Xuda Database Socket for Xuda's proprietary structure powered by CouchDB",
5
5
  "scripts": {
6
6
  "pub": "npm version patch --force && npm publish --access public"
package/studio.mjs ADDED
@@ -0,0 +1,1215 @@
1
+ const check_unique = async function (e, docP, table_obj, db) {
2
+ var len = docP.udfIndex.length;
3
+ if (!len) {
4
+ return { code: -11, data: "table must have primary index" };
5
+ }
6
+ var found_unique = undefined;
7
+ var ret = { code: 1, data: "ok" };
8
+
9
+ for await (var val of docP.udfIndex) {
10
+ if (!table_obj.tableIndexes) {
11
+ ret = {
12
+ code: -14,
13
+ data: "table definition missing for: " + val.fileId,
14
+ };
15
+ break;
16
+ }
17
+
18
+ const table_index = find_item_by_key_root(
19
+ table_obj.tableIndexes,
20
+ "id",
21
+ val.indexId
22
+ );
23
+
24
+ if (!table_index) {
25
+ ret = {
26
+ code: -13,
27
+ data: "keys definition missing for Table: " + val.fileId,
28
+ };
29
+ break;
30
+ }
31
+
32
+ if (!table_index.data.unique) {
33
+ continue;
34
+ }
35
+ if (!table_index?.data?.keys || _.isEmpty(table_index.data.keys)) {
36
+ ret = {
37
+ code: -14,
38
+ data: "keys definition missing for index: " + val.indexId,
39
+ };
40
+ break;
41
+ }
42
+
43
+ var keysArr = table_index.data.keys;
44
+ var keyValue = [];
45
+
46
+ for await (const [keySegment, valSegment] of Object.entries(keysArr)) {
47
+ // run on key segment
48
+ let _fieldType = find_item_by_key(
49
+ table_obj.tableFields,
50
+ "field_id",
51
+ valSegment
52
+ ).props.fieldType;
53
+ let _val = await get_cast_val(
54
+ "check_unique",
55
+ valSegment,
56
+ _fieldType,
57
+ val.keyValue[Number(keySegment)]
58
+ );
59
+ keyValue.push(_val);
60
+ }
61
+
62
+ var key =
63
+ '["' +
64
+ val.fileId +
65
+ '","' +
66
+ val.indexId +
67
+ '",[' +
68
+ keyValue.join(",") +
69
+ "]]";
70
+ try {
71
+ e.view = "db_index";
72
+ const ret = await query_db(e, db, table_obj);
73
+ const json = ret.data;
74
+
75
+ // var data;
76
+
77
+ if (json.code > 0) {
78
+ var data = json.data;
79
+ if (data?.rows?.length) {
80
+ for await (var val of data.rows) {
81
+ if (val.id !== docP._id) {
82
+ found_unique = true;
83
+ }
84
+ }
85
+ if (found_unique) {
86
+ throw "error checking unique:" + key;
87
+ }
88
+ }
89
+ }
90
+ // throw json.data;
91
+ return { code: 1, data: "ok" };
92
+ } catch (msg) {
93
+ console.error(msg);
94
+ ret = { code: -22, data: msg };
95
+ break;
96
+ }
97
+ }
98
+
99
+ return ret;
100
+ };
101
+
102
+ const get_index_json = async function (docInP, table_obj) {
103
+ try {
104
+ var keysArr = [];
105
+ var index_json = [];
106
+ var key_val = [];
107
+
108
+ if (docInP.udfData && table_obj) {
109
+ // check for udf data array
110
+ if (table_obj.tableIndexes) {
111
+ // console.log(udfDicIndexT.rows);
112
+ for await (var valIndex of table_obj.tableIndexes) {
113
+ // run on index rows
114
+ keysArr = valIndex.data.keys; // create array from keys string segment
115
+ key_val = [];
116
+ for await (var valSegment of keysArr) {
117
+ // run on key segment
118
+ // find keys values
119
+ if (docInP.udfData.data[valSegment]) {
120
+ key_val.push(docInP.udfData.data[valSegment]);
121
+ continue;
122
+ }
123
+ // put the value
124
+ // debugger;
125
+ const field_obj = find_item_by_key(
126
+ table_obj.tableFields,
127
+ "field_id",
128
+ valSegment
129
+ );
130
+ if (!field_obj) {
131
+ throw "field not found in key: " + valSegment;
132
+ }
133
+
134
+ let _val = await get_cast_val(
135
+ "get_index_json",
136
+ field_obj.id,
137
+ field_obj.props.fieldType,
138
+ null
139
+ );
140
+ key_val.push(_val);
141
+ }
142
+
143
+ index_json.push({
144
+ fileId: docInP.udfData.udffileid,
145
+ indexId: valIndex.id,
146
+ keySegments: keysArr,
147
+ keyValue: key_val,
148
+ });
149
+ }
150
+ // );
151
+ }
152
+ }
153
+ return { code: 1, data: index_json };
154
+ } catch (msg) {
155
+ return { code: -1, data: msg };
156
+ }
157
+ };
158
+
159
+ const find_item_by_key_root = function (arr, key, val) {
160
+ return _.find(arr, function (e) {
161
+ return e[key] === val;
162
+ });
163
+ };
164
+
165
+ const find_item_by_key = function (arr, key, val) {
166
+ return _.find(arr, function (e) {
167
+ return e.data[key] === val;
168
+ });
169
+ };
170
+
171
+ const get_cast_val = async function (source, attributeP, typeP, valP) {
172
+ return xu_cast(
173
+ typeP,
174
+ valP,
175
+ function (res) {
176
+ var msg = `error converting ${attributeP} from ${valP} to ${typeP}`;
177
+ console.error(source, msg);
178
+ },
179
+ function (res) {
180
+ var msg = `type mismatch auto conversion made to ${attributeP} from value ${valP} to ${typeP}`;
181
+ console.warn(source, msg);
182
+ }
183
+ );
184
+ };
185
+ const query_db = async function (e, db, table_obj) {
186
+ var key = undefined;
187
+
188
+ const runtime_get_mango_data = async function () {
189
+ const done = async function (body) {
190
+ const raw_data = async function () {
191
+ var rows = [];
192
+
193
+ for (var val of body.docs) {
194
+ var data = {};
195
+ if (e.fields) {
196
+ for (const [key2, val2] of Object.entries(
197
+ typeof e.fields === "string" ? e.fields.split(",") : e.fields
198
+ )) {
199
+ if (val.udfData) {
200
+ data[val2] = val["udfData"]["data"][val2];
201
+ } else {
202
+ data[val2] = null;
203
+ }
204
+ }
205
+ } else {
206
+ for (const [key2, val2] of Object.entries(table_obj.tableFields)) {
207
+ if (val.udfData) {
208
+ data[val2.data.field_id] =
209
+ val["udfData"]["data"][val2.data.field_id];
210
+ } else {
211
+ data[val2.data.field_id] = null;
212
+ }
213
+ }
214
+ }
215
+
216
+ rows.push({
217
+ id: val._id,
218
+ value: data,
219
+ });
220
+ }
221
+
222
+ return { code: 1, data: { rows: rows, total_rows: rows.length } };
223
+ };
224
+ const count_data = async function () {
225
+ var rows = [];
226
+ var keys_obj = {};
227
+ const table_index = find_item_by_key_root(
228
+ table_obj.tableIndexes,
229
+ "id",
230
+ e.indexId
231
+ );
232
+ if (e.indexId && table_index) {
233
+ var index_keys = table_index.data.keys;
234
+ var index_id = e.indexId;
235
+
236
+ for (var val of body.docs) {
237
+ var data = {};
238
+ const _tableFieldsObj = find_item_by_key(
239
+ table_obj.tableFields,
240
+ "field_id",
241
+ e.field_id
242
+ );
243
+
244
+ for (const [key2, val2] of Object.entries(table_obj.tableFields)) {
245
+ data[val2.data.field_id] =
246
+ val["udfData"]["data"][val2.data.field_id];
247
+ }
248
+
249
+ var key_arr = [];
250
+
251
+ for (const [key_idx, key_name] of Object.entries(index_keys)) {
252
+ key_arr.push(data[key_name]);
253
+ }
254
+ keys_obj[key_arr]++;
255
+ }
256
+
257
+ for (const [key_arr, key_count] of Object.entries(keys_obj)) {
258
+ rows.push({
259
+ key: [e.key, index_id, key_arr],
260
+ value: body.docs.length,
261
+ });
262
+ }
263
+ } else {
264
+ // no index
265
+ rows.push({ key: "", value: body.docs.length });
266
+ }
267
+ return { code: 1, data: { rows: rows, total_rows: rows.length } };
268
+ };
269
+
270
+ const totals = async function () {
271
+ const median = (arr) => {
272
+ const mid = Math.floor(arr.length / 2),
273
+ nums = [...arr].sort((a, b) => a - b);
274
+ return arr.length % 2 !== 0
275
+ ? nums[mid]
276
+ : (nums[mid - 1] + nums[mid]) / 2;
277
+ };
278
+
279
+ var total_fields_info = JSON.parse(e.total_fields_info);
280
+ var totals_prop = {};
281
+ var totals_obj = {};
282
+ var totals_counts = {};
283
+ var totals_arr = {};
284
+ var totals_sums = {};
285
+ var totals_group_obj = {};
286
+
287
+ for (const [key, val] of Object.entries(total_fields_info)) {
288
+ totals_counts[val.field_id] = 0;
289
+ totals_prop[val.field_id] = val;
290
+ totals_arr[val.field_id] = [];
291
+ totals_sums[val.field_id] = 0;
292
+ totals_group_obj[val.field_id] = {};
293
+ }
294
+
295
+ for (var row_data of body.docs) {
296
+ for (const [key, val] of Object.entries(row_data.udfData.data)) {
297
+ var field_id = key;
298
+ var value = val;
299
+ totals_counts[field_id]++;
300
+
301
+ switch (totals_prop[field_id].sum_type) {
302
+ case "sum":
303
+ if (typeof totals_obj[field_id] === "undefined") {
304
+ totals_obj[field_id] = value;
305
+ } else {
306
+ totals_obj[field_id] += value;
307
+ }
308
+ break;
309
+
310
+ case "average":
311
+ totals_sums[field_id] += value;
312
+ totals_obj[field_id] =
313
+ totals_sums[field_id] / totals_counts[field_id];
314
+ break;
315
+
316
+ case "median":
317
+ if (!totals_arr[field_id].includes(value)) {
318
+ totals_arr[field_id].push(value);
319
+ }
320
+ totals_obj[field_id] = median(totals_arr[field_id]);
321
+ break;
322
+ case "min":
323
+ if (
324
+ typeof totals_obj[field_id] === "undefined" ||
325
+ value < totals_obj[field_id]
326
+ ) {
327
+ totals_obj[field_id] = value;
328
+ }
329
+ break;
330
+ case "max":
331
+ if (
332
+ typeof totals_obj[field_id] === "undefined" ||
333
+ value > totals_obj[field_id]
334
+ ) {
335
+ totals_obj[field_id] = value;
336
+ }
337
+ break;
338
+ case "count":
339
+ if (typeof totals_obj[field_id] === "undefined") {
340
+ totals_obj[field_id] = 1;
341
+ } else {
342
+ totals_obj[field_id]++;
343
+ }
344
+ break;
345
+ case "distinct":
346
+ if (!totals_arr[field_id].includes(value)) {
347
+ totals_arr[field_id].push(value);
348
+ }
349
+ totals_obj[field_id] = totals_arr[field_id].length;
350
+ break;
351
+
352
+ case "group":
353
+ if (!totals_obj[field_id]) {
354
+ totals_obj[field_id] = {};
355
+ }
356
+
357
+ if (typeof totals_obj[field_id][value] === "undefined") {
358
+ totals_obj[field_id][value] = 1; //value;
359
+ } else {
360
+ totals_obj[field_id][value]++; //+= value;
361
+ }
362
+
363
+ break;
364
+ default:
365
+ totals_obj[field_id] = null;
366
+ }
367
+ }
368
+ }
369
+ return { code: 1, data: totals_obj };
370
+ };
371
+ if (e.count) {
372
+ return count_data();
373
+ }
374
+ if (e.total_fields_info) {
375
+ return totals();
376
+ }
377
+ return raw_data();
378
+ };
379
+
380
+ var limit = 99999;
381
+ var skip = 0;
382
+
383
+ if (e.limit) {
384
+ limit = Number(e.limit);
385
+ }
386
+
387
+ if (e.skip) {
388
+ skip = JSON.parse(e.skip);
389
+ }
390
+
391
+ var fields = [];
392
+ if (e.fields) {
393
+ for (const [key, val] of Object.entries(
394
+ typeof e.fields === "string" ? e.fields.split(",") : e.fields
395
+ )) {
396
+ fields.push(val);
397
+ }
398
+ } else {
399
+ for (const [key, val] of Object.entries(table_obj.tableFields)) {
400
+ fields.push(val.data.field_id);
401
+ }
402
+ }
403
+
404
+ var data = {};
405
+ var from = e.filter_from ? JSON.parse(e.filter_from) : {};
406
+ var to = e.filter_to ? JSON.parse(e.filter_to) : {};
407
+ var sort = [];
408
+ for (const [key, val] of Object.entries(from)) {
409
+ var field_name = key;
410
+
411
+ sort.push(field_name);
412
+
413
+ if (val === to[key]) {
414
+ data[field_name] = val;
415
+ } else {
416
+ data[field_name] = { $gte: val };
417
+ }
418
+ }
419
+
420
+ for (const [key, val] of Object.entries(to)) {
421
+ var field_name = key;
422
+
423
+ if (val !== from[key]) {
424
+ data[field_name]["$lte"] = val;
425
+ }
426
+ }
427
+
428
+ var selector = {};
429
+
430
+ if (from && !_.isEmpty(from)) {
431
+ selector = data;
432
+ }
433
+
434
+ var opt = {
435
+ selector,
436
+ limit: limit,
437
+ skip: skip,
438
+ fields: fields,
439
+ };
440
+
441
+ if (sort.length) {
442
+ opt.sort = sort;
443
+ }
444
+
445
+ if (e?.sort_fields?.length) {
446
+ opt.sort = e.sort_fields;
447
+ if (opt.sort) {
448
+ for (const [key, val] of Object.entries(opt.sort)) {
449
+ var field_name = val.colId;
450
+ opt.sort[key] = {
451
+ ["udfData.data." + field_name]: val.sort,
452
+ };
453
+ }
454
+ }
455
+ }
456
+ // if (e.sort_fields && JSON.parse(e.sort_fields).length) {
457
+ // opt.sort = JSON.parse(e.sort_fields);
458
+ // if (opt.sort) {
459
+ // for (const [key, val] of Object.entries(opt.sort)) {
460
+ // var field_name = val.colId;
461
+ // opt.sort[key] = {
462
+ // ["udfData.data." + field_name]: val.sort,
463
+ // };
464
+ // }
465
+ // }
466
+ // }
467
+
468
+ if (e.grid_filter_info) {
469
+ for (const [key, val] of Object.entries(e.grid_filter_info)) {
470
+ var field_name = key;
471
+ var condition = "$and";
472
+ const make_selector = function (val) {
473
+ var value = "";
474
+ var operator = "";
475
+ var value_to = "";
476
+ var operator_to = "";
477
+
478
+ if (val.filterType === "date") {
479
+ var date = val.dateFrom.substr(0, 10);
480
+ switch (val.type) {
481
+ case "equals":
482
+ operator = "$regex";
483
+ value = `^${date}`;
484
+ break;
485
+
486
+ case "greaterThan":
487
+ operator = "$gt";
488
+ value = `${date}`;
489
+ break;
490
+
491
+ case "lessThan":
492
+ operator = "$lt";
493
+ value = `${date}`;
494
+ break;
495
+
496
+ case "blank":
497
+ operator = "$eq";
498
+ value = "";
499
+ break;
500
+
501
+ case "inRange":
502
+ operator = "$gte";
503
+ value = date;
504
+ operator_to = "$lte";
505
+ value_to = val.dateTo.substr(0, 10);
506
+ break;
507
+
508
+ case "notEqual":
509
+ operator = "$regex";
510
+ value = `^((?!${date}).)*$`;
511
+ break;
512
+
513
+ case "notBlank":
514
+ operator = "$ne";
515
+ value = "";
516
+ break;
517
+
518
+ default:
519
+ operator = "$regex";
520
+ value = `^${date}`;
521
+ }
522
+ }
523
+
524
+ if (val.filterType === "string" || val.filterType === "text") {
525
+ switch (val.type) {
526
+ case "contains":
527
+ operator = "$regex";
528
+ value = `${val.filter}`;
529
+ break;
530
+
531
+ case "notContains":
532
+ operator = "$regex";
533
+ value = `^((?!${val.filter}).)*$`;
534
+ break;
535
+
536
+ case "equals":
537
+ operator = "$eq";
538
+ value = `${val.filter}`;
539
+ break;
540
+
541
+ case "notEqual":
542
+ operator = "$ne";
543
+ value = `${val.filter}`;
544
+ break;
545
+
546
+ case "startsWith":
547
+ operator = "$regex";
548
+ value = `^${val.filter}`;
549
+ break;
550
+
551
+ case "endsWith":
552
+ operator = "$regex";
553
+ value = `${val.filter}$`;
554
+ break;
555
+
556
+ case "blank":
557
+ operator = "$eq";
558
+ value = "";
559
+ break;
560
+
561
+ case "notBlank":
562
+ operator = "$ne";
563
+ value = "";
564
+ break;
565
+
566
+ default:
567
+ value = "^" + val.filter;
568
+ }
569
+ }
570
+
571
+ if (val.filterType === "number") {
572
+ switch (val.type) {
573
+ case "equals":
574
+ operator = "$eq";
575
+ value = val.filter;
576
+ break;
577
+
578
+ case "notEqual":
579
+ operator = "$ne";
580
+ value = val.filter;
581
+ break;
582
+
583
+ case "lessThanOrEqual":
584
+ operator = "$lte";
585
+ value = val.filter;
586
+ break;
587
+
588
+ case "greaterThanOrEqual":
589
+ operator = "$gte";
590
+ value = val.filter;
591
+ break;
592
+
593
+ case "lessThan":
594
+ operator = "$lt";
595
+ value = val.filter;
596
+ break;
597
+
598
+ case "greaterThan":
599
+ operator = "$gt";
600
+ value = val.filter;
601
+ break;
602
+
603
+ case "blank":
604
+ operator = "$eq";
605
+ value = 0;
606
+ break;
607
+
608
+ case "notBlank":
609
+ operator = "$ne";
610
+ value = 0;
611
+ break;
612
+
613
+ case "inRange":
614
+ operator = "$gte";
615
+ value = val.filter;
616
+ operator_to = "$lte";
617
+ value_to = val.filterTo;
618
+ break;
619
+
620
+ default:
621
+ operator = "$eq";
622
+ value = val.filter;
623
+ }
624
+ }
625
+ if (!opt.selector[field_name]) {
626
+ opt.selector[field_name] = {};
627
+ }
628
+ if (!opt.selector[field_name][condition]) {
629
+ opt.selector[field_name][condition] = [];
630
+ }
631
+ opt.selector[field_name][condition].push({
632
+ [operator]: value,
633
+ });
634
+
635
+ if (operator_to) {
636
+ opt.selector[field_name][condition].push({
637
+ [operator_to]: value_to,
638
+ });
639
+ }
640
+ };
641
+
642
+ if (!val.condition1) {
643
+ make_selector(val);
644
+ } else {
645
+ condition = "$" + val.operator.toLowerCase();
646
+ make_selector(val.condition1);
647
+ make_selector(val.condition2);
648
+ }
649
+ }
650
+ }
651
+
652
+ if (e.total_fields_info) {
653
+ fields = [];
654
+ for (const [key, val] of Object.entries(
655
+ JSON.parse(e.total_fields_info)
656
+ )) {
657
+ var field_name = val.field_id;
658
+
659
+ fields.push(field_name);
660
+ }
661
+ opt.fields = fields;
662
+ }
663
+ // fix names
664
+
665
+ for (const [key, val] of Object.entries(opt.fields)) {
666
+ opt.fields[key] = "udfData.data." + val;
667
+ }
668
+ if (!e?.sort_fields?.length) {
669
+ // added 2021 09 10
670
+ if (opt.sort) {
671
+ for (const [key, val] of Object.entries(opt.sort)) {
672
+ opt.sort[key] = {
673
+ ["udfData.data." + val]: e.sortOrder === "des" ? "desc" : "asc",
674
+ };
675
+ }
676
+ }
677
+ }
678
+ // if (!e.sort_fields || !JSON.parse(e.sort_fields).length) {
679
+ // // added 2021 09 10
680
+ // if (opt.sort) {
681
+ // for (const [key, val] of Object.entries(opt.sort)) {
682
+ // opt.sort[key] = {
683
+ // ["udfData.data." + val]: e.sortOrder === "des" ? "desc" : "asc",
684
+ // };
685
+ // }
686
+ // }
687
+ // }
688
+
689
+ var selector_new = {};
690
+
691
+ for (const [key, val] of Object.entries(opt.selector)) {
692
+ selector_new["udfData.data." + key] = val;
693
+ }
694
+
695
+ if (e.viewDbQuery) {
696
+ for (const [key, val] of Object.entries(table_obj.tableFields)) {
697
+ if (e.viewDbQuery.includes(val.id)) {
698
+ const replacer = new RegExp(val.id, "g");
699
+ e.viewDbQuery = e.viewDbQuery.replace(
700
+ replacer,
701
+ "udfData.data." + val.data.field_id
702
+ );
703
+ }
704
+ }
705
+
706
+ let viewDbQuery = JSON.parse(e.viewDbQuery.replace(/\\/g, ""));
707
+
708
+ for (const [key, val] of Object.entries(viewDbQuery)) {
709
+ selector_new[key] = val;
710
+ }
711
+ }
712
+
713
+ opt.selector = selector_new;
714
+ opt.selector["udfData.udffileid"] = e.table_id;
715
+ opt.selector.stat = e.archived ? 4 : 3;
716
+
717
+ opt.fields.push("_id");
718
+ opt.fields.push("_rev");
719
+
720
+ if (e.selector) {
721
+ opt.selector = { ...e.selector, ...opt.selector };
722
+ }
723
+
724
+ // xuda
725
+
726
+ try {
727
+ try {
728
+ // console.log("opt", opt);
729
+ const doc = await db.find(opt);
730
+
731
+ if (doc?.warning?.includes("No matching index found")) {
732
+ const index_name = `index_${e.table_id}_${new Date()
733
+ .valueOf()
734
+ .toString()}`;
735
+ var index = [];
736
+
737
+ for (const [key, val] of Object.entries(opt.selector)) {
738
+ index.push(key);
739
+ }
740
+ mango_index_obj = {
741
+ index: {
742
+ fields: index,
743
+ },
744
+ name: index_name,
745
+ ddoc: `mango_index_table_${e.table_id}`,
746
+ };
747
+ db.createIndex(mango_index_obj).then((result) => {
748
+ console.log(result);
749
+ });
750
+ }
751
+ return await done(doc);
752
+ } catch (err) {
753
+ if (err.error === "no_usable_index") {
754
+ const index_name = `index_${e.table_id}_${new Date()
755
+ .valueOf()
756
+ .toString()}`;
757
+
758
+ mango_index_obj = {
759
+ index: {
760
+ fields: opt.sort,
761
+ },
762
+ name: index_name,
763
+ ddoc: `mango_index_table_${e.table_id}`,
764
+ };
765
+
766
+ try {
767
+ const result = await db.createIndex(mango_index_obj);
768
+
769
+ const doc = await db.find(opt);
770
+ return await done(doc);
771
+ } catch (err) {
772
+ return { code: -1, data: err.message };
773
+ }
774
+ } else {
775
+ return { code: -1, data: err.message };
776
+ }
777
+ }
778
+ } catch (err) {
779
+ return { code: -1, data: err.message };
780
+ }
781
+ };
782
+
783
+ const runtime_get_query_data = async function () {
784
+ var limit = 99999;
785
+ var skip = 0;
786
+
787
+ if (e.limit) {
788
+ limit = e.limitP;
789
+ }
790
+
791
+ if (e.skipP) {
792
+ skip = e.skipP;
793
+ }
794
+
795
+ var opt = undefined;
796
+ if (key) {
797
+ opt = {
798
+ key: key,
799
+ include_docs: !e.ids && view !== "db_index_reduce",
800
+ limit: limit,
801
+ skip: skip,
802
+ };
803
+ } else {
804
+ if (e.reduce) {
805
+ opt = {
806
+ startkey: e.startkey ? JSON.parse(e.startkey) : "",
807
+ endkey: e.endkey ? JSON.parse(e.endkey) : "",
808
+ include_docs: false,
809
+ reduce: true,
810
+ group_level: 3,
811
+
812
+ descending: e.desc,
813
+ };
814
+ } else {
815
+ opt = {
816
+ startkey: e.startkey ? JSON.parse(e.startkey) : "",
817
+ endkey: e.endkey ? JSON.parse(e.endkey) : "",
818
+ include_docs: !e.ids,
819
+ limit: limit,
820
+ skip: skip,
821
+ descending: e.desc,
822
+ };
823
+ }
824
+ }
825
+
826
+ try {
827
+ const body = await db.query(view, opt);
828
+ if (e.reduce) {
829
+ let rows = [];
830
+
831
+ const table_index = find_item_by_key_root(
832
+ table_obj.tableIndexes,
833
+ "id",
834
+ e.indexId
835
+ );
836
+
837
+ for await (var val of body.rows) {
838
+ const arr = val.key[2];
839
+
840
+ var obj = {};
841
+ for await (const [arr_key, arr_val] of Object.entries(arr)) {
842
+ let field_id = table_index.data.keys[Number(arr_key)];
843
+
844
+ const _tableFieldsObj = find_item_by_key(
845
+ table_obj.tableFields,
846
+ "field_id",
847
+ field_id
848
+ );
849
+
850
+ let field_value = await get_cast_val(
851
+ "dbs_update",
852
+ e.field_id,
853
+ _tableFieldsObj.props.fieldType,
854
+ arr_val
855
+ );
856
+
857
+ obj[field_id] = field_value;
858
+ }
859
+ obj["REDUCE_VALUE"] = val.value;
860
+
861
+ rows.push({ id: crypto.randomUUID(), value: obj });
862
+ }
863
+ return { code: 1, data: { rows } };
864
+ }
865
+
866
+ var rows = [];
867
+
868
+ for await (var val of body.rows) {
869
+ if (e.ids) {
870
+ rows.push({ id: val.id, value: val.value._id });
871
+ continue;
872
+ }
873
+ rows.push({
874
+ id: val.id,
875
+ value: val.doc.udfData,
876
+ // value: { udfData: val.doc.udfData, _id: val.id },
877
+ });
878
+ }
879
+
880
+ // const reduce_rows = () => {
881
+ // const reduce_obj = body.docs.reduce(
882
+ // (params, data) => {
883
+ // const fx = (val, idx) => {
884
+ // const group_by_field = data[params.sort[idx]];
885
+
886
+ // if (params.sort[idx + 1]) {
887
+ // val[group_by_field] = val[group_by_field] ?? {};
888
+ // val[group_by_field][data[params.sort[idx + 1]]] = 0;
889
+ // idx++;
890
+ // fx(val[group_by_field], idx);
891
+ // return;
892
+ // }
893
+
894
+ // val[group_by_field] = val[group_by_field] ?? 0;
895
+ // val[group_by_field] += 1;
896
+ // };
897
+ // fx(params.group, 0);
898
+
899
+ // return params;
900
+ // },
901
+ // { sort: opt.sort, group: {} }
902
+ // );}
903
+
904
+ return { code: 1, data: { rows: rows, total_rows: rows.length } };
905
+ } catch (err) {
906
+ return { code: -1, data: err.message };
907
+ }
908
+ };
909
+
910
+ const count_tables = async function () {
911
+ var opt = {
912
+ reduce: true,
913
+ group_level: 1,
914
+ };
915
+
916
+ if (e.table_id) {
917
+ opt.key = e.table_id;
918
+ }
919
+
920
+ const body = await db.query("db_table_counts", opt);
921
+
922
+ return { code: 1, data: body };
923
+ };
924
+
925
+ if (e.reduce && JSON.parse(e.reduce)) {
926
+ view = "db_index_reduce";
927
+ return await runtime_get_query_data();
928
+ }
929
+ if (e.view === "db_index") {
930
+ key = e.key;
931
+ view = e.view;
932
+ return await runtime_get_query_data();
933
+ }
934
+
935
+ if (e.count && !e.filter_from) {
936
+ // count tables
937
+ return await count_tables();
938
+ }
939
+
940
+ return await runtime_get_mango_data();
941
+ };
942
+
943
+ export const create = async (params, resolve, reject) => {
944
+ const e = params.e;
945
+ const db = params.db;
946
+
947
+ const table_obj = params.table_obj;
948
+
949
+ const create_data_obj = async function (table_data) {
950
+ var doc = {};
951
+ for await (const val of table_obj.tableFields) {
952
+ doc[val.data.field_id] = await get_cast_val(
953
+ "dbs_create",
954
+ val.data.field_id,
955
+ val.props.fieldType,
956
+ table_data[val.data.field_id]
957
+ );
958
+ }
959
+
960
+ return doc;
961
+ };
962
+
963
+ const batch = async function () {
964
+ var docs = [];
965
+ try {
966
+ for await (var val of e.table_data) {
967
+ var doc = {
968
+ docType: "database",
969
+
970
+ user: e.uid,
971
+ stat: 3,
972
+ udfData: {
973
+ udffileid: e.table_id,
974
+ data: await create_data_obj(val),
975
+ error: {},
976
+ },
977
+
978
+ ts: new Date().valueOf(),
979
+ date: new Date().valueOf(),
980
+ };
981
+ const index_ret = await get_index_json(doc, table_obj);
982
+ if (index_ret < 0) throw index_ret.data;
983
+ doc.udfIndex = index_ret.data;
984
+
985
+ const ret = await check_unique(e, doc, table_obj, db);
986
+ if (ret.code < 0) {
987
+ throw ret;
988
+ }
989
+ docs.push(doc);
990
+ }
991
+ try {
992
+ const body = await db.bulk({ docs: docs });
993
+ return resolve(body);
994
+ } catch (error) {
995
+ return reject(error);
996
+ }
997
+ } catch (msg) {
998
+ return reject(msg);
999
+ }
1000
+ };
1001
+ const single = async function () {
1002
+ var doc = {
1003
+ docType: "database",
1004
+
1005
+ user: e.uid,
1006
+ stat: 3,
1007
+ udfData: {
1008
+ udffileid: e.table_id,
1009
+ data: await create_data_obj(e.table_data),
1010
+ error: {},
1011
+ },
1012
+
1013
+ ts: new Date().valueOf(),
1014
+ date: new Date().valueOf(),
1015
+ };
1016
+ const index_ret = await get_index_json(doc, table_obj);
1017
+ if (index_ret.code < 0) {
1018
+ return index_ret;
1019
+ }
1020
+ doc.udfIndex = index_ret.data;
1021
+ const ret = await check_unique(e, doc, table_obj, db);
1022
+ if (ret.code < 0) {
1023
+ return reject(ret.data);
1024
+ }
1025
+ try {
1026
+ const body = await db.put(doc);
1027
+ return resolve(body);
1028
+ } catch (error) {
1029
+ return reject(error);
1030
+ }
1031
+ };
1032
+ if (Array.isArray(e.table_data)) {
1033
+ return await batch();
1034
+ }
1035
+ return await single();
1036
+ };
1037
+ export const read = async (params, resolve, reject) => {
1038
+ const e = params.e;
1039
+ const db = params.db;
1040
+
1041
+ const table_obj = params.table_obj;
1042
+
1043
+ const ret = await query_db(e, db, table_obj);
1044
+ if (ret.code < 0) {
1045
+ return reject(ret.data);
1046
+ }
1047
+
1048
+ return resolve(ret.data);
1049
+ };
1050
+ export const update = async (params, resolve, reject) => {
1051
+ const e = params.e;
1052
+ const db = params.db;
1053
+
1054
+ const table_obj = params.table_obj;
1055
+ try {
1056
+ if (e.row_id === "newRecord") {
1057
+ return this.create(params, resolve, reject);
1058
+ }
1059
+ var doc = await db.get(e.row_id, {});
1060
+ // let data = doc.udfData.data;
1061
+ var error = undefined;
1062
+ if (!e.field_id && !e.table_data) {
1063
+ error = "Invalid field_id or table_data object to save";
1064
+ return reject(error);
1065
+ }
1066
+ // single value save
1067
+ if (e.field_id) {
1068
+ let _tableFieldsObj = find_item_by_key(
1069
+ table_obj.tableFields,
1070
+ "field_id",
1071
+ e.field_id
1072
+ );
1073
+ if (!_tableFieldsObj || _.isEmpty(_tableFieldsObj)) {
1074
+ return reject("Error: " + e.field_id + " - field not found");
1075
+ }
1076
+
1077
+ doc.udfData.data[e.field_id] = await get_cast_val(
1078
+ "dbs_update",
1079
+ e.field_id,
1080
+ _tableFieldsObj.props.fieldType,
1081
+ e.field_value
1082
+ );
1083
+ }
1084
+
1085
+ // object value save
1086
+ if (e.table_data) {
1087
+ // data = {};
1088
+ for await (const [key, val] of Object.entries(e.table_data)) {
1089
+ let _tableFieldsObj = find_item_by_key(
1090
+ table_obj.tableFields,
1091
+ "field_id",
1092
+ key
1093
+ );
1094
+ if (!_tableFieldsObj || _.isEmpty(_tableFieldsObj)) {
1095
+ reject("Error: " + key + " - field not found");
1096
+ break;
1097
+ }
1098
+
1099
+ doc.udfData.data[key] = await get_cast_val(
1100
+ "dbs_update",
1101
+ key,
1102
+ _tableFieldsObj.props.fieldType,
1103
+ val
1104
+ );
1105
+ }
1106
+ }
1107
+
1108
+ if (error) {
1109
+ return reject(error);
1110
+ }
1111
+ doc.ts = Date.now();
1112
+ const index_ret = await get_index_json(doc, table_obj);
1113
+ if (index_ret.code < 0) {
1114
+ return index_ret;
1115
+ }
1116
+ doc.udfIndex = index_ret.data;
1117
+ const ret = await check_unique(e, doc, table_obj, db);
1118
+ if (ret.code < 0) {
1119
+ return ret;
1120
+ }
1121
+ try {
1122
+ const body = await db.put(doc);
1123
+ return resolve(body);
1124
+ } catch (error) {
1125
+ return reject(error);
1126
+ }
1127
+ } catch (error) {
1128
+ return reject(error);
1129
+ }
1130
+ };
1131
+ export const del = async (params, resolve, reject) => {
1132
+ const e = params.e;
1133
+ const db = params.db;
1134
+
1135
+ const table_obj = params.table_obj;
1136
+ const data = await db.fetch({ keys: e.ids });
1137
+ var docs_to_delete = [];
1138
+
1139
+ for await (var val of data.rows) {
1140
+ var doc = val.doc;
1141
+
1142
+ if (doc && doc._id) {
1143
+ if (e.permanent) {
1144
+ docs_to_delete.push({
1145
+ _id: doc._id,
1146
+ _rev: doc._rev,
1147
+ _deleted: true,
1148
+ });
1149
+ } else {
1150
+ doc.stat = 4;
1151
+ doc.ts = new Date().valueOf();
1152
+ docs_to_delete.push(doc);
1153
+ }
1154
+ }
1155
+ }
1156
+ try {
1157
+ await db.bulk({ docs: docs_to_delete });
1158
+ resolve(docs_to_delete);
1159
+ } catch (error) {
1160
+ return { code: -110, data: error };
1161
+ }
1162
+ };
1163
+
1164
+ export const restore = async (params, resolve, reject) => {
1165
+ const e = params.e;
1166
+ const db = params.db;
1167
+ var docs_to_restore = [];
1168
+ const data = await db.fetch({ keys: e.ids });
1169
+
1170
+ for await (var val of data.rows) {
1171
+ var doc = val.doc;
1172
+
1173
+ if (doc && doc._id) {
1174
+ doc.stat = 3;
1175
+ doc.ts = new Date().valueOf();
1176
+ docs_to_restore.push(doc);
1177
+ }
1178
+ }
1179
+
1180
+ try {
1181
+ await db.bulk({ docs: docs_to_restore });
1182
+ resolve(docs_to_restore);
1183
+ } catch (error) {
1184
+ return reject(error);
1185
+ }
1186
+ };
1187
+
1188
+ export const _design = async (params, resolve, reject) => {
1189
+ const db = params.db;
1190
+
1191
+ const ddoc = {
1192
+ _id: "_design/xuda",
1193
+ views: {
1194
+ db_index_reduce: {
1195
+ map: 'function(doc) {\r\n if (doc.docType=="database" && doc.stat===3) {\r\n if (doc.udfIndex) {\r\n for (var i = 0; i < doc.udfIndex.length; i++)\r\n {\r\n var val = doc.udfIndex[i]; \r\n emit([val.fileId, val.indexId, val.keyValue],1);\r\n }\r\n }\r\n }\r\n \r\n}',
1196
+ reduce: "function(keys, values) {\n return sum(values);\n}",
1197
+ },
1198
+ db_index: {
1199
+ map: 'function(doc) {\r\n if (doc.docType=="database" && doc.stat===3) {\r\n if (doc.udfIndex) {\r\n for (var i = 0; i < doc.udfIndex.length; i++)\r\n {\r\n var val = doc.udfIndex[i]; \r\n emit([val.fileId, val.indexId, val.keyValue],{_id: doc._id});\r\n }\r\n }\r\n }\r\n \r\n}',
1200
+ },
1201
+
1202
+ db_table_counts: {
1203
+ map: 'function(doc) {\r\n\r\nif (doc.docType=="database" && doc.stat===3) {\r\n if(doc.udfData && doc.udfData.udffileid) \r\n emit(doc.udfData.udffileid, 1); \r\n }\r\n}',
1204
+ reduce: "function(keys, values) {\n return sum(values);\n}",
1205
+ },
1206
+ },
1207
+ };
1208
+
1209
+ try {
1210
+ const ret = await db.put(ddoc, { timeout: 99999999999 });
1211
+ resolve(ret);
1212
+ } catch (error) {
1213
+ return reject(error);
1214
+ }
1215
+ };