bonsaif 1.10.34 → 1.10.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,6 +92,139 @@ const localMariaDB= {
92
92
  runMongo();
93
93
 
94
94
 
95
+ /**
96
+ * Execute Mongoose (MongoDB ORM with Schema validation)
97
+ * https://mongoosejs.com/docs/guide.html
98
+ **/
99
+ const endpointMongoose= {
100
+ uri: '',
101
+ user: '',
102
+ password: '',
103
+ client:'mongoose'
104
+ };
105
+
106
+ const localMongoose= {
107
+ uri:'mongodb://localhost:27017',
108
+ poolSize:8,
109
+ local:true,
110
+ debug:false,
111
+ client:'mongoose'
112
+ };
113
+
114
+ // Schema definition (opcional - también acepta documentos sin schema)
115
+ const userSchema = {
116
+ name: { type: 'String', required: true, minlength: 3 },
117
+ email: { type: 'String', required: true, unique: true, lowercase: true },
118
+ age: { type: 'Number', min: 18, max: 100 },
119
+ status: { type: 'String', enum: ['active', 'inactive', 'pending'], default: 'active' }
120
+ };
121
+
122
+ const runMongoose = async()=>{
123
+
124
+ // INSERT con schema y validaciones
125
+ let insert = await bonsaif.query({
126
+ endpoint:localMongoose,
127
+ options:{db:'mydb', sys:''},
128
+ query:{
129
+ dml: 'insert',
130
+ collection: 'users',
131
+ schema: userSchema,
132
+ document: { name: 'John Doe', email: 'john@example.com', age: 30 }
133
+ },
134
+ tag
135
+ });
136
+
137
+ // INSERT sin schema (genérico - acepta cualquier campo)
138
+ let insertGeneric = await bonsaif.query({
139
+ endpoint:localMongoose,
140
+ options:{db:'mydb'},
141
+ query:{
142
+ dml: 'insert',
143
+ collection: 'logs',
144
+ document: { event: 'login', user_id: 123, timestamp: new Date() }
145
+ }
146
+ });
147
+
148
+ // FIND con filtros, sorting y populate
149
+ let find = await bonsaif.query({
150
+ endpoint:localMongoose,
151
+ options:{db:'mydb'},
152
+ query:{
153
+ dml: 'find',
154
+ collection: 'users',
155
+ filter: { age: { $gte: 25 } },
156
+ sort: { age: -1 },
157
+ limit: 10,
158
+ select: 'name email age'
159
+ }
160
+ });
161
+
162
+ // UPSERT (update o insert)
163
+ let upsert = await bonsaif.query({
164
+ endpoint:localMongoose,
165
+ options:{db:'mydb'},
166
+ query:{
167
+ dml: 'upsert',
168
+ collection: 'users',
169
+ filter: { email: 'jane@example.com' },
170
+ document: { name: 'Jane Doe', email: 'jane@example.com', age: 28 }
171
+ }
172
+ });
173
+
174
+ // AGGREGATE con pipeline
175
+ let aggregate = await bonsaif.query({
176
+ endpoint:localMongoose,
177
+ options:{db:'mydb'},
178
+ query:{
179
+ dml: 'aggregate',
180
+ collection: 'users',
181
+ pipeline: [
182
+ { $match: { age: { $gte: 25 } } },
183
+ { $group: { _id: '$status', count: { $sum: 1 }, avgAge: { $avg: '$age' } } },
184
+ { $sort: { count: -1 } }
185
+ ]
186
+ }
187
+ });
188
+
189
+ // UPDATE / UPDATEMANY
190
+ let update = await bonsaif.query({
191
+ endpoint:localMongoose,
192
+ options:{db:'mydb'},
193
+ query:{
194
+ dml: 'updateMany',
195
+ collection: 'users',
196
+ filter: { age: { $lt: 30 } },
197
+ update: { $set: { category: 'young' } }
198
+ }
199
+ });
200
+
201
+ // DELETE / DELETEMANY
202
+ let deleteMany = await bonsaif.query({
203
+ endpoint:localMongoose,
204
+ options:{db:'mydb'},
205
+ query:{
206
+ dml: 'deleteMany',
207
+ collection: 'users',
208
+ filter: { status: 'inactive' }
209
+ }
210
+ });
211
+
212
+ // DISTINCT
213
+ let distinct = await bonsaif.query({
214
+ endpoint:localMongoose,
215
+ options:{db:'mydb'},
216
+ query:{
217
+ dml: 'distinct',
218
+ collection: 'users',
219
+ field: 'status',
220
+ filter: {}
221
+ }
222
+ });
223
+ }
224
+
225
+ runMongoose();
226
+
227
+
95
228
  /**
96
229
  * Execute redis
97
230
  * https://redis.io/commands/?group=set
package/lib/execute.js CHANGED
@@ -45,6 +45,7 @@ const query = async (o)=>{
45
45
  switch(o.endpoint.client){
46
46
  case 'mariadb': rs = await mariadb(o); break;
47
47
  case 'mongodb': rs = await mongodb(o); break;
48
+ case 'mongoose': rs = await mongoose(o); break;
48
49
  case 'redis': rs = await redis(o); break;
49
50
  case 'api': rs = await api(o); break;
50
51
  case 'postgres': rs = await postgres(o); break;
@@ -127,6 +128,33 @@ const mariadb= async(o)=>{
127
128
 
128
129
  /**
129
130
  *
131
+ * @param {object} o Configuracion de mongoose
132
+ * @returns
133
+ */
134
+ const mongoose= async(o)=>{
135
+ const { local=false } = o.endpoint;
136
+ const { db = '', resultFormat=true} = o.options;
137
+ o.options.dml = 'api';
138
+ o.body = o.query;
139
+
140
+ if (local){
141
+ let mongoose = require("../lib/hookup/mongoose");
142
+ let r= await mongoose.api(o,db,o.body);
143
+ try{ r.query = o.query }catch(e){}
144
+ return resultFormat ? resultSet(r) : r ;
145
+ }else{
146
+ return new Promise((resolve, reject)=>{
147
+ backend(o)
148
+ .then(r=>{
149
+ try{ r.query = o.query }catch(e){}
150
+ resolve(resultFormat ? resultSet(r) : r);
151
+ });
152
+ });
153
+ }
154
+ }
155
+
156
+ /**
157
+ *
130
158
  * @param {object} o Configuracion de redis
131
159
  * @returns
132
160
  */
@@ -53,8 +53,10 @@ module.exports = {
53
53
 
54
54
  mongoClose: async function (mongoclient){
55
55
  try{
56
- mongoclient.then(function(mongoclient){mongoclient.close();});
57
- this.debug ? utl.log(`${tag} [Mongo] closing connection`) : '';
56
+ if (mongoclient && typeof mongoclient.close === 'function') {
57
+ await mongoclient.close();
58
+ this.debug ? utl.log(`${tag} [Mongo] closing connection`) : '';
59
+ }
58
60
  }catch(e){
59
61
  utl.log(`${tag} [Mongo] err.exec.mongoClose`,e);
60
62
  }
@@ -15,17 +15,12 @@
15
15
  let obj_json ={};
16
16
  let headers = '';
17
17
  const start = Date.now();
18
+
18
19
  return new Promise(function(resolve, reject) {
19
- //2022/08/27 VRSZ Se cambia el la utileria para consumirmo por mysql ya que mariadb no regresa los campos de las columnas
20
- conn.query(query, function (err, rows, fields) {
20
+ conn.query(query, async function (err, rows, fields) {
21
21
  const end = Date.now();
22
22
  const time = end - start;
23
- // cerrar conexion
24
- try{
25
- exec.mariadbClose(conn);
26
- }catch(e){
27
- utl.log('err.qson close '+e);
28
- }
23
+
29
24
  try{
30
25
  if (err){
31
26
  resolve({"result":{dml, headers, time:utl.milisegundosASegundos(time), code:err.errno, error:1, msg:err.sqlMessage}, results:err});
@@ -50,7 +45,6 @@
50
45
  tipo = 'insert';
51
46
  headers = 'insert_id|changed_rows';
52
47
  }
53
- //Remove RowDataPacket {} Object.values(JSON.parse(JSON.stringify(rows)))
54
48
  switch(tipo){
55
49
  case 'store': data = Object.values(JSON.parse(JSON.stringify(rows[0]))); break;
56
50
  case 'insert': data =[{"insert_id":rows.insertId, "changed_rows":rows.changedRows}]; break;
@@ -60,13 +54,20 @@
60
54
  }
61
55
  }catch(e){
62
56
  console.log(e);
57
+ resolve({"result":{dml, headers:"", time:utl.milisegundosASegundos(time), code:500, error:1, msg:e}, results:e});
58
+ }finally{
59
+ // Cerrar conexión SIEMPRE
60
+ try{
61
+ await exec.mariadbClose(conn);
62
+ }catch(e){
63
+ utl.log('err.qson.close '+e);
64
+ }
63
65
  }
64
66
  });
65
67
  });
66
68
  }
67
69
 
68
70
  const api=async (options,db,query,dml,ip,tag,callback)=>{
69
- //Inicializar conexiones a bases
70
71
  tag = tag == null ? '': tag;
71
72
  const exec = require("./exec");
72
73
 
@@ -78,6 +79,14 @@ const api=async (options,db,query,dml,ip,tag,callback)=>{
78
79
  }catch(e){
79
80
  r.result.headers = 'err';
80
81
  r.data=[{'err':e}];
82
+ // Cerrar conexión si hubo error antes de qson
83
+ if (con){
84
+ try{
85
+ await exec.mariadbClose(con);
86
+ }catch(closeErr){
87
+ utl.log('err.api.close.catch '+closeErr);
88
+ }
89
+ }
81
90
  }finally {
82
91
  try{
83
92
  let code = r.result.code;
@@ -89,7 +98,16 @@ const api=async (options,db,query,dml,ip,tag,callback)=>{
89
98
  let connErr = await execErr.mariadbConn(options);
90
99
  try{
91
100
  let rerr = await qson(db,connErr,qErr,dml,ip);
101
+ // qson ya cierra connErr, no necesitamos cerrarlo aquí
92
102
  }catch(e){
103
+ // Si falla el logging, cerrar la conexión de error
104
+ if (connErr){
105
+ try{
106
+ await execErr.mariadbClose(connErr);
107
+ }catch(closeErr){
108
+ utl.log('err.api.connErr.close '+closeErr);
109
+ }
110
+ }
93
111
  }
94
112
  }
95
113
  }catch(e){