bonsaif 1.10.39 → 1.10.40

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.
@@ -1,988 +0,0 @@
1
- /**
2
- * ::: B[]NSAIF() ::: => 2024
3
- * Hookup para Mongoose (MongoDB ORM)
4
- */
5
-
6
- 'use strict';
7
-
8
- const utl = require('../utl');
9
- let debug = false;
10
- let tag = ` ::: B[]NSAIF() ::: => mongoose.js `;
11
-
12
- // Cache de modelos dinámicos por base de datos y colección
13
- const modelCache = new Map();
14
-
15
- /**
16
- * Parsear schema dinámico recibido del cliente
17
- * Convierte definición simple a Schema de Mongoose
18
- */
19
- const parseSchema = (schemaDefinition) => {
20
- const mongoose = require('mongoose');
21
- const parsedSchema = {};
22
-
23
- for (const [field, def] of Object.entries(schemaDefinition)) {
24
- if (typeof def === 'string') {
25
- // Formato simple: { "name": "String" }
26
- parsedSchema[field] = { type: mongoose.Schema.Types[def] || String };
27
- } else if (typeof def === 'object') {
28
- // Formato completo: { "name": { "type": "String", "required": true } }
29
- const fieldDef = { ...def };
30
-
31
- // Convertir string del type a tipo real de Mongoose
32
- if (def.type && typeof def.type === 'string') {
33
- fieldDef.type = mongoose.Schema.Types[def.type] || String;
34
- }
35
-
36
- // Convertir enum si existe
37
- if (def.enum && Array.isArray(def.enum)) {
38
- fieldDef.enum = def.enum;
39
- }
40
-
41
- // Convertir default
42
- if (def.default !== undefined) {
43
- fieldDef.default = def.default;
44
- }
45
-
46
- // Validaciones
47
- if (def.required !== undefined) fieldDef.required = def.required;
48
- if (def.unique !== undefined) fieldDef.unique = def.unique;
49
- if (def.min !== undefined) fieldDef.min = def.min;
50
- if (def.max !== undefined) fieldDef.max = def.max;
51
- if (def.minlength !== undefined) fieldDef.minlength = def.minlength;
52
- if (def.maxlength !== undefined) fieldDef.maxlength = def.maxlength;
53
- if (def.trim !== undefined) fieldDef.trim = def.trim;
54
- if (def.lowercase !== undefined) fieldDef.lowercase = def.lowercase;
55
- if (def.uppercase !== undefined) fieldDef.uppercase = def.uppercase;
56
- if (def.match !== undefined) fieldDef.match = new RegExp(def.match);
57
-
58
- // Referencias (populate)
59
- if (def.ref) {
60
- fieldDef.ref = def.ref;
61
- fieldDef.type = mongoose.Schema.Types.ObjectId;
62
- }
63
-
64
- parsedSchema[field] = fieldDef;
65
- }
66
- }
67
-
68
- return parsedSchema;
69
- };
70
-
71
- /**
72
- * Conectar a MongoDB usando Mongoose
73
- */
74
- const connect = async (options) => {
75
- const mongoose = require('mongoose');
76
- const { uri = '', poolSize = 10, debug: debugMode = false } = options.endpoint;
77
-
78
- try {
79
- if (mongoose.connection.readyState === 1) {
80
- debugMode ? utl.log(`${tag} [Mongoose] ya conectado`) : '';
81
- return mongoose.connection;
82
- }
83
-
84
- await mongoose.connect(uri, {
85
- maxPoolSize: poolSize,
86
- minPoolSize: 2,
87
- serverSelectionTimeoutMS: 15000,
88
- socketTimeoutMS: 45000,
89
- connectTimeoutMS: 10000
90
- });
91
-
92
- debugMode ? utl.log(`${tag} [Mongoose] conectado a ${uri}`) : '';
93
- return mongoose.connection;
94
- } catch (e) {
95
- utl.log(`${tag} [Mongoose] error de conexión:`, e);
96
- throw e;
97
- }
98
- };
99
-
100
- /**
101
- * Obtener o crear modelo dinámico para una colección
102
- */
103
- const getModel = (db, collection, schemaDefinition = null) => {
104
- const mongoose = require('mongoose');
105
- const cacheKey = schemaDefinition
106
- ? `${db}.${collection}.custom.${JSON.stringify(schemaDefinition)}`
107
- : `${db}.${collection}.generic`;
108
-
109
- if (modelCache.has(cacheKey)) {
110
- return modelCache.get(cacheKey);
111
- }
112
-
113
- let schema;
114
-
115
- if (schemaDefinition) {
116
- // Schema personalizado con validaciones
117
- const parsedSchema = parseSchema(schemaDefinition);
118
- schema = new mongoose.Schema(parsedSchema, {
119
- strict: true,
120
- timestamps: true,
121
- collection: collection
122
- });
123
- } else {
124
- // Schema genérico (acepta cualquier campo)
125
- schema = new mongoose.Schema({}, {
126
- strict: false,
127
- timestamps: true,
128
- collection: collection
129
- });
130
- }
131
-
132
- // Crear modelo en la conexión específica de la BD
133
- const conn = mongoose.connection.useDb(db);
134
-
135
- // Nombre único para evitar conflictos
136
- const modelName = schemaDefinition
137
- ? `${collection}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
138
- : collection;
139
-
140
- const Model = conn.model(modelName, schema);
141
-
142
- modelCache.set(cacheKey, Model);
143
- return Model;
144
- };
145
-
146
- /**
147
- * FIND - Búsqueda dinámica
148
- */
149
- const find = async (options, db, collection, query) => {
150
- const start = Date.now();
151
-
152
- try {
153
- await connect(options);
154
-
155
- const { filter = {}, select = '', sort = {}, limit = 0, skip = 0, populate = '', schema = null } = query;
156
-
157
- const Model = getModel(db, collection, schema);
158
- let mongoQuery = Model.find(filter);
159
-
160
- if (select) mongoQuery = mongoQuery.select(select);
161
- if (Object.keys(sort).length > 0) mongoQuery = mongoQuery.sort(sort);
162
- if (limit > 0) mongoQuery = mongoQuery.limit(limit);
163
- if (skip > 0) mongoQuery = mongoQuery.skip(skip);
164
- if (populate) mongoQuery = mongoQuery.populate(populate);
165
-
166
- const data = await mongoQuery.lean().exec();
167
-
168
- const end = Date.now();
169
- const time = end - start;
170
-
171
- return {
172
- result: {
173
- dml: 'find',
174
- collection,
175
- db,
176
- time: utl.milisegundosASegundos(time),
177
- code: 200,
178
- error: 0
179
- },
180
- data
181
- };
182
- } catch (e) {
183
- const end = Date.now();
184
- const time = end - start;
185
- utl.log(`${tag} find error:`, e);
186
- return {
187
- result: {
188
- dml: 'find',
189
- time: utl.milisegundosASegundos(time),
190
- code: 500,
191
- error: 1,
192
- msg: e.message
193
- },
194
- data: []
195
- };
196
- }
197
- };
198
-
199
- /**
200
- * FINDONE - Buscar un solo documento
201
- */
202
- const findOne = async (options, db, collection, query) => {
203
- const start = Date.now();
204
-
205
- try {
206
- await connect(options);
207
-
208
- const { filter = {}, select = '', populate = '', schema = null } = query;
209
-
210
- const Model = getModel(db, collection, schema);
211
- let mongoQuery = Model.findOne(filter);
212
-
213
- if (select) mongoQuery = mongoQuery.select(select);
214
- if (populate) mongoQuery = mongoQuery.populate(populate);
215
-
216
- const data = await mongoQuery.lean().exec();
217
-
218
- const end = Date.now();
219
- const time = end - start;
220
-
221
- return {
222
- result: {
223
- dml: 'findOne',
224
- collection,
225
- db,
226
- time: utl.milisegundosASegundos(time),
227
- code: 200,
228
- error: 0
229
- },
230
- data: data ? [data] : []
231
- };
232
- } catch (e) {
233
- const end = Date.now();
234
- const time = end - start;
235
- utl.log(`${tag} findOne error:`, e);
236
- return {
237
- result: {
238
- dml: 'findOne',
239
- time: utl.milisegundosASegundos(time),
240
- code: 500,
241
- error: 1,
242
- msg: e.message
243
- },
244
- data: []
245
- };
246
- }
247
- };
248
-
249
- /**
250
- * COUNT - Contar documentos
251
- */
252
- const count = async (options, db, collection, query) => {
253
- const start = Date.now();
254
-
255
- try {
256
- await connect(options);
257
-
258
- const { filter = {}, schema = null } = query;
259
-
260
- const Model = getModel(db, collection, schema);
261
- const total = await Model.countDocuments(filter);
262
-
263
- const end = Date.now();
264
- const time = end - start;
265
-
266
- return {
267
- result: {
268
- dml: 'count',
269
- collection,
270
- db,
271
- time: utl.milisegundosASegundos(time),
272
- code: 200,
273
- error: 0
274
- },
275
- data: { count: total }
276
- };
277
- } catch (e) {
278
- const end = Date.now();
279
- const time = end - start;
280
- utl.log(`${tag} count error:`, e);
281
- return {
282
- result: {
283
- dml: 'count',
284
- time: utl.milisegundosASegundos(time),
285
- code: 500,
286
- error: 1,
287
- msg: e.message
288
- },
289
- data: { count: 0 }
290
- };
291
- }
292
- };
293
-
294
- /**
295
- * INSERT - Crear documento
296
- */
297
- const insert = async (options, db, collection, query) => {
298
- const start = Date.now();
299
-
300
- try {
301
- await connect(options);
302
-
303
- const { document = {}, schema = null } = query;
304
-
305
- const Model = getModel(db, collection, schema);
306
- const doc = new Model(document);
307
- const result = await doc.save();
308
-
309
- const end = Date.now();
310
- const time = end - start;
311
-
312
- return {
313
- result: {
314
- dml: 'insert',
315
- collection,
316
- db,
317
- insertId: result._id,
318
- time: utl.milisegundosASegundos(time),
319
- code: 200,
320
- error: 0
321
- },
322
- data: [result.toObject()]
323
- };
324
- } catch (e) {
325
- const end = Date.now();
326
- const time = end - start;
327
- utl.log(`${tag} insert error:`, e);
328
- return {
329
- result: {
330
- dml: 'insert',
331
- time: utl.milisegundosASegundos(time),
332
- code: 500,
333
- error: 1,
334
- msg: e.message,
335
- validationErrors: e.errors ? Object.keys(e.errors).map(key => ({
336
- field: key,
337
- message: e.errors[key].message
338
- })) : undefined
339
- },
340
- data: []
341
- };
342
- }
343
- };
344
-
345
- /**
346
- * INSERTMANY - Crear múltiples documentos
347
- */
348
- const insertMany = async (options, db, collection, query) => {
349
- const start = Date.now();
350
-
351
- try {
352
- await connect(options);
353
-
354
- const { documents = [], schema = null } = query;
355
-
356
- const Model = getModel(db, collection, schema);
357
- const results = await Model.insertMany(documents);
358
-
359
- const end = Date.now();
360
- const time = end - start;
361
-
362
- return {
363
- result: {
364
- dml: 'insertMany',
365
- collection,
366
- db,
367
- insertedCount: results.length,
368
- time: utl.milisegundosASegundos(time),
369
- code: 200,
370
- error: 0
371
- },
372
- data: results.map(doc => doc.toObject())
373
- };
374
- } catch (e) {
375
- const end = Date.now();
376
- const time = end - start;
377
- utl.log(`${tag} insertMany error:`, e);
378
- return {
379
- result: {
380
- dml: 'insertMany',
381
- time: utl.milisegundosASegundos(time),
382
- code: 500,
383
- error: 1,
384
- msg: e.message
385
- },
386
- data: []
387
- };
388
- }
389
- };
390
-
391
- /**
392
- * UPDATE - Actualizar documento(s)
393
- */
394
- const update = async (options, db, collection, query) => {
395
- const start = Date.now();
396
-
397
- try {
398
- await connect(options);
399
-
400
- const { filter = {}, update: updateDoc = {}, options: updateOpts = {}, schema = null } = query;
401
-
402
- const Model = getModel(db, collection, schema);
403
- const result = await Model.updateOne(filter, updateDoc, updateOpts);
404
-
405
- const end = Date.now();
406
- const time = end - start;
407
-
408
- return {
409
- result: {
410
- dml: 'update',
411
- collection,
412
- db,
413
- matchedCount: result.matchedCount,
414
- modifiedCount: result.modifiedCount,
415
- time: utl.milisegundosASegundos(time),
416
- code: 200,
417
- error: 0
418
- },
419
- data: {
420
- matchedCount: result.matchedCount,
421
- modifiedCount: result.modifiedCount
422
- }
423
- };
424
- } catch (e) {
425
- const end = Date.now();
426
- const time = end - start;
427
- utl.log(`${tag} update error:`, e);
428
- return {
429
- result: {
430
- dml: 'update',
431
- time: utl.milisegundosASegundos(time),
432
- code: 500,
433
- error: 1,
434
- msg: e.message
435
- },
436
- data: {}
437
- };
438
- }
439
- };
440
-
441
- /**
442
- * UPDATEMANY - Actualizar múltiples documentos
443
- */
444
- const updateMany = async (options, db, collection, query) => {
445
- const start = Date.now();
446
-
447
- try {
448
- await connect(options);
449
-
450
- const { filter = {}, update: updateDoc = {}, options: updateOpts = {}, schema = null } = query;
451
-
452
- const Model = getModel(db, collection, schema);
453
- const result = await Model.updateMany(filter, updateDoc, updateOpts);
454
-
455
- const end = Date.now();
456
- const time = end - start;
457
-
458
- return {
459
- result: {
460
- dml: 'updateMany',
461
- collection,
462
- db,
463
- matchedCount: result.matchedCount,
464
- modifiedCount: result.modifiedCount,
465
- time: utl.milisegundosASegundos(time),
466
- code: 200,
467
- error: 0
468
- },
469
- data: {
470
- matchedCount: result.matchedCount,
471
- modifiedCount: result.modifiedCount
472
- }
473
- };
474
- } catch (e) {
475
- const end = Date.now();
476
- const time = end - start;
477
- utl.log(`${tag} updateMany error:`, e);
478
- return {
479
- result: {
480
- dml: 'updateMany',
481
- time: utl.milisegundosASegundos(time),
482
- code: 500,
483
- error: 1,
484
- msg: e.message
485
- },
486
- data: {}
487
- };
488
- }
489
- };
490
-
491
- /**
492
- * UPSERT - Actualizar o insertar
493
- */
494
- const upsert = async (options, db, collection, query) => {
495
- const start = Date.now();
496
-
497
- try {
498
- await connect(options);
499
-
500
- const { filter = {}, document = {}, schema = null } = query;
501
-
502
- const Model = getModel(db, collection, schema);
503
-
504
- // Buscar documento existente
505
- const existing = await Model.findOne(filter);
506
-
507
- let result, operation;
508
-
509
- if (existing) {
510
- // Actualizar
511
- Object.assign(existing, document);
512
- result = await existing.save();
513
- operation = 'update';
514
- } else {
515
- // Insertar
516
- const doc = new Model({ ...filter, ...document });
517
- result = await doc.save();
518
- operation = 'insert';
519
- }
520
-
521
- const end = Date.now();
522
- const time = end - start;
523
-
524
- return {
525
- result: {
526
- dml: 'upsert',
527
- operation,
528
- collection,
529
- db,
530
- time: utl.milisegundosASegundos(time),
531
- code: 200,
532
- error: 0
533
- },
534
- data: [result.toObject()]
535
- };
536
- } catch (e) {
537
- const end = Date.now();
538
- const time = end - start;
539
- utl.log(`${tag} upsert error:`, e);
540
- return {
541
- result: {
542
- dml: 'upsert',
543
- time: utl.milisegundosASegundos(time),
544
- code: 500,
545
- error: 1,
546
- msg: e.message
547
- },
548
- data: []
549
- };
550
- }
551
- };
552
-
553
- /**
554
- * DELETE - Eliminar documento(s)
555
- */
556
- const deleteOne = async (options, db, collection, query) => {
557
- const start = Date.now();
558
-
559
- try {
560
- await connect(options);
561
-
562
- const { filter = {}, schema = null } = query;
563
-
564
- const Model = getModel(db, collection, schema);
565
- const result = await Model.deleteOne(filter);
566
-
567
- const end = Date.now();
568
- const time = end - start;
569
-
570
- return {
571
- result: {
572
- dml: 'delete',
573
- collection,
574
- db,
575
- deletedCount: result.deletedCount,
576
- time: utl.milisegundosASegundos(time),
577
- code: 200,
578
- error: 0
579
- },
580
- data: { deletedCount: result.deletedCount }
581
- };
582
- } catch (e) {
583
- const end = Date.now();
584
- const time = end - start;
585
- utl.log(`${tag} delete error:`, e);
586
- return {
587
- result: {
588
- dml: 'delete',
589
- time: utl.milisegundosASegundos(time),
590
- code: 500,
591
- error: 1,
592
- msg: e.message
593
- },
594
- data: { deletedCount: 0 }
595
- };
596
- }
597
- };
598
-
599
- /**
600
- * DELETEMANY - Eliminar múltiples documentos
601
- */
602
- const deleteMany = async (options, db, collection, query) => {
603
- const start = Date.now();
604
-
605
- try {
606
- await connect(options);
607
-
608
- const { filter = {}, schema = null } = query;
609
-
610
- const Model = getModel(db, collection, schema);
611
- const result = await Model.deleteMany(filter);
612
-
613
- const end = Date.now();
614
- const time = end - start;
615
-
616
- return {
617
- result: {
618
- dml: 'deleteMany',
619
- collection,
620
- db,
621
- deletedCount: result.deletedCount,
622
- time: utl.milisegundosASegundos(time),
623
- code: 200,
624
- error: 0
625
- },
626
- data: { deletedCount: result.deletedCount }
627
- };
628
- } catch (e) {
629
- const end = Date.now();
630
- const time = end - start;
631
- utl.log(`${tag} deleteMany error:`, e);
632
- return {
633
- result: {
634
- dml: 'deleteMany',
635
- time: utl.milisegundosASegundos(time),
636
- code: 500,
637
- error: 1,
638
- msg: e.message
639
- },
640
- data: { deletedCount: 0 }
641
- };
642
- }
643
- };
644
-
645
- /**
646
- * AGGREGATE - Pipeline de agregación
647
- */
648
- const aggregate = async (options, db, collection, query) => {
649
- const start = Date.now();
650
-
651
- try {
652
- await connect(options);
653
-
654
- const { pipeline = [], schema = null } = query;
655
-
656
- const Model = getModel(db, collection, schema);
657
- const data = await Model.aggregate(pipeline);
658
-
659
- const end = Date.now();
660
- const time = end - start;
661
-
662
- return {
663
- result: {
664
- dml: 'aggregate',
665
- collection,
666
- db,
667
- time: utl.milisegundosASegundos(time),
668
- code: 200,
669
- error: 0
670
- },
671
- data
672
- };
673
- } catch (e) {
674
- const end = Date.now();
675
- const time = end - start;
676
- utl.log(`${tag} aggregate error:`, e);
677
- return {
678
- result: {
679
- dml: 'aggregate',
680
- time: utl.milisegundosASegundos(time),
681
- code: 500,
682
- error: 1,
683
- msg: e.message
684
- },
685
- data: []
686
- };
687
- }
688
- };
689
-
690
- /**
691
- * DISTINCT - Valores únicos
692
- */
693
- const distinct = async (options, db, collection, query) => {
694
- const start = Date.now();
695
-
696
- try {
697
- await connect(options);
698
-
699
- const { field = '', filter = {}, schema = null } = query;
700
-
701
- const Model = getModel(db, collection, schema);
702
- const data = await Model.distinct(field, filter);
703
-
704
- const end = Date.now();
705
- const time = end - start;
706
-
707
- return {
708
- result: {
709
- dml: 'distinct',
710
- collection,
711
- db,
712
- time: utl.milisegundosASegundos(time),
713
- code: 200,
714
- error: 0
715
- },
716
- data
717
- };
718
- } catch (e) {
719
- const end = Date.now();
720
- const time = end - start;
721
- utl.log(`${tag} distinct error:`, e);
722
- return {
723
- result: {
724
- dml: 'distinct',
725
- time: utl.milisegundosASegundos(time),
726
- code: 500,
727
- error: 1,
728
- msg: e.message
729
- },
730
- data: []
731
- };
732
- }
733
- };
734
-
735
- /**
736
- * DBS - Listar todas las bases de datos
737
- */
738
- const dbs = async (options) => {
739
- const start = Date.now();
740
-
741
- try {
742
- const mongoose = require('mongoose');
743
- await connect(options);
744
-
745
- const adminDb = mongoose.connection.db.admin();
746
- const result = await adminDb.listDatabases();
747
-
748
- const end = Date.now();
749
- const time = end - start;
750
-
751
- return {
752
- result: {
753
- dml: 'dbs',
754
- headers: 'name|sizeOnDisk|empty',
755
- time: utl.milisegundosASegundos(time),
756
- code: 200,
757
- error: 0
758
- },
759
- results: { totalSize: result.totalSize || 0 },
760
- data: result.databases || []
761
- };
762
- } catch (e) {
763
- const end = Date.now();
764
- const time = end - start;
765
- utl.log(`${tag} dbs error:`, e);
766
- return {
767
- result: {
768
- dml: 'dbs',
769
- time: utl.milisegundosASegundos(time),
770
- code: 500,
771
- error: 1,
772
- msg: e.message
773
- },
774
- data: []
775
- };
776
- }
777
- };
778
-
779
- /**
780
- * COLLECTIONS - Listar todas las colecciones de una base de datos
781
- */
782
- const collections = async (options, db) => {
783
- const start = Date.now();
784
-
785
- try {
786
- const mongoose = require('mongoose');
787
- await connect(options);
788
-
789
- const dbConn = mongoose.connection.useDb(db);
790
- const colls = await dbConn.db.listCollections().toArray();
791
-
792
- const end = Date.now();
793
- const time = end - start;
794
-
795
- return {
796
- result: {
797
- dml: 'collections',
798
- headers: 'name|type',
799
- db,
800
- time: utl.milisegundosASegundos(time),
801
- code: 200,
802
- error: 0
803
- },
804
- results: colls,
805
- data: colls
806
- };
807
- } catch (e) {
808
- const end = Date.now();
809
- const time = end - start;
810
- utl.log(`${tag} collections error:`, e);
811
- return {
812
- result: {
813
- dml: 'collections',
814
- time: utl.milisegundosASegundos(time),
815
- code: 500,
816
- error: 1,
817
- msg: e.message
818
- },
819
- data: []
820
- };
821
- }
822
- };
823
-
824
- /**
825
- * DROP - Eliminar una colección completa
826
- */
827
- const drop = async (options, db, collection) => {
828
- const start = Date.now();
829
-
830
- try {
831
- const mongoose = require('mongoose');
832
- await connect(options);
833
-
834
- const dbConn = mongoose.connection.useDb(db);
835
- const result = await dbConn.db.dropCollection(collection);
836
-
837
- const end = Date.now();
838
- const time = end - start;
839
-
840
- return {
841
- result: {
842
- dml: 'drop',
843
- collection,
844
- db,
845
- time: utl.milisegundosASegundos(time),
846
- code: 200,
847
- error: 0
848
- },
849
- results: result,
850
- data: { drop: result }
851
- };
852
- } catch (e) {
853
- const end = Date.now();
854
- const time = end - start;
855
- utl.log(`${tag} drop error:`, e);
856
- return {
857
- result: {
858
- dml: 'drop',
859
- time: utl.milisegundosASegundos(time),
860
- code: 500,
861
- error: 1,
862
- msg: e.message
863
- },
864
- data: { drop: false }
865
- };
866
- }
867
- };
868
-
869
- /**
870
- * API - Router principal para todas las operaciones
871
- */
872
- const api = async (options, db, body) => {
873
- let { dml = '', collection = '' } = body;
874
-
875
- // Si dml es 'api', buscar el DML real en el body
876
- if (dml === 'api' || !dml) {
877
- const possibleDmls = ['find', 'findOne', 'insert', 'insertMany', 'update', 'updateMany',
878
- 'delete', 'deleteMany', 'upsert', 'count', 'aggregate', 'distinct',
879
- 'dbs', 'collections', 'drop'];
880
- for (const possibleDml of possibleDmls) {
881
- if (body[possibleDml] !== undefined) {
882
- dml = possibleDml;
883
- // En formato MongoDB, la colección viene en body.[dml]
884
- if (typeof body[possibleDml] === 'string') {
885
- collection = body[possibleDml];
886
- }
887
- break;
888
- }
889
- }
890
- }
891
-
892
- // Compatibilidad con formato MongoDB: collection puede venir en json.[dml]
893
- if (!collection && dml && dml !== 'api') {
894
- collection = body[dml] || '';
895
- }
896
-
897
- // Si aún no hay collection pero hay document/documents, usar dml por defecto
898
- if (!collection && body.document) {
899
- dml = dml || 'insert';
900
- }
901
-
902
- // Validar que collection tenga un valor (excepto para dbs y collections que no lo necesitan)
903
- const requiresCollection = !['dbs', 'collections'].includes(dml);
904
-
905
- if (requiresCollection && (!collection || collection === '')) {
906
- const errorMsg = collection === ''
907
- ? 'La "collection" está vacía. Asegúrate de que la variable tenga un valor válido.'
908
- : 'Se requiere especificar "collection" en body.collection o body.[dml]';
909
-
910
- return {
911
- result: {
912
- dml: dml || 'unknown',
913
- time: 0,
914
- code: 400,
915
- error: 1,
916
- msg: errorMsg,
917
- debug: {
918
- receivedDml: body.dml,
919
- detectedDml: dml,
920
- collectionValue: collection,
921
- collectionIsEmpty: collection === '',
922
- bodyKeys: Object.keys(body)
923
- }
924
- },
925
- data: []
926
- };
927
- }
928
-
929
- let r;
930
-
931
- switch (dml) {
932
- case 'find': r = await find(options, db, collection, body); break;
933
- case 'findOne': r = await findOne(options, db, collection, body); break;
934
- case 'count': r = await count(options, db, collection, body); break;
935
- case 'insert': r = await insert(options, db, collection, body); break;
936
- case 'insertMany': r = await insertMany(options, db, collection, body); break;
937
- case 'update': r = await update(options, db, collection, body); break;
938
- case 'updateMany': r = await updateMany(options, db, collection, body); break;
939
- case 'upsert': r = await upsert(options, db, collection, body); break;
940
- case 'delete': r = await deleteOne(options, db, collection, body); break;
941
- case 'deleteMany': r = await deleteMany(options, db, collection, body); break;
942
- case 'aggregate': r = await aggregate(options, db, collection, body); break;
943
- case 'distinct': r = await distinct(options, db, collection, body); break;
944
- case 'dbs': r = await dbs(options); break;
945
- case 'collections': r = await collections(options, db); break;
946
- case 'drop': r = await drop(options, db, collection); break;
947
- default:
948
- r = {
949
- result: {
950
- dml: dml || 'unknown',
951
- time: 0,
952
- code: 400,
953
- error: 1,
954
- msg: `Operación "${dml}" no soportada`
955
- },
956
- supportedOperations: [
957
- 'find', 'findOne', 'count', 'insert', 'insertMany',
958
- 'update', 'updateMany', 'upsert', 'delete', 'deleteMany',
959
- 'aggregate', 'distinct', 'dbs', 'collections', 'drop'
960
- ]
961
- };
962
- }
963
-
964
- return new Promise((resolve) => {
965
- resolve(r);
966
- });
967
- };
968
-
969
- module.exports = {
970
- api,
971
- find,
972
- findOne,
973
- count,
974
- insert,
975
- insertMany,
976
- update,
977
- updateMany,
978
- upsert,
979
- deleteOne,
980
- deleteMany,
981
- aggregate,
982
- distinct,
983
- dbs,
984
- collections,
985
- drop,
986
- connect,
987
- getModel
988
- };