bonsaif 1.10.3

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.
@@ -0,0 +1,681 @@
1
+ /**
2
+ * ::: B[]NSAIF() ::: => 2022
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const utl = require('../utl');
8
+ let debug = false;
9
+ let tag = ` ::: B[]NSAIF() ::: => mongodb.js `;
10
+ const ObjectId = require('mongodb').ObjectId;
11
+
12
+ const find=async(options,dbm, col, query, orderby, limit)=>{
13
+ const exec = require("./exec");
14
+ const mongoclient = exec.mongoConn(options);
15
+ limit = limit!=null?limit*1:0;
16
+ if (limit=-1){
17
+ limit = 0;
18
+ }
19
+ orderby = orderby!=null?orderby:'';
20
+ const start = Date.now();
21
+ //console.log(' ****find ['+JSON.stringify(query)+'] limit ['+limit+']');
22
+
23
+ let results = new Array();
24
+ //let obj_result = {"alias":alias,"dml":dml,"headers":"","columns":0,"error":0,"msg":"","ip":ip, "time":0}
25
+ return new Promise((resolve, reject)=>{
26
+ mongoclient.then(
27
+ function(client){
28
+ let db = client.db(dbm);
29
+ db.collection(col).find(query).sort(orderby).limit(limit).toArray(function(err, result) {
30
+ const end = Date.now();
31
+ const time = end - start;
32
+
33
+ if (err) {
34
+ resolve({"result":{"dml":"find", "headers":"", "time":utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
35
+ }else{
36
+ resolve({"result":{"dml":"find", "headers":getFields(result[0]), "time":utl.milisegundosASegundos(time), code:200, error:0}, data:result});
37
+ }
38
+
39
+ try{
40
+ exec.mongoClose(mongoclient);
41
+ }catch(e){
42
+ utl.log('err.find '+e);
43
+ }
44
+ });
45
+ }
46
+ ).catch(err=>{
47
+ resolve({"result":{"dml":"find", "headers":"", time:0, code:404, error:1}, "results":err});
48
+ });
49
+ })
50
+ }
51
+
52
+
53
+ const count=async(options,dbm, col, json)=>{
54
+ let {filter:query={}}=json;
55
+ const exec = require("./exec");
56
+ const mongoclient = exec.mongoConn(options);
57
+ const start = Date.now();
58
+ return new Promise((resolve, reject)=>{
59
+ mongoclient.then(
60
+ function(client){
61
+ let db = client.db(dbm);
62
+ db.collection(col).find(query).count(function(err, res) {
63
+
64
+ const end = Date.now();
65
+ const time = end - start;
66
+
67
+ if (err) {
68
+ resolve({result:{dml:"count", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
69
+ }else{
70
+ let data = {"count":res};
71
+ resolve({"result":{dml:"count", headers:"count", "time":utl.milisegundosASegundos(time), code:200, error:0}, results:res, data});
72
+ }
73
+ try{
74
+ exec.mongoClose(mongoclient);
75
+ }catch(e){
76
+ utl.log('err.count '+e);
77
+ }
78
+ });
79
+ }
80
+ ).catch(err=>{
81
+ resolve({result:{dml:"insert", headers:"", time:0, code:404, error:1}, results:err});
82
+ });
83
+ })
84
+ }
85
+
86
+ const insert= async(options,dbm, col, json_obj)=>{
87
+ const exec = require("./exec");
88
+
89
+ const mongoclient = exec.mongoConn(options);
90
+ const start = Date.now();
91
+
92
+ //json_obj = formatAttributes(json_obj);
93
+
94
+ let _id = ObjectId();
95
+ let json_insert ={};
96
+ try{
97
+ // 2022/12/08 VRSZ Se soluciona error en numeros enteros ya que los cambiaba a string
98
+ json_insert = { _id , ...json_obj };
99
+ }catch(e){
100
+ utl.log(e);
101
+ }
102
+
103
+ return new Promise((resolve, reject)=>{
104
+ mongoclient.then(
105
+ function(client){
106
+ let db = client.db(dbm);
107
+ db.collection(col).insertOne(json_insert, function(err, res) {
108
+ const end = Date.now();
109
+ const time = end - start;
110
+ if (err) {
111
+ resolve({result:{dml:"insert", headers:"insertId", insertId:_id, time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
112
+ }else{
113
+ let data = {"insertId":_id};
114
+ let ops=res.ops!=null?res.ops:{};
115
+ resolve({result:{dml:"insert", headers:"insertId", insertId:_id, time:utl.milisegundosASegundos(time), code:200, error:0}, results:{WriteResult:'1 document inserted', ops}, data:[data]});
116
+ }
117
+ try{
118
+ exec.mongoClose(mongoclient);
119
+ }catch(e){
120
+ utl.log('err.insert '+e);
121
+ }
122
+ });
123
+ }
124
+ ).catch(err=>{
125
+ resolve({"result":{"dml":"insert", "headers":"", time:0, code:404, error:1}, results:err});
126
+ });
127
+ })
128
+ }
129
+
130
+ const update=async(options,dbm, col, json_obj, query)=>{
131
+ const exec = require("./exec");
132
+
133
+ const mongoclient = exec.mongoConn(options);
134
+ const start = Date.now();
135
+
136
+ //json_obj = formatAttributes(json_obj);
137
+
138
+ return new Promise((resolve, reject)=>{
139
+ mongoclient.then(
140
+ function(client){
141
+ let db = client.db(dbm);
142
+ db.collection(col).updateOne(query, { $set: json_obj }, function(err, res) {
143
+ const end = Date.now();
144
+ const time = end - start;
145
+ let result, nModified=0;
146
+ try{ result = res.result; nModified = res.result.nModified; } catch(e){ }
147
+ if (err) {
148
+ resolve({result:{dml:"update", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
149
+ }else{
150
+ resolve({result:{dml:"update", headers:"update", time:utl.milisegundosASegundos(time), code:200, error:0}, results:{WriteResult:`${nModified} document Updated`, result }});
151
+ }
152
+ try{
153
+ exec.mongoClose(mongoclient);
154
+ }catch(e){
155
+ utl.log('err.update '+e);
156
+ }
157
+ });
158
+ }
159
+ ).catch(err=>{
160
+ resolve({result:{dml:"update", headers:"", time:0, code:404, error:1}, results:err});
161
+ });
162
+ })
163
+ }
164
+
165
+ const upsert=async(options,dbm, col, json_obj, query)=>{
166
+ return new Promise((resolve, reject)=>{
167
+ find(options, dbm,col, query)
168
+ .then(result=>{
169
+ if (result.error==1){
170
+ resolve(result);
171
+ }
172
+
173
+ if (result.data[0]){ //update
174
+ update(options,dbm,col, json_obj, query)
175
+ .then(result_update=>{
176
+ resolve(result_update);
177
+ })
178
+ .catch(err=>{
179
+ reject(err);
180
+ });
181
+ }else{ // Insert
182
+ insert(options,dbm,col, json_obj)
183
+ .then(result_insert=>{
184
+ resolve(result_insert);
185
+ })
186
+ .catch(err=>{
187
+ reject(err);
188
+ });
189
+ }
190
+ })
191
+ .catch(err=>{
192
+ reject(err);
193
+ });
194
+ })
195
+ }
196
+
197
+
198
+ const dbs=async(options)=>{
199
+ const exec = require("./exec");
200
+
201
+ const mongoclient = exec.mongoConn(options);
202
+ const start = Date.now();
203
+ return new Promise((resolve, reject)=>{
204
+ mongoclient.then(
205
+ function(client){
206
+ let db = client.db().admin();
207
+ db.listDatabases(function(err, res) {
208
+ const end = Date.now();
209
+ const time = end - start;
210
+ if (err) {
211
+ resolve({result:{dml:"dbs", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
212
+ }else{
213
+ res.time=utl.milisegundosASegundos(time);
214
+ let databases=res.databases!=null?res.databases:{};
215
+ let totalSize=res.totalSize!=null?res.totalSize:0;
216
+ resolve({result:{dml:"dbs", headers:getFields(databases[0]), time:utl.milisegundosASegundos(time), code:200, error:0}, results:{totalSize}, data:databases});
217
+ }
218
+ try{
219
+ exec.mongoClose(mongoclient);
220
+ }catch(e){
221
+ utl.log('err.dbs '+e);
222
+ }
223
+ });
224
+ }
225
+ ).catch(err=>{
226
+ resolve({result:{dml:"dbs", headers:"", time:0, code:404, error:1}, results:err});
227
+ });
228
+ })
229
+ }
230
+
231
+ const collections=async(options,dbm)=>{
232
+ const exec = require("./exec");
233
+
234
+ const mongoclient = exec.mongoConn(options);
235
+ const start = Date.now();
236
+ return new Promise((resolve, reject)=>{
237
+ mongoclient.then(
238
+ function(client){
239
+ let db = client.db(dbm);
240
+ db.listCollections().toArray(function(err, res) {
241
+
242
+ const end = Date.now();
243
+ const time = end - start;
244
+
245
+ if (err) {
246
+ resolve({result:{dml:"collections", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
247
+ }else{
248
+ resolve({result:{dml:"collections", headers:"name", time:utl.milisegundosASegundos(time), code:200, error:0}, results:res, data:res});
249
+ }
250
+ try{
251
+ exec.mongoClose(mongoclient);
252
+ }catch(e){
253
+ utl.log('err.collections '+e);
254
+ }
255
+ });
256
+ }
257
+ ).catch(err=>{
258
+ resolve({result:{dml:"collections", headers:"", time:0, code:404, error:1}, results:err});
259
+ });
260
+ })
261
+ }
262
+
263
+ const formatAttributes=(json_obj)=>{
264
+ for(let attributename in json_obj){
265
+ let vl = json_obj[attributename];
266
+ //2022/04/21 VRSZ Se realiza ajuste de lo contrario los vacios los toma como un numero
267
+ if (!isNaN(vl*1)){
268
+ eval(" json_obj."+attributename+"="+vl*1+";");
269
+ }
270
+ }
271
+ return json_obj;
272
+ }
273
+
274
+ const getFields=(json)=>{
275
+ let fields = '';
276
+ try{
277
+ for(let field in json){
278
+ if (fields.length>0){
279
+ fields = fields + "|";
280
+ }
281
+ fields = fields + field;
282
+ }
283
+ }
284
+ catch(e){
285
+ utl.log('err.getFields ['+e+']');
286
+ }
287
+ return fields;
288
+ }
289
+
290
+ //2022/04/28 VRSZ Construye el query para utilizarlo en mongo
291
+ const buildQuery=(field,value)=>{
292
+ let where = {}, query = {};
293
+ let ltField, ltValue;
294
+ try{
295
+ ltField = field.split("|");
296
+ ltValue = value.split("|");
297
+ }catch(e){
298
+ //utl.log('err.1 buildQuery'+e);
299
+ }
300
+
301
+ try{
302
+ for (let i in ltField){
303
+ let query_in ={};
304
+ let val = ltValue[i];
305
+ let number = false;
306
+ let tipo = "";
307
+ try{
308
+ let valN = val *1;
309
+ if(!isNaN(valN)){
310
+ number = true;
311
+ tipo = "int";
312
+ }
313
+ }catch(e){
314
+
315
+ }
316
+
317
+ if (ltField[i]=='_id'){
318
+ tipo= "id";
319
+ }
320
+ //console.log('tipo:'+tipo);
321
+ switch (tipo){
322
+ case 'id':
323
+ eval('where.'+ltField[i]+' = new ObjectId('+val+'); ');
324
+ break;
325
+
326
+ case 'int':
327
+ eval('where.'+ltField[i]+' = { $in:['+val+',"'+val+'"] };');
328
+ break;
329
+
330
+ default:
331
+ //eval(' query_in.$regex = /^'+val+'$/i;'); //equals ignore case
332
+ //eval('where.'+ltField[i]+' = query_in;');
333
+ eval(`where.${ltField[i]} = ${val};`);
334
+
335
+ }
336
+ }
337
+ if (field!=''){
338
+ eval('query.$and = [ where ];');
339
+ }
340
+ }catch(e){
341
+ //utl.log('err.2 buildQuery'+e);
342
+ }
343
+
344
+ return query;
345
+ }
346
+
347
+ const buildOrderBy=(fieldOrder, valueOrder)=>{
348
+ let orderby ={};
349
+ let ltFieldOrder, ltValueOrder;
350
+ try{
351
+ ltFieldOrder = fieldOrder.split("|");
352
+ ltValueOrder = valueOrder.split("|");
353
+ }catch(e){
354
+
355
+ }
356
+ try{
357
+ for (let i in ltFieldOrder){
358
+ let val = '1'; //order asc
359
+ try{
360
+ val = ltValueOrder[i];
361
+ }catch(e){
362
+
363
+ }
364
+ eval('orderby.'+ltFieldOrder[i]+' = '+val);
365
+ }
366
+ }catch(e){
367
+
368
+ }
369
+ return orderby;
370
+ }
371
+
372
+
373
+ const command=async(options,dbm, json)=>{
374
+
375
+ const exec = require("./exec");
376
+ const mongoclient = exec.mongoConn(options);
377
+ const start = Date.now();
378
+
379
+ let find = utl.ObjectEmpty(json, 'find') ? true: false;
380
+ //2022/09/15 VRSZ Se realiza validacion para poder buscar el _id en mongo
381
+
382
+ let _id=false;
383
+ try{if(json.filter._id){_id=json.filter._id}}catch(e){}
384
+
385
+ if (_id){
386
+ try{
387
+ if (typeof _id == "string") {
388
+ json.filter._id = new ObjectId(_id);
389
+ }else{ // fix filters in _id
390
+ for (let field in json.filter._id){
391
+ let value = json.filter._id[field];
392
+ json.filter._id[field] = new ObjectId(value);
393
+ }
394
+ }
395
+ }catch(e){
396
+ console.log('json.filter.err',e)
397
+ }
398
+ }
399
+
400
+ return new Promise((resolve, reject)=>{
401
+ mongoclient.then(
402
+ function(client){
403
+ let db = client.db(dbm);
404
+ db.command(json,function(err, res) {
405
+ const end = Date.now();
406
+ const time = end - start;
407
+
408
+ if (err) {
409
+ resolve({result:{dml:"command", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
410
+ }else{
411
+ if (find){
412
+ let rFind = res.cursor.firstBatch;
413
+ resolve({result:{dml:"find", headers:getFields(rFind[0]), time:utl.milisegundosASegundos(time), code:200, error:0}, data:rFind});
414
+ }else{
415
+ resolve({result:{dml:"command", headers:"", time:utl.milisegundosASegundos(time), code:200, error:0}, results:res});
416
+ }
417
+ }
418
+
419
+ try{
420
+ exec.mongoClose(mongoclient);
421
+ }catch(e){
422
+ utl.log('err.find '+e);
423
+ }
424
+ });
425
+ }
426
+ ).catch(err=>{
427
+ resolve({result:{dml:"insert", headers:"", time:0, code:404, error:1}, results:err});
428
+ });
429
+ })
430
+ }
431
+
432
+ const deleteMany=async(options,dbm, col, json)=>{
433
+ let {filter:query={}}=json;
434
+ const exec = require("./exec");
435
+ const mongoclient = exec.mongoConn(options);
436
+ const start = Date.now();
437
+ return new Promise((resolve, reject)=>{
438
+ mongoclient.then(
439
+ function(client){
440
+ let db = client.db(dbm);
441
+ db.collection(col).deleteMany(query,function(err, res) {
442
+
443
+ const end = Date.now();
444
+ const time = end - start;
445
+
446
+ if (err) {
447
+ resolve({result:{dml:"deleteMany", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
448
+ }else{
449
+ resolve({"result":{dml:"deleteMany", headers:"", "time":utl.milisegundosASegundos(time), code:200, error:0}, results:res});
450
+ }
451
+ try{
452
+ exec.mongoClose(mongoclient);
453
+ }catch(e){
454
+ utl.log('err.deleteMany '+e);
455
+ }
456
+ });
457
+ }
458
+ ).catch(err=>{
459
+ resolve({result:{dml:"deleteMany", headers:"", time:0, code:404, error:1}, results:err});
460
+ });
461
+ })
462
+ }
463
+
464
+ const updateMany=async(options,dbm, col, json_obj, query)=>{
465
+ const exec = require("./exec");
466
+
467
+ const mongoclient = exec.mongoConn(options);
468
+ const start = Date.now();
469
+
470
+ //json_obj = formatAttributes(json_obj);
471
+
472
+ return new Promise((resolve, reject)=>{
473
+ mongoclient.then(
474
+ function(client){
475
+ let db = client.db(dbm);
476
+ db.collection(col).updateMany(query, { $set: json_obj }, function(err, res) {
477
+ const end = Date.now();
478
+ const time = end - start;
479
+ let result, nModified=0;
480
+ try{ result = res.result; nModified = res.result.nModified; } catch(e){ }
481
+ if (err) {
482
+ resolve({result:{dml:"updateMany", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
483
+ }else{
484
+ resolve({result:{dml:"updateMany", headers:"updateMany", time:utl.milisegundosASegundos(time), code:200, error:0}, results:{WriteResult:`${nModified} document Updated`, result }});
485
+ }
486
+ try{
487
+ exec.mongoClose(mongoclient);
488
+ }catch(e){
489
+ utl.log('err.updateMany '+e);
490
+ }
491
+ });
492
+ }
493
+ ).catch(err=>{
494
+ resolve({result:{dml:"update", headers:"", time:0, code:404, error:1}, results:err});
495
+ });
496
+ })
497
+ }
498
+
499
+ const drop=async(options,dbm, col)=>{
500
+ const exec = require("./exec");
501
+ const mongoclient = exec.mongoConn(options);
502
+ const start = Date.now();
503
+ return new Promise((resolve, reject)=>{
504
+ mongoclient.then(
505
+ function(client){
506
+ let db = client.db(dbm);
507
+ db.collection(col).drop(function(err, res) {
508
+
509
+ const end = Date.now();
510
+ const time = end - start;
511
+
512
+ if (err) {
513
+ resolve({result:{dml:"drop", headers:"", time:utl.milisegundosASegundos(time), code:204, error:1, msg:err}, results:err});
514
+ }else{
515
+ let data = {"drop":res};
516
+ resolve({"result":{dml:"drop", headers:"drop", "time":utl.milisegundosASegundos(time), code:200, error:0}, results:res, data});
517
+ }
518
+ try{
519
+ exec.mongoClose(mongoclient);
520
+ }catch(e){
521
+ utl.log('err.drop '+e);
522
+ }
523
+ });
524
+ }
525
+ ).catch(err=>{
526
+ resolve({result:{dml:"insert", headers:"", time:0, code:404, error:1}, results:err});
527
+ });
528
+ })
529
+ }
530
+
531
+ //fix: solves the problem of queries that have more than 23K records
532
+ const findMany=async(options,dbm, col, json)=>{
533
+ const start = Date.now();
534
+ let {limit=0, sort={}} = json ? json : {};
535
+ let result=[];
536
+ if (limit>0){
537
+ let result = await command(options,dbm,json);
538
+ return {...result};
539
+ }else{
540
+ let {_id:_id_sort=''}=sort?sort:{};
541
+ if (_id_sort=='-1'){
542
+ json.sort._id = 1;
543
+ }
544
+ let count_rows = await count(options,dbm,col, json);
545
+ //utl.log('count_rows',count_rows);
546
+ let {count:total=0} = count_rows.data ? count_rows.data :0;
547
+ let limit_part = 3000; // fix:15000 version: 3.2.11
548
+ let parts = Math.ceil(total / limit_part);
549
+ json.limit= limit_part;
550
+ json.batchSize= limit_part;
551
+
552
+ let batch_rows = [], last_row={}, _id ='';
553
+ let dataset = [];
554
+ if (total==0){
555
+ result= await command(options,dbm,json);
556
+ }
557
+
558
+ while (parts>0){
559
+ if (_id!=''){
560
+ eval(`json.filter._id = { '$gt': _id } `);
561
+ }
562
+
563
+ result= await command(options,dbm,json);
564
+ batch_rows = result.data;
565
+
566
+ for (let rows of batch_rows){
567
+ dataset.push(rows);
568
+ }
569
+
570
+ last_row = batch_rows.pop();
571
+ _id = last_row._id;
572
+ parts--;
573
+ }
574
+ const end = Date.now();
575
+ const time = end - start;
576
+ try{
577
+ result.result.time=time;
578
+ result.data = dataset;
579
+ }catch(e){
580
+ }
581
+ return {...result};
582
+ }
583
+ }
584
+
585
+ const api=async(options,dbm, json)=>{
586
+ let dml = ''; let json_api, query, col;
587
+ let {filter=''} = json;
588
+ try{
589
+ /* 2022/12/08 Se quita esta regla para evitar problemas en los filtros en el update
590
+ let field='', value='';
591
+ for (let x in filter){
592
+ if (field.length>0){ field = field +"|"; value = value +"|"; }
593
+ field = field +x; value = value+ JSON.stringify(filter[x]); //value = value+ filter[x];
594
+ } query = buildQuery(field,value);
595
+ */
596
+ let {_id=false} = filter ? filter : {};
597
+ if (_id){
598
+ filter._id = new ObjectId(_id);
599
+ }
600
+ query = filter;
601
+ }catch(e){
602
+ }
603
+
604
+ if (utl.ObjectEmpty(json, 'upsert')){
605
+ dml = 'upsert';
606
+ json_api = json.document;
607
+ }
608
+
609
+ if (utl.ObjectEmpty(json, 'insert')){
610
+ dml = 'insert';
611
+ json_api = json.documents?json.documents:[];
612
+ if (json_api.length==1){
613
+ json_api = json.documents[0];
614
+ }else{
615
+ dml = 'insertMany';
616
+ }
617
+ }
618
+
619
+ if (utl.ObjectEmpty(json, 'update')){
620
+ dml = 'update';
621
+ json_api = json.documents?json.documents:[];
622
+ if (json_api.length==1){
623
+ json_api = json.documents[0];
624
+ }else{
625
+ dml = 'updateMany';
626
+ }
627
+ }
628
+
629
+ if (utl.ObjectEmpty(json, 'updateMany')){
630
+ dml = 'updateMany';
631
+ json_api = json.documents?json.documents:[];
632
+ if (json_api.length==1){
633
+ json_api = json.documents[0];
634
+ }else{
635
+ dml = 'updateMany';
636
+ }
637
+ }
638
+
639
+ let ltdml = ['find','delete','count','dbs','collections','deleteMany','drop'];
640
+ for (let x of ltdml){
641
+ if (utl.ObjectEmpty(json,x)){
642
+ dml = x; break;
643
+ }
644
+ }
645
+
646
+ eval(` try{ col = json.${dml}; } catch(e){ } `);
647
+ let r;
648
+ switch (dml){
649
+ case 'insert': r = await insert(options,dbm,col, json_api); break;
650
+ case 'upsert': r = await upsert(options,dbm,col, json_api, query); break;
651
+ case 'update': r = await update(options,dbm,col, json_api, query); break;
652
+ case 'count': r = await count(options,dbm,col, json); break;
653
+ case 'dbs': r = await dbs(options); break;
654
+ case 'collections': r = await collections(options,dbm); break;
655
+ case 'deleteMany': r = await deleteMany(options,dbm,col, json); break;
656
+ case 'updateMany': r = await updateMany(options,dbm,col, json_api, query); break;
657
+ case 'drop': r = await drop(options,dbm,col); break;
658
+ case 'find': r = await findMany(options,dbm,col,json); break;
659
+ default: r = await command(options,dbm,json);
660
+ }
661
+
662
+ return new Promise((resolve, reject)=>{
663
+ resolve(r);
664
+ })
665
+ }
666
+
667
+ module.exports ={
668
+ find,
669
+ insert,
670
+ update,
671
+ count,
672
+ dbs,
673
+ collections,
674
+ upsert,
675
+ buildQuery,
676
+ buildOrderBy,
677
+ command,
678
+ api,
679
+ drop,
680
+ findMany
681
+ }