@dnax/core 0.0.1

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,1214 @@
1
+ import moment from "moment";
2
+ import { sessionStorage } from "../../lib/asyncLocalStorage";
3
+ import { getCollection } from "../../lib/collection";
4
+ import { getTenant } from "../../lib/tenant";
5
+ import type { Actions, Collection, Tenant } from "./../../types/index";
6
+ import { isArray, omit } from "radash";
7
+ import { ClientSession, MongoClient, ObjectId } from "mongodb";
8
+ import { contextError, fn, toJson } from "../../utils";
9
+ import * as v from "valibot";
10
+ import type { Context } from "hono";
11
+
12
+ import type {
13
+ findOneParam,
14
+ findParam,
15
+ queryParam,
16
+ updateParams,
17
+ } from "./@types";
18
+ import {
19
+ buildPipeline,
20
+ toBson,
21
+ formatData,
22
+ randomCode,
23
+ hashPasswordAuto,
24
+ cleanData,
25
+ transformAllDate,
26
+ deepSetId,
27
+ } from "./utils";
28
+ import { Cfg } from "../../config";
29
+
30
+ type options = {
31
+ tenant_id: string;
32
+ c?: Context;
33
+ useHook?: boolean;
34
+ customApi?: boolean;
35
+ };
36
+
37
+ type optionCb = {
38
+ useHook?: boolean;
39
+ cleanDeep?: boolean;
40
+ };
41
+
42
+ const omitUpdate = [
43
+ "$set._id",
44
+ "$set.id",
45
+ "$set.createdAt",
46
+ "$set.updatedAt",
47
+ "$unset",
48
+ "$rename",
49
+ ];
50
+
51
+ class useRest {
52
+ #useHook: boolean;
53
+ #c: Context | undefined;
54
+ #tenant: Tenant;
55
+ #tenant_id: string;
56
+ #session: ClientSession | null | undefined;
57
+ #customApi = false;
58
+ constructor(options: options) {
59
+ this.#c = options.c;
60
+ this.#customApi = options.customApi ?? false;
61
+ this.#tenant_id = options.tenant_id;
62
+ this.#session = null;
63
+ this.#tenant = getTenant(this.#tenant_id);
64
+ this.#useHook = options?.useHook ?? true;
65
+ /* if (options?.useHook == undefined || options?.useHook == null) {
66
+ this.#useHook = true;
67
+ } else {
68
+ this.#useHook = options.useHook;
69
+ } */
70
+ }
71
+
72
+ validator(
73
+ collection: string,
74
+ data: any,
75
+ options: { partial: boolean } = {
76
+ partial: false,
77
+ }
78
+ ): { valid: boolean; output: any; error: any } {
79
+ let col = getCollection(collection, this.#tenant_id);
80
+ let valid = true;
81
+ let output = data;
82
+ let error;
83
+ /* let issue = err?.issues[0] || {};
84
+ let msg = `Field : ${issue?.path[0]?.key} - ${issue?.message}`;
85
+ */
86
+ try {
87
+ if (col?.schema) {
88
+ if (options.partial) {
89
+ var issue = v.safeParse(v.partial(col.schema), data);
90
+ output = issue.output;
91
+ } else {
92
+ var issue = v.safeParse(col.schema, data);
93
+ output = issue.output;
94
+ }
95
+ if (issue?.success) {
96
+ } else {
97
+ valid = false;
98
+ error = `Field : ${issue?.issues[0]?.path[0]?.key} - ${issue?.issues[0]?.message}`;
99
+ }
100
+ }
101
+ } catch (err: any) {
102
+ error = err?.message;
103
+ valid = false;
104
+ }
105
+
106
+ return {
107
+ valid: valid,
108
+ output,
109
+ error: error,
110
+ };
111
+ }
112
+
113
+ async aggregate(
114
+ collection: string,
115
+ pipeline: Array<object>,
116
+ options?: optionCb
117
+ ) {
118
+ return new Promise(async (resolve, reject) => {
119
+ try {
120
+ let result = {
121
+ docs: [],
122
+ };
123
+ let useHook = options?.useHook ?? this.#useHook;
124
+ let sharedData = {};
125
+ let col = getCollection(collection, this.#tenant_id);
126
+ if (col?.hooks?.beforeOperation && useHook) {
127
+ await col.hooks.beforeOperation({
128
+ io: Cfg.io,
129
+ sharedData: sharedData,
130
+ pipeline: pipeline,
131
+ c: this.#c,
132
+ driver: "mongodb",
133
+ action: "aggregate",
134
+ session: sessionStorage(),
135
+ rest: new useRest({
136
+ useHook: false,
137
+ tenant_id: this.#tenant_id,
138
+ }),
139
+ });
140
+ }
141
+
142
+ if (col?.hooks?.beforeAggregate && useHook) {
143
+ await col.hooks.beforeAggregate({
144
+ io: Cfg.io,
145
+ sharedData: sharedData,
146
+ pipeline: pipeline,
147
+ c: this.#c,
148
+ driver: "mongodb",
149
+ action: "aggregate",
150
+ session: sessionStorage(),
151
+ rest: new useRest({
152
+ useHook: false,
153
+ tenant_id: this.#tenant_id,
154
+ }),
155
+ });
156
+ }
157
+
158
+ result.docs = await this.#tenant.database.db
159
+ ?.collection(collection)
160
+ .aggregate(pipeline, {
161
+ allowDiskUse: true,
162
+ })
163
+ .toArray();
164
+
165
+ if (col?.hooks?.afterAggregate && useHook) {
166
+ await col.hooks.afterAggregate({
167
+ io: Cfg.io,
168
+ sharedData: sharedData,
169
+ docs: result.docs,
170
+ c: this.#c,
171
+ driver: "mongodb",
172
+ action: "aggregate",
173
+ session: sessionStorage(),
174
+ result: result.docs,
175
+ rest: new useRest({
176
+ useHook: false,
177
+ tenant_id: this.#tenant_id,
178
+ }),
179
+ });
180
+ }
181
+
182
+ return resolve(result.docs);
183
+ } catch (err) {
184
+ return reject(err);
185
+ }
186
+ });
187
+ }
188
+ async insertOne(collection: string, data: object, options?: optionCb) {
189
+ return new Promise(async (resolve, reject) => {
190
+ try {
191
+ let sharedData = {};
192
+ let useHook = options?.useHook ?? this.#useHook;
193
+ let col = getCollection(collection, this.#tenant_id);
194
+ if (!col) return fn.error(`Collection ${collection} not found`, 404);
195
+
196
+ if (col?.customApi?.insertOne && !this.#customApi) {
197
+ let result = await col?.customApi?.insertOne({
198
+ io: Cfg.io,
199
+ session: sessionStorage(),
200
+ data: data,
201
+ rest: new useRest({
202
+ useHook: false,
203
+ tenant_id: this.#tenant_id,
204
+ customApi: true,
205
+ }),
206
+ });
207
+ return resolve(result);
208
+ }
209
+
210
+ // Processing before validation
211
+ data = await randomCode(data, col);
212
+ data = await hashPasswordAuto(data, col);
213
+ data = transformAllDate(data);
214
+ data = deepSetId(col, data);
215
+
216
+ var { valid, output, error } = this.validator(collection, data);
217
+ if (!valid) fn.error(error, 400);
218
+
219
+ if (col?.hooks?.beforeOperation && useHook) {
220
+ await col.hooks.beforeOperation({
221
+ sharedData: sharedData,
222
+ io: Cfg.io,
223
+ data: data,
224
+ c: this.#c,
225
+ driver: "mongodb",
226
+ action: "insertOne",
227
+ session: sessionStorage(),
228
+ rest: new useRest({
229
+ useHook: false,
230
+ tenant_id: this.#tenant_id,
231
+ }),
232
+ });
233
+ }
234
+
235
+ if (col?.hooks?.beforeInsert && useHook) {
236
+ await col.hooks.beforeInsert({
237
+ sharedData: sharedData,
238
+ data: data,
239
+ io: Cfg.io,
240
+ c: this.#c,
241
+ driver: "mongodb",
242
+ action: "insertOne",
243
+ session: sessionStorage(),
244
+ rest: new useRest({
245
+ useHook: false,
246
+ tenant_id: this.#tenant_id,
247
+ }),
248
+ });
249
+ }
250
+
251
+ await this.#tenant.database.db?.collection(collection).insertOne(
252
+ formatData(data, {
253
+ action: "insertOne",
254
+ tenant_id: this.#tenant_id,
255
+ collection: collection,
256
+ }),
257
+ {
258
+ session: this.#session ? this.#session : undefined,
259
+ }
260
+ );
261
+
262
+ if (col?.hooks?.afterInsert && useHook) {
263
+ await col.hooks.afterInsert({
264
+ sharedData: sharedData,
265
+ data: data,
266
+ c: this.#c,
267
+ io: Cfg.io,
268
+ driver: "mongodb",
269
+ result: data,
270
+ action: "insertOne",
271
+ session: sessionStorage(),
272
+ rest: new useRest({
273
+ useHook: false,
274
+ tenant_id: this.#tenant_id,
275
+ }),
276
+ });
277
+ }
278
+ return resolve(data);
279
+ } catch (err) {
280
+ return reject(err);
281
+ }
282
+ });
283
+ }
284
+ async insertMany(
285
+ collection: string,
286
+ data: Array<object>,
287
+ options?: optionCb
288
+ ) {
289
+ return new Promise(async (resolve, reject) => {
290
+ try {
291
+ let sharedData = {};
292
+ let col = getCollection(collection, this.#tenant_id);
293
+ let useHook = options?.useHook ?? this.#useHook;
294
+ if (!col) return fn.error(`Collection ${collection} not found`, 404);
295
+
296
+ if (col?.customApi?.insertMany && !this.#customApi) {
297
+ let result = await col?.customApi?.insertMany({
298
+ io: Cfg.io,
299
+ session: sessionStorage(),
300
+ data: data,
301
+ rest: new useRest({
302
+ useHook: false,
303
+ tenant_id: this.#tenant_id,
304
+ customApi: true,
305
+ }),
306
+ });
307
+ return resolve(result);
308
+ }
309
+
310
+ for await (let d of data) {
311
+ // Processing before validation
312
+ d = await randomCode(d, col);
313
+ d = await hashPasswordAuto(d, col);
314
+ d = deepSetId(col, d);
315
+ var { valid, output, error } = this.validator(collection, d);
316
+ if (!valid) fn.error(error, 400);
317
+ }
318
+
319
+ if (col?.hooks?.beforeOperation && useHook) {
320
+ await col.hooks.beforeOperation({
321
+ sharedData: sharedData,
322
+ data: data,
323
+ io: Cfg.io,
324
+ c: this.#c,
325
+ driver: "mongodb",
326
+ action: "insertMany",
327
+ session: sessionStorage(),
328
+ rest: new useRest({
329
+ useHook: false,
330
+ tenant_id: this.#tenant_id,
331
+ }),
332
+ });
333
+ }
334
+
335
+ if (col?.hooks?.beforeInsert && useHook) {
336
+ await col.hooks.beforeInsert({
337
+ sharedData: sharedData,
338
+ data: data,
339
+ io: Cfg.io,
340
+ c: this.#c,
341
+ driver: "mongodb",
342
+ action: "insertMany",
343
+ session: sessionStorage(),
344
+ rest: new useRest({
345
+ useHook: false,
346
+ tenant_id: this.#tenant_id,
347
+ }),
348
+ });
349
+ }
350
+
351
+ await this.#tenant.database.db?.collection(collection).insertMany(
352
+ formatData(data, {
353
+ collection: collection,
354
+ action: "insertMany",
355
+ tenant_id: this.#tenant_id,
356
+ }),
357
+ {
358
+ session: this.#session ? this.#session : undefined,
359
+ }
360
+ );
361
+
362
+ if (col?.hooks?.afterInsert && useHook) {
363
+ await col.hooks.afterInsert({
364
+ sharedData: sharedData,
365
+ data: data,
366
+ c: this.#c,
367
+ io: Cfg.io,
368
+ driver: "mongodb",
369
+ action: "insertMany",
370
+ result: data,
371
+ session: sessionStorage(),
372
+ rest: new useRest({
373
+ useHook: false,
374
+ tenant_id: this.#tenant_id,
375
+ }),
376
+ });
377
+ }
378
+
379
+ return resolve(data);
380
+ } catch (err) {
381
+ reject(err);
382
+ }
383
+ });
384
+ }
385
+
386
+ /**
387
+ *
388
+ * @param collection - Collection name
389
+ * @param params - Find params
390
+ * @param options
391
+ */
392
+ async find(
393
+ collection: string,
394
+ params: findParam,
395
+ options?: optionCb
396
+ ): Promise<object[]> {
397
+ return new Promise(async (resolve, reject) => {
398
+ try {
399
+ let useHook = options?.useHook ?? this.#useHook;
400
+ let sharedData = {};
401
+ let result = {
402
+ docs: [],
403
+ };
404
+
405
+ let col = getCollection(collection, this.#tenant_id);
406
+
407
+ if (col?.customApi?.find && !this.#customApi) {
408
+ let result = await col?.customApi?.find({
409
+ io: Cfg.io,
410
+ session: sessionStorage(),
411
+ params: params,
412
+ rest: new useRest({
413
+ useHook: false,
414
+ tenant_id: this.#tenant_id,
415
+ customApi: true,
416
+ }),
417
+ });
418
+ return resolve(result);
419
+ }
420
+
421
+ if (col?.hooks?.beforeOperation && useHook) {
422
+ await col.hooks.beforeOperation({
423
+ sharedData: sharedData,
424
+ c: this.#c,
425
+ driver: "mongodb",
426
+ io: Cfg.io,
427
+ action: "find",
428
+ params: params,
429
+ session: sessionStorage(),
430
+ rest: new useRest({
431
+ useHook: false,
432
+ tenant_id: this.#tenant_id,
433
+ }),
434
+ });
435
+ }
436
+
437
+ if (col?.hooks?.beforeFind && useHook) {
438
+ await col.hooks.beforeFind({
439
+ sharedData: sharedData,
440
+ c: this.#c,
441
+ driver: "mongodb",
442
+ action: "find",
443
+ io: Cfg.io,
444
+ params: params,
445
+ session: sessionStorage(),
446
+ rest: new useRest({
447
+ useHook: false,
448
+ tenant_id: this.#tenant_id,
449
+ }),
450
+ });
451
+ }
452
+
453
+ result.docs = await this.#tenant.database.db
454
+ ?.collection(collection)
455
+ .aggregate(formatData(buildPipeline(params, col)), {
456
+ allowDiskUse: true,
457
+ })
458
+ .toArray();
459
+
460
+ if (col?.hooks?.afterFind && useHook) {
461
+ await col.hooks.afterFind({
462
+ sharedData: sharedData,
463
+ c: this.#c,
464
+ io: Cfg.io,
465
+ driver: "mongodb",
466
+ action: "find",
467
+ params: params,
468
+ session: sessionStorage(),
469
+ result: result.docs,
470
+ rest: new useRest({
471
+ useHook: false,
472
+ tenant_id: this.#tenant_id,
473
+ }),
474
+ });
475
+ }
476
+
477
+ return resolve(toJson(result.docs));
478
+ } catch (err) {
479
+ return reject(err);
480
+ }
481
+ });
482
+ }
483
+ async findOne(
484
+ collection: string,
485
+ id: string,
486
+ params?: findOneParam,
487
+ options?: optionCb
488
+ ): Promise<object | null> {
489
+ return new Promise(async (resolve, reject) => {
490
+ try {
491
+ let sharedData = {};
492
+ let docs: Array<any> | any = [];
493
+ let useHook = options?.useHook ?? this.#useHook;
494
+
495
+ let col = getCollection(collection, this.#tenant_id);
496
+
497
+ if (col?.customApi?.findOne && !this.#customApi) {
498
+ let result = await col?.customApi?.findOne({
499
+ io: Cfg.io,
500
+ session: sessionStorage(),
501
+ id: id,
502
+ params: params,
503
+ rest: new useRest({
504
+ useHook: false,
505
+ tenant_id: this.#tenant_id,
506
+ customApi: true,
507
+ }),
508
+ });
509
+ return resolve(result);
510
+ }
511
+
512
+ if (col?.hooks?.beforeOperation && useHook) {
513
+ await col.hooks.beforeOperation({
514
+ sharedData: sharedData,
515
+ id: id,
516
+ io: Cfg.io,
517
+ c: this.#c,
518
+ driver: "mongodb",
519
+ action: "findOne",
520
+ params: params,
521
+ session: sessionStorage(),
522
+ rest: new useRest({
523
+ useHook: false,
524
+ tenant_id: this.#tenant_id,
525
+ }),
526
+ });
527
+ }
528
+
529
+ if (col?.hooks?.beforeFind && useHook) {
530
+ await col.hooks.beforeFind({
531
+ sharedData: sharedData,
532
+ c: this.#c,
533
+ driver: "mongodb",
534
+ io: Cfg.io,
535
+ action: "find",
536
+ params: params,
537
+ session: sessionStorage(),
538
+ rest: new useRest({
539
+ useHook: false,
540
+ tenant_id: this.#tenant_id,
541
+ }),
542
+ });
543
+ }
544
+
545
+ let params_: findParam = {};
546
+ if (typeof id === "string") {
547
+ params_ = {
548
+ ...params,
549
+ $match: {
550
+ _id: id,
551
+ },
552
+ $limit: 1,
553
+ };
554
+ }
555
+
556
+ docs = await this.#tenant.database.db
557
+ ?.collection(collection)
558
+ .aggregate(
559
+ formatData(
560
+ buildPipeline(params_, getCollection(collection, this.#tenant_id))
561
+ ),
562
+ {
563
+ allowDiskUse: true,
564
+ }
565
+ )
566
+ .toArray();
567
+
568
+ if (col?.hooks?.afterFind && useHook) {
569
+ await col.hooks.afterFind({
570
+ sharedData: sharedData,
571
+ c: this.#c,
572
+ io: Cfg.io,
573
+ driver: "mongodb",
574
+ action: "findOne",
575
+ params: params,
576
+ session: sessionStorage(),
577
+ result: docs,
578
+ rest: new useRest({
579
+ useHook: false,
580
+ tenant_id: this.#tenant_id,
581
+ }),
582
+ });
583
+ }
584
+
585
+ return resolve(docs?.length ? toJson(docs[0]) : null);
586
+ } catch (err) {
587
+ return reject(err);
588
+ }
589
+ });
590
+ }
591
+
592
+ async updateOne(
593
+ collection: string,
594
+ id: string,
595
+ update: updateParams,
596
+ options?: optionCb
597
+ ): Promise<object> {
598
+ return new Promise(async (resolve, reject) => {
599
+ try {
600
+ let result = {
601
+ doc: null,
602
+ };
603
+ let col = getCollection(collection, this.#tenant_id);
604
+ if (!col) return fn.error(`Collection ${collection} not found`, 404);
605
+
606
+ if (col?.customApi?.updateOne && !this.#customApi) {
607
+ let result = await col?.customApi?.updateOne({
608
+ io: Cfg.io,
609
+ session: sessionStorage(),
610
+ update: update,
611
+ id: id,
612
+ rest: new useRest({
613
+ useHook: false,
614
+ tenant_id: this.#tenant_id,
615
+ customApi: true,
616
+ }),
617
+ });
618
+ return resolve(result);
619
+ }
620
+
621
+ let sharedData = {};
622
+ let useHook = options?.useHook ?? this.#useHook;
623
+
624
+ //@ts-expect-error
625
+ update = omit(update, omitUpdate);
626
+
627
+ if (update?.$set) {
628
+ update.$set = deepSetId(col, update.$set);
629
+ update.$set = transformAllDate(update.$set);
630
+ update.$set = await hashPasswordAuto(update.$set, col);
631
+ // data = transformAllDate(data);
632
+ // data = deepSetId(col, data);
633
+ var { valid, output, error } = this.validator(
634
+ collection,
635
+ update.$set,
636
+ {
637
+ partial: true,
638
+ }
639
+ );
640
+
641
+ // update.$set = output;
642
+
643
+ //console.log(valid, error);
644
+
645
+ if (!valid) fn?.error(error, 400);
646
+ }
647
+
648
+ if (col?.hooks?.beforeOperation && useHook) {
649
+ await col.hooks.beforeOperation({
650
+ sharedData: sharedData,
651
+ id: id,
652
+ io: Cfg.io,
653
+ c: this.#c,
654
+ driver: "mongodb",
655
+ action: "updateOne",
656
+ update: update,
657
+ session: sessionStorage(),
658
+ rest: new useRest({
659
+ useHook: false,
660
+ tenant_id: this.#tenant_id,
661
+ }),
662
+ });
663
+ }
664
+
665
+ if (col?.hooks?.beforeUpdate && useHook) {
666
+ await col.hooks.beforeUpdate({
667
+ sharedData: sharedData,
668
+ c: this.#c,
669
+ id: id,
670
+ driver: "mongodb",
671
+ io: Cfg.io,
672
+ action: "updateOne",
673
+ update: update,
674
+ session: sessionStorage(),
675
+ rest: new useRest({
676
+ useHook: false,
677
+ tenant_id: this.#tenant_id,
678
+ }),
679
+ });
680
+ }
681
+
682
+ if (typeof id == "string") {
683
+ result.doc = await this.#tenant.database.db
684
+ ?.collection(collection)
685
+ .findOneAndUpdate(
686
+ {
687
+ _id: new ObjectId(id),
688
+ },
689
+ {
690
+ ...formatData(omit(update, omitUpdate)),
691
+ $currentDate: {
692
+ updatedAt: true,
693
+ },
694
+ },
695
+ {
696
+ returnDocument: "after",
697
+ session: this.#session ? this.#session : undefined,
698
+ }
699
+ );
700
+ }
701
+
702
+ if (col?.hooks?.afterUpdate && useHook) {
703
+ await col.hooks.afterUpdate({
704
+ sharedData: sharedData,
705
+ c: this.#c,
706
+ driver: "mongodb",
707
+ id: id,
708
+ io: Cfg.io,
709
+ action: "updateOne",
710
+ update: update,
711
+ session: sessionStorage(),
712
+ result: result.doc,
713
+ rest: new useRest({
714
+ useHook: false,
715
+ tenant_id: this.#tenant_id,
716
+ }),
717
+ });
718
+ }
719
+
720
+ return resolve(result.doc);
721
+ } catch (err) {
722
+ return reject(err);
723
+ }
724
+ });
725
+ }
726
+
727
+ async findOneAndUpdate(
728
+ collection: string,
729
+ filter: object,
730
+ update: updateParams,
731
+ options?: optionCb
732
+ ): Promise<object> {
733
+ return new Promise(async (resolve, reject) => {
734
+ try {
735
+ let result = {
736
+ doc: null,
737
+ };
738
+ let col = getCollection(collection, this.#tenant_id);
739
+ if (!col) return fn.error(`Collection ${collection} not found`, 404);
740
+
741
+ let sharedData = {};
742
+ let useHook = options?.useHook ?? this.#useHook;
743
+
744
+ //@ts-expect-error
745
+ update = omit(update, omitUpdate);
746
+
747
+ if (update.$set) {
748
+ update.$set = deepSetId(col, update.$set);
749
+ var { valid, output, error } = this.validator(
750
+ collection,
751
+ update.$set,
752
+ {
753
+ partial: true,
754
+ }
755
+ );
756
+ // update.$set = output;
757
+ if (!valid) fn.error(error, 400);
758
+ }
759
+
760
+ if (col?.hooks?.beforeOperation && useHook) {
761
+ await col.hooks.beforeOperation({
762
+ sharedData: sharedData,
763
+ filter: filter || {},
764
+ c: this.#c,
765
+ io: Cfg.io,
766
+ driver: "mongodb",
767
+ action: "findOneAndUpdate",
768
+ update: update,
769
+ session: sessionStorage(),
770
+ rest: new useRest({
771
+ useHook: false,
772
+ tenant_id: this.#tenant_id,
773
+ }),
774
+ });
775
+ }
776
+
777
+ if (col?.hooks?.beforeUpdate && useHook) {
778
+ await col.hooks.beforeUpdate({
779
+ sharedData: sharedData,
780
+ c: this.#c,
781
+ filter: filter || {},
782
+ driver: "mongodb",
783
+ io: Cfg.io,
784
+ action: "findOneAndUpdate",
785
+ update: update,
786
+ session: sessionStorage(),
787
+ rest: new useRest({
788
+ useHook: false,
789
+ tenant_id: this.#tenant_id,
790
+ }),
791
+ });
792
+ }
793
+
794
+ if (typeof id == "string") {
795
+ result.doc = await this.#tenant.database.db
796
+ ?.collection(collection)
797
+ .findOneAndUpdate(
798
+ {
799
+ ...(filter || {}),
800
+ },
801
+ {
802
+ ...formatData(omit(update, omitUpdate)),
803
+ $currentDate: {
804
+ updatedAt: true,
805
+ },
806
+ },
807
+ {
808
+ upsert: true,
809
+ returnDocument: "after",
810
+ session: this.#session ? this.#session : undefined,
811
+ }
812
+ );
813
+ }
814
+
815
+ if (col?.hooks?.afterUpdate && useHook) {
816
+ await col.hooks.afterUpdate({
817
+ sharedData: sharedData,
818
+ c: this.#c,
819
+ driver: "mongodb",
820
+ id: id,
821
+ action: "updateOne",
822
+ update: update,
823
+ session: sessionStorage(),
824
+ result: result.doc,
825
+ io: Cfg.io,
826
+ rest: new useRest({
827
+ useHook: false,
828
+ tenant_id: this.#tenant_id,
829
+ }),
830
+ });
831
+ }
832
+
833
+ return resolve(result.doc);
834
+ } catch (err) {
835
+ return reject(err);
836
+ }
837
+ });
838
+ }
839
+
840
+ async updateMany(
841
+ collection: string,
842
+ ids: Array<string>,
843
+ update: updateParams,
844
+ options?: optionCb
845
+ ): Promise<object> {
846
+ return new Promise(async (resolve, reject) => {
847
+ try {
848
+ let sharedData = {};
849
+ let result = {
850
+ docs: [],
851
+ };
852
+ let col = getCollection(collection, this.#tenant_id);
853
+ if (!col) return fn.error(`Collection ${collection} not found`, 404);
854
+
855
+ if (col?.customApi?.updateMany && !this.#customApi) {
856
+ let result = await col?.customApi?.updateMany({
857
+ io: Cfg.io,
858
+ session: sessionStorage(),
859
+ update: update,
860
+ ids: ids,
861
+ rest: new useRest({
862
+ useHook: false,
863
+ tenant_id: this.#tenant_id,
864
+ customApi: true,
865
+ }),
866
+ });
867
+ return resolve(result);
868
+ }
869
+
870
+ let useHook = options?.useHook ?? this.#useHook;
871
+
872
+ //@ts-expect-error
873
+ update = omit(update, omitUpdate);
874
+
875
+ if (update.$set) {
876
+ update.$set = deepSetId(col, update.$set);
877
+ update.$set = transformAllDate(update.$set);
878
+ update.$set = await hashPasswordAuto(update.$set, col);
879
+ var { valid, output, error } = this.validator(
880
+ collection,
881
+ update.$set,
882
+ {
883
+ partial: true,
884
+ }
885
+ );
886
+ // update.$set = output;
887
+
888
+ if (!valid) fn.error(error, 400);
889
+ }
890
+
891
+ if (Array.isArray(ids)) {
892
+ if (!ids?.length) throw new contextError("List of id required", 400);
893
+
894
+ if (col?.hooks?.beforeOperation && useHook) {
895
+ await col.hooks.beforeOperation({
896
+ sharedData: sharedData,
897
+ ids: ids,
898
+ c: this.#c,
899
+ driver: "mongodb",
900
+ io: Cfg.io,
901
+ action: "updateMany",
902
+ update: update,
903
+ session: sessionStorage(),
904
+ rest: new useRest({
905
+ useHook: false,
906
+ tenant_id: this.#tenant_id,
907
+ }),
908
+ });
909
+ }
910
+
911
+ if (col?.hooks?.beforeUpdate && useHook) {
912
+ await col.hooks.beforeUpdate({
913
+ sharedData: sharedData,
914
+ c: this.#c,
915
+ ids: ids,
916
+ driver: "mongodb",
917
+ io: Cfg.io,
918
+ action: "updateMany",
919
+ update: update,
920
+ session: sessionStorage(),
921
+ rest: new useRest({
922
+ useHook: false,
923
+ tenant_id: this.#tenant_id,
924
+ }),
925
+ });
926
+ }
927
+
928
+ await this.#tenant.database.db?.collection(collection).updateMany(
929
+ {
930
+ _id: {
931
+ $in: ids.map((id) => new ObjectId(id)),
932
+ },
933
+ },
934
+ {
935
+ ...formatData(omit(update, omitUpdate)),
936
+ $currentDate: {
937
+ updatedAt: true,
938
+ },
939
+ },
940
+ {
941
+ session: this.#session ? this.#session : undefined,
942
+ }
943
+ );
944
+
945
+ result.docs = await this.#tenant.database.db
946
+ .collection(collection)
947
+ .find(
948
+ {
949
+ _id: {
950
+ $in: ids.map((id) => new ObjectId(id)),
951
+ },
952
+ },
953
+ {
954
+ allowDiskUse: true,
955
+ }
956
+ )
957
+ .toArray();
958
+
959
+ if (col?.hooks?.afterUpdate && useHook) {
960
+ await col.hooks.afterUpdate({
961
+ sharedData: sharedData,
962
+ c: this.#c,
963
+ driver: "mongodb",
964
+ ids: ids,
965
+ action: "updateMany",
966
+ update: update,
967
+ session: sessionStorage(),
968
+ result: result.docs,
969
+ io: Cfg.io,
970
+ rest: new useRest({
971
+ useHook: false,
972
+ tenant_id: this.#tenant_id,
973
+ }),
974
+ });
975
+ }
976
+
977
+ return resolve(result.docs);
978
+ } else {
979
+ throw new contextError("List of id required", 400);
980
+ }
981
+ } catch (err) {
982
+ return reject(err);
983
+ }
984
+ });
985
+ }
986
+ async deleteOne(
987
+ collection: string,
988
+ id: string,
989
+ options?: optionCb
990
+ ): Promise<object> {
991
+ return new Promise(async (resolve, reject) => {
992
+ try {
993
+ if (!id) fn.error("Id is required", 400);
994
+ let useHook = options?.useHook ?? this.#useHook;
995
+
996
+ let col = getCollection(collection, this.#tenant_id);
997
+ let sharedData = {};
998
+
999
+ if (col?.customApi?.deleteOne && !this.#customApi) {
1000
+ let result = await col?.customApi?.deleteOne({
1001
+ io: Cfg.io,
1002
+ session: sessionStorage(),
1003
+ id: id,
1004
+ rest: new useRest({
1005
+ useHook: false,
1006
+ tenant_id: this.#tenant_id,
1007
+ customApi: true,
1008
+ }),
1009
+ });
1010
+ return resolve(result!);
1011
+ }
1012
+
1013
+ if (col?.hooks?.beforeOperation && useHook) {
1014
+ await col.hooks.beforeOperation({
1015
+ sharedData: sharedData,
1016
+ id: id,
1017
+ c: this.#c,
1018
+ driver: "mongodb",
1019
+ action: "deleteOne",
1020
+ session: sessionStorage(),
1021
+ rest: new useRest({
1022
+ useHook: false,
1023
+ tenant_id: this.#tenant_id,
1024
+ }),
1025
+ });
1026
+ }
1027
+
1028
+ if (col?.hooks?.beforeDelete && useHook) {
1029
+ await col.hooks.beforeDelete({
1030
+ sharedData: sharedData,
1031
+ id: id,
1032
+ c: this.#c,
1033
+ driver: "mongodb",
1034
+ io: Cfg.io,
1035
+ action: "deleteOne",
1036
+ session: sessionStorage(),
1037
+ rest: new useRest({
1038
+ useHook: false,
1039
+ tenant_id: this.#tenant_id,
1040
+ }),
1041
+ });
1042
+ }
1043
+
1044
+ let doc = await this.#tenant.database.db
1045
+ ?.collection(collection)
1046
+ .findOneAndDelete(
1047
+ {
1048
+ _id: new ObjectId(id),
1049
+ },
1050
+ {
1051
+ session: this.#session ? this.#session : undefined,
1052
+ }
1053
+ );
1054
+
1055
+ if (col?.hooks?.afterDelete && useHook) {
1056
+ await col.hooks.afterDelete({
1057
+ sharedData: sharedData,
1058
+ id: id,
1059
+ c: this.#c,
1060
+ driver: "mongodb",
1061
+ action: "deleteOne",
1062
+ result: doc,
1063
+ io: Cfg.io,
1064
+ session: sessionStorage(),
1065
+ rest: new useRest({
1066
+ useHook: false,
1067
+ tenant_id: this.#tenant_id,
1068
+ }),
1069
+ });
1070
+ }
1071
+
1072
+ return resolve(doc);
1073
+ } catch (err) {
1074
+ return resolve(err);
1075
+ }
1076
+ });
1077
+ }
1078
+ async deleteMany(collection: string, ids: Array<string>, options?: optionCb) {
1079
+ return new Promise(async (resolve, reject) => {
1080
+ try {
1081
+ let useHook = options?.useHook ?? this.#useHook;
1082
+
1083
+ let sharedData = {};
1084
+ let col = getCollection(collection, this.#tenant_id);
1085
+
1086
+ if (col?.customApi?.deleteMany && !this.#customApi) {
1087
+ let result = await col?.customApi?.deleteMany({
1088
+ io: Cfg.io,
1089
+ session: sessionStorage(),
1090
+ ids: ids,
1091
+ rest: new useRest({
1092
+ useHook: false,
1093
+ tenant_id: this.#tenant_id,
1094
+ customApi: true,
1095
+ }),
1096
+ });
1097
+ return resolve(result!);
1098
+ }
1099
+
1100
+ let deletedIds: any = [];
1101
+
1102
+ if (!ids) fn.error("List of id required", 400);
1103
+
1104
+ if (col?.hooks?.beforeOperation && useHook) {
1105
+ await col.hooks.beforeOperation({
1106
+ sharedData: sharedData,
1107
+ ids: ids,
1108
+ c: this.#c,
1109
+ driver: "mongodb",
1110
+ io: Cfg.io,
1111
+ action: "deleteMany",
1112
+ session: sessionStorage(),
1113
+ rest: new useRest({
1114
+ useHook: false,
1115
+ tenant_id: this.#tenant_id,
1116
+ }),
1117
+ });
1118
+ }
1119
+
1120
+ if (col?.hooks?.beforeDelete && useHook) {
1121
+ await col.hooks.beforeDelete({
1122
+ sharedData: sharedData,
1123
+ ids: ids,
1124
+ c: this.#c,
1125
+ driver: "mongodb",
1126
+ io: Cfg.io,
1127
+ action: "deleteMany",
1128
+ session: sessionStorage(),
1129
+ rest: new useRest({
1130
+ useHook: false,
1131
+ tenant_id: this.#tenant_id,
1132
+ }),
1133
+ });
1134
+ }
1135
+
1136
+ if (Array.isArray(ids)) {
1137
+ await this.#tenant.database.db?.collection(collection).deleteMany(
1138
+ {
1139
+ _id: { $in: formatData(ids) },
1140
+ },
1141
+ {
1142
+ session: this.#session ? this.#session : undefined,
1143
+ }
1144
+ );
1145
+ }
1146
+
1147
+ if (col?.hooks?.afterDelete && useHook) {
1148
+ await col.hooks.afterDelete({
1149
+ sharedData: sharedData,
1150
+ ids: ids,
1151
+ c: this.#c,
1152
+ driver: "mongodb",
1153
+ io: Cfg.io,
1154
+ action: "deleteMany",
1155
+ result: deletedIds,
1156
+ session: sessionStorage(),
1157
+ rest: new useRest({
1158
+ useHook: false,
1159
+ tenant_id: this.#tenant_id,
1160
+ }),
1161
+ });
1162
+ }
1163
+
1164
+ return resolve(deletedIds);
1165
+ } catch (err) {
1166
+ return reject(err);
1167
+ }
1168
+ });
1169
+ }
1170
+
1171
+ async estimateDocumentCount(collection: string) {
1172
+ return await this.#tenant.database.db
1173
+ ?.collection(collection)
1174
+ .estimatedDocumentCount();
1175
+ }
1176
+ async dropCollection(Collection: string) {
1177
+ return await this.#tenant.database.db?.collection(Collection).drop();
1178
+ }
1179
+
1180
+ async dropIndexes(Collection: string) {
1181
+ return await this.#tenant.database.db?.collection(Collection).dropIndexes();
1182
+ }
1183
+
1184
+ async dropIndex(Collection: string, indexName: string) {
1185
+ return await this.#tenant.database.db
1186
+ ?.collection(Collection)
1187
+ .dropIndex(indexName);
1188
+ }
1189
+
1190
+ startTransaction() {
1191
+ if (!this.#session) {
1192
+ this.#session = this.#tenant.database.client?.startSession();
1193
+ this.#session?.startTransaction();
1194
+ }
1195
+ }
1196
+ async commitTransaction() {
1197
+ return new Promise(async (resolve, reject) => {
1198
+ if (this.#session) {
1199
+ await this.#session
1200
+ ?.commitTransaction()
1201
+ .then((e) => {
1202
+ this.#session?.endSession();
1203
+ this.#session = null;
1204
+ resolve(true);
1205
+ })
1206
+ .catch((err) => {
1207
+ reject(err);
1208
+ });
1209
+ }
1210
+ });
1211
+ }
1212
+ }
1213
+
1214
+ export { useRest };