@cocreate/mongodb 1.7.2 → 1.9.0

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/src/index.js CHANGED
@@ -20,52 +20,44 @@ async function dbClient(data) {
20
20
  return
21
21
  }
22
22
 
23
- async function databaseStats(data) {
24
- const client = await dbClient(data)
25
- if (!client) return
26
- const db = client.db(data.organization_id)
27
- const stats = await db.stats()
28
- stats.storage = data.storageName
29
- if (!data.stats)
30
- data.stats = [stats]
31
- else
32
- data.stats.push(stats)
33
- return data
34
- }
35
-
36
- function createDatabase(data) {
37
- return database('createDatabase', data)
38
- }
39
-
40
- function readDatabase(data) {
41
- return database('readDatabase', data)
42
- }
43
-
44
- function updateDatabase(data) {
45
- return database('updateDatabase', data)
46
- }
47
-
48
- function deleteDatabase(data) {
49
- return database('deleteDatabase', data)
23
+ function send(data) {
24
+ let [method, type] = data.method.split('.')
25
+ // let action = data.method.replace(/\.([a-z])/g, (_, match) => match.toUpperCase());
26
+
27
+ if (type === 'database')
28
+ return database(method + type.charAt(0).toUpperCase() + type.slice(1), data)
29
+ if (type === 'array')
30
+ return array(method + type.charAt(0).toUpperCase() + type.slice(1), data)
31
+ if (type === 'object')
32
+ return object(method + type.charAt(0).toUpperCase() + type.slice(1), data)
50
33
  }
51
34
 
52
35
  function database(action, data) {
53
36
  return new Promise(async (resolve, reject) => {
54
37
  let type = 'database'
55
38
  let databaseArray = []
39
+ let dataTransferedIn = 0
40
+ let dataTransferedOut = 0
56
41
 
57
42
  try {
58
43
  const client = await dbClient(data)
59
44
  if (!client) return
60
45
  if (action == 'readDatabase') {
61
46
  const db = client.db().admin();
47
+ // TODO: support if a database name is defined then return the database details and stats
48
+ // else apply filter and return dbs for which each should have stats and details
49
+ // if (data.database) {
50
+ // const db = client.db(data.organization_id)
51
+ // const stats = await db.stats()
52
+ // }
62
53
 
63
54
  // List all the available databases
64
55
  db.listDatabases(function (err, dbs) {
56
+ dataTransferedIn += getBytes(dbs)
65
57
 
66
58
  for (let database of dbs.databases) {
67
- if (data.filter && data.filter.query) {
68
- let isFilter = queryData(database, data.filter.query)
59
+ if (data.$filter && data.$filter.query) {
60
+ let isFilter = queryData(database, data.$filter.query)
69
61
  if (isFilter)
70
62
  databaseArray.push({ database, storage: data.storageName })
71
63
  } else
@@ -77,8 +69,9 @@ function database(action, data) {
77
69
  }
78
70
  if (action == 'deleteDatabase') {
79
71
  const db = client.db(data.database);
80
- db.dropDatabase().then(response => {
81
- resolve(response)
72
+ db.dropDatabase().then(restult => {
73
+ dataTransferedIn += getBytes(restult)
74
+ resolve(restult)
82
75
  })
83
76
  }
84
77
  } catch (error) {
@@ -92,27 +85,12 @@ function database(action, data) {
92
85
  });
93
86
  }
94
87
 
95
-
96
- function createCollection(data) {
97
- return array('createCollection', data)
98
- }
99
-
100
- function readCollection(data) {
101
- return array('readCollection', data)
102
- }
103
-
104
- function updateCollection(data) {
105
- return array('updateCollection', data)
106
- }
107
-
108
- function deleteCollection(data) {
109
- return array('deleteCollection', data)
110
- }
111
-
112
88
  function array(action, data) {
113
89
  return new Promise(async (resolve, reject) => {
114
90
  let type = 'array'
115
91
  let arrayArray = [];
92
+ let dataTransferedIn = 0
93
+ let dataTransferedOut = 0
116
94
 
117
95
  try {
118
96
  const client = await dbClient(data)
@@ -131,16 +109,18 @@ function array(action, data) {
131
109
 
132
110
  if (action == 'readCollection') {
133
111
 
134
- let { query, sort } = getFilters(data);
112
+ let { query, sort } = await createFilter(data);
135
113
 
136
114
  db.listCollections().toArray(function (error, result) {
137
115
  if (error)
138
116
  errorHandler(data, error, database)
139
117
 
140
118
  if (result) {
119
+ dataTransferedIn += getBytes(result)
120
+
141
121
  for (let res of result) {
142
- if (data.filter && data.filter.query) {
143
- let isFilter = queryData(res, data.filter.query)
122
+ if (data.$filter && data.$filter.query) {
123
+ let isFilter = queryData(res, data.$filter.query)
144
124
  if (isFilter)
145
125
  arrayArray.push({ name: res.name, database, storage: data.storageName })
146
126
  } else
@@ -150,7 +130,7 @@ function array(action, data) {
150
130
 
151
131
  databasesLength -= 1
152
132
  if (!databasesLength) {
153
- data = createData(data, arrayArray, type)
133
+ data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
154
134
  resolve(data)
155
135
  }
156
136
  })
@@ -169,19 +149,22 @@ function array(action, data) {
169
149
  for (let array of arrays) {
170
150
 
171
151
  if (action == 'createCollection') {
152
+ dataTransferedOut += getBytes(array)
172
153
  db.createCollection(array, function (error, result) {
173
154
  if (error)
174
155
  errorHandler(data, error, database, array)
175
156
 
176
- if (result)
157
+ if (result) {
158
+ dataTransferedIn += getBytes(result)
177
159
  arrayArray.push({ name: array, database, storage: data.storageName })
160
+ }
178
161
 
179
162
  arraysLength -= 1
180
163
  if (!arraysLength)
181
164
  databasesLength -= 1
182
165
 
183
166
  if (!databasesLength && !arraysLength) {
184
- data = createData(data, arrayArray, type)
167
+ data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
185
168
  resolve(data)
186
169
  }
187
170
  })
@@ -193,19 +176,21 @@ function array(action, data) {
193
176
  const arrayObj = db.collection(array);
194
177
 
195
178
  if (action == 'updateCollection') {
179
+ dataTransferedOut += getBytes(result)
196
180
  arrayObj.rename(value, function (error, result) {
197
181
  if (error)
198
182
  errorHandler(data, error, database, array)
199
183
 
200
- if (result)
184
+ if (result) {
185
+ dataTransferedIn += getBytes(result)
201
186
  arrayArray.push({ name: value, oldName: array, database, storage: data.storageName })
202
-
187
+ }
203
188
  arraysLength -= 1
204
189
  if (!arraysLength)
205
190
  databasesLength -= 1
206
191
 
207
192
  if (!databasesLength && !arraysLength) {
208
- data = createData(data, arrayArray, type)
193
+ data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
209
194
  resolve(data)
210
195
  }
211
196
 
@@ -217,15 +202,17 @@ function array(action, data) {
217
202
  if (error)
218
203
  errorHandler(data, error, database, array)
219
204
 
220
- if (result)
205
+ if (result) {
206
+ dataTransferedOut += getBytes(result)
221
207
  arrayArray.push({ name: array, database, storage: data.storageName })
208
+ }
222
209
 
223
210
  arraysLength -= 1
224
211
  if (!arraysLength)
225
212
  databasesLength -= 1
226
213
 
227
214
  if (!databasesLength && !arraysLength) {
228
- data = createData(data, arrayArray, type)
215
+ data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
229
216
  resolve(data)
230
217
  }
231
218
 
@@ -248,324 +235,169 @@ function array(action, data) {
248
235
  });
249
236
  }
250
237
 
251
-
252
- function createObject(data) {
253
- return object('createObject', data)
254
- }
255
-
256
- function readObject(data) {
257
- return object('readObject', data)
258
- }
259
-
260
- function updateObject(data) {
261
- return object('updateObject', data)
262
- }
263
-
264
- function deleteObject(data) {
265
- return object('deleteObject', data)
266
- }
267
-
268
238
  function object(action, data) {
269
239
  return new Promise(async (resolve, reject) => {
270
240
  try {
271
241
  const client = await dbClient(data)
272
242
  if (!client) return
273
-
243
+ let dataTransferedIn = 0
244
+ let dataTransferedOut = 0
274
245
  let type = 'object'
275
246
  let documents = [];
276
247
 
277
248
  if (data.request)
278
249
  data[type] = data.request
279
250
 
280
-
281
251
  if (!data['timeStamp'])
282
252
  data['timeStamp'] = new Date().toISOString()
283
253
 
284
-
285
- let isFilter
286
- if (data.filter && data.filter.query)
287
- isFilter = true
288
-
289
254
  let databases = data.database;
290
255
  if (!Array.isArray(databases))
291
256
  databases = [databases]
292
257
 
293
- let databasesLength = databases.length
294
258
  for (let database of databases) {
295
259
  let arrays = data.array;
296
260
  if (!Array.isArray(arrays))
297
261
  arrays = [arrays]
298
262
 
299
- let arraysLength = arrays.length
300
263
  for (let array of arrays) {
301
264
  const db = client.db(database);
302
265
  const arrayObj = db.collection(array);
266
+ const reference = { $storage: data.storageName, $database: database, $array: array }
303
267
 
304
- let { query, sort } = getFilters(data);
305
- if (data['organization_id']) {
306
- query['organization_id'] = { $eq: data['organization_id'] }
307
- }
308
-
309
- let _ids = []
310
- let update_ids = []
311
- let updateData = {}
312
-
313
- if (data[type]) {
314
- if (!Array.isArray(data[type]))
315
- data[type] = [data[type]]
316
- for (let i = 0; i < data[type].length; i++) {
317
- data[type][i] = replaceArray(data[type][i])
318
- data[type][i]['organization_id'] = data['organization_id'];
268
+ if (data[type] && !Array.isArray(data[type]))
269
+ data[type] = [data[type]]
319
270
 
271
+ let isFilter
272
+ if (data.$filter && data.$filter.query)
273
+ isFilter = true
320
274
 
321
- if (action == 'createObject') {
322
- data[type][i] = dotNotationToObject(data[type][i])
275
+ let filter = await createFilter(data, arrayObj);
323
276
 
324
- if (!data[type][i]._id)
325
- data[type][i]._id = ObjectId()
326
- else
327
- data[type][i]._id = ObjectId(data[type][i]._id)
328
- data[type][i]['created'] = { on: data.timeStamp, by: data.user_id || data.clientId }
329
- }
330
- if (action == 'readObject' && data[type][i]._id) {
331
- _ids.push(ObjectId(data[type][i]._id))
332
- }
333
- if (action == 'updateObject') {
334
- if (data[type][i]._id)
335
- update_ids.push({ _id: data[type][i]._id, updateDoc: data[type][i], updateType: '_id' })
277
+ let projections = {}, projection = {}, update = {}, options = {}
336
278
 
337
- if (!data[type][i]._id)
338
- updateData = createUpdate({ object: [data[type][i]] }, type)
279
+ if (isFilter && (!data[type] || !data[type].length))
280
+ data[type] = [{}]
339
281
 
340
- data[type][i]['modified'] = { on: data.timeStamp, by: data.user_id || data.clientId }
282
+ if (action === 'updateObject')
283
+ createUpdate(update, options, data, true)
341
284
 
342
- }
343
- if (action == 'deleteObject') {
344
- if (data[type][i]._id) {
345
- _ids.push(ObjectId(data[type][i]._id))
346
- documents.push({ _id: data[type][i]._id, storage: data.storageName, database, array })
347
- }
348
- }
285
+ for (let i = 0; i < data[type].length; i++) {
286
+ if (action !== 'createObject' && data[type][i].$filter) {
287
+ isFilter = true
288
+ reference['$filter'] = data[type][i].$filter
289
+ filter = await createFilter({ $filter: data[type][i].$filter }, arrayObj)
349
290
  }
350
- if (_ids.length == 1)
351
- query['_id'] = ObjectId(_ids[0])
352
- else if (_ids.length > 0)
353
- query['_id'] = { $in: _ids }
354
- }
355
-
356
-
357
- if (action == 'createObject') {
358
- arrayObj.insertMany(data[type], function (error, result) {
359
- if (error)
360
- errorHandler(data, error, database, array)
361
-
362
- for (let i = 0; i < data[type].length; i++)
363
- documents.push({ storage: data.storageName, database, array, ...data[type][i] })
364
-
365
- arraysLength -= 1
366
- if (!arraysLength)
367
- databasesLength -= 1
368
291
 
369
- if (!databasesLength && !arraysLength) {
370
- data = createData(data, documents, type)
371
- resolve(data)
372
- }
373
- });
374
- }
292
+ let { query, sort, index, limit } = filter
375
293
 
376
- if (action == 'readObject') {
377
- let index = 0, limit = 0
378
- if (data.filter) {
379
- const count = await arrayObj.estimatedDocumentCount()
380
- data.filter.count = count
381
-
382
- if (data.filter.index)
383
- index = data.filter.index
384
- if (data.filter.limit)
385
- limit = data.filter.limit
386
- if (limit)
387
- limit = index + limit;
294
+ if (action === 'createObject') {
295
+ data[type][i] = replaceArray(data[type][i])
296
+ data[type][i] = dotNotationToObject(data[type][i])
297
+ data[type][i]._id = ObjectId(data[type][i]._id)
298
+ data[type][i]['organization_id'] = data['organization_id'];
299
+ data[type][i]['created'] = { on: data.timeStamp, by: data.user_id || data.clientId }
300
+ } else if (action === 'readObject') {
301
+ projection = createProjection(data[type][i])
302
+ } else if (action === 'updateObject') {
303
+ data[type][i].modified = { on: data.timeStamp, by: data.user_id || data.clientId }
304
+ data[type][i].organization_id = data.organization_id
305
+ createUpdate(update, options, data[type][i])
388
306
  }
389
307
 
390
- arrayObj.find(query).skip(index).limit(limit).sort(sort).toArray(function (error, result) {
391
- if (error)
392
- errorHandler(data, error, database, array)
393
-
394
- if (result) {
395
- // TODO: forEach at cursor
396
- for (let doc of result) {
397
- let isMatch = true
398
- if (data.filter && data.filter['search'])
399
- isMatch = searchData(doc, data.filter['search'])
400
- if (isMatch) {
401
- doc.storage = 'mongodb'
402
- doc.database = database
403
- doc.array = array
404
- doc._id = doc._id.toString()
405
-
406
- if (data.returnObject == false) {
407
- let tempDoc = {};
408
- let docs = new Map(data[type].map((obj) => [obj._id, obj]));
409
- let doc1 = docs.get(doc._id)
410
- if (doc1) {
411
- tempDoc._id = tempDoc
412
- for (let key of Object.keys(doc1)) {
413
- tempDoc[key] = doc[key]
414
- }
415
- doc = tempDoc
416
- }
417
- }
308
+ if (data[type][i]._id) {
309
+ try {
310
+ if (action !== 'createObject') {
311
+ query._id = ObjectId(data[type][i]._id)
312
+ }
418
313
 
419
- documents.push(doc)
420
- }
314
+ dataTransferedOut += getBytes({ query, update, projection, options })
315
+
316
+ let result
317
+ if (action === 'createObject') {
318
+ let _id = data[type][i]._id.toString()
319
+ // TODO: type error occuring when pushing the item pushes but throws an error
320
+ documents.push({ ...data[type][i], ...reference, _id })
321
+ } else if (action === 'readObject') {
322
+ result = await arrayObj.findOne(query, projection);
323
+ result._id = result._id.toString()
324
+ documents.push({ ...result, ...reference })
325
+ } else if (action === 'updateObject') {
326
+ result = await arrayObj.updateOne(query, update, options);
327
+ documents.push({ ...data[type][i], ...reference })
328
+ } else if (action === 'deleteObject') {
329
+ result = await arrayObj.deleteOne(query);
330
+ documents.push({ ...reference, _id: data[type][i]._id })
421
331
  }
332
+ dataTransferedIn += getBytes(result)
422
333
 
423
- // if (index && limit) {
424
- // documents = documents.slice(index, limit)
425
- // }
334
+ } catch (error) {
335
+ errorHandler(data, error, database, array)
426
336
  }
337
+ } else if (isFilter) {
338
+ try {
339
+ if (action === 'readObject')
340
+ projection = { ...projections, ...projection }
427
341
 
428
- arraysLength -= 1
429
- if (!arraysLength)
430
- databasesLength -= 1
431
-
432
- if (!databasesLength && !arraysLength) {
433
- data = createData(data, documents, type)
434
- resolve(data)
435
- }
436
- });
437
- }
342
+ delete query._id
438
343
 
439
- if (action == 'updateObject' || action == 'deleteObject') {
440
- const queryDocs = () => {
441
- return new Promise(async (resolve, reject) => {
344
+ dataTransferedOut += getBytes({ query, projection, sort, index, limit })
345
+ let document = ''
442
346
 
443
- arrayObj.find(query).sort(sort).toArray(function (error, result) {
444
- if (error)
445
- errorHandler(data, error, database, array)
347
+ const cursor = arrayObj.find(query, projection).sort(sort).skip(index).limit(limit);
348
+ if (!(await cursor.hasNext()) && action === 'updateObject' && data.upsert)
349
+ document = { _id: ObjectId(data[type][i]._id) }
350
+ while (await cursor.hasNext() || document) {
351
+ if (!document)
352
+ document = await cursor.next();
446
353
 
447
- if (data.filter && data.filter.search) {
448
- let searchResult = []
354
+ dataTransferedIn += getBytes(document)
449
355
 
450
- for (let doc of result) {
451
- let isMatch = searchData(doc, data.filter.search)
452
- if (isMatch)
453
- searchResult.push(doc)
454
- }
455
- result = searchResult
356
+ if (data.$filter && data.$filter.search) {
357
+ let isMatch = searchData(document, data.$filter.search)
358
+ if (!isMatch)
359
+ continue;
456
360
  }
457
- resolve(result)
458
- })
459
- }, (err) => {
460
- console.log(err);
461
- });
462
- }
463
361
 
464
- let Result, $update, update, projection;
362
+ if (action === 'readObject') {
363
+ documents.push({ ...document, ...reference, _id: document._id.toString() })
364
+ } else {
365
+ dataTransferedOut += getBytes({ _id: document._id, update, options })
465
366
 
466
- if (isFilter && data.returnObject != false)
467
- if (action == 'deleteObject' || action == 'updateObject' && updateData.update)
468
- Result = await queryDocs()
469
-
470
- if (Result) {
471
- for (let doc of Result) {
472
- if (action == 'deleteObject')
473
- documents.push({ _id: doc._id, storage: data.storageName, database, array })
474
- else
475
- doc['modified'] = { on: data.timeStamp, by: data.user_id || data.clientId }
476
-
477
- _ids.push(doc._id)
478
- }
479
- update_ids.push({ updateType: 'filter' })
480
- }
481
-
482
- if (action == 'updateObject') {
483
- let docsLength = update_ids.length
484
- for (let { updateDoc, updateType } of update_ids) {
485
-
486
- if (updateType == '_id') {
487
- let update_id = updateDoc._id
488
- query['_id'] = ObjectId(update_id)
489
- $update = createUpdate({ object: [updateDoc] }, type)
490
- update = $update.update
491
- projection = $update.projection
492
- documents.push({ _id: update_id, storage: data.storageName, database, array, ...update['$set'] })
493
- }
494
-
495
- if (updateType == 'filter') {
496
- query['_id'] = { $in: _ids }
497
- $update = updateData
498
- update = $update.update
499
- projection = $update.projection
500
- for (let _id of _ids)
501
- documents.push({ _id, storage: data.storageName, database, array, ...update['$set'] })
502
-
503
- }
504
-
505
- update['$set']['organization_id'] = data.organization_id
506
-
507
- arrayObj.updateMany(query, update, {
508
- upsert: data.upsert,
509
- projection
510
- }).then((result) => {
511
-
512
- }).catch((error) => {
513
- errorHandler(data, error, database, array)
514
- console.log(action, 'error', error);
515
- }).finally((error) => {
516
- docsLength -= 1
517
- if (!docsLength)
518
- arraysLength -= 1
519
-
520
- if (!arraysLength)
521
- databasesLength -= 1
367
+ let result
368
+ if (action === 'updateObject') {
369
+ result = await arrayObj.updateOne({ _id: document._id }, update, options);
370
+ } else if (action === 'deleteObject') {
371
+ result = await arrayObj.deleteOne({ _id: document._id });
372
+ }
522
373
 
523
- if (!databasesLength && !arraysLength) {
524
- data = createData(data, documents, type)
525
- resolve(data)
374
+ dataTransferedIn += getBytes(result)
375
+ documents.push({ ...data[type][i], ...reference, _id: document._id.toString() })
526
376
  }
527
- })
528
- }
529
-
530
- if (!update_ids.length) {
531
- docsLength -= 1
532
- if (!docsLength)
533
- arraysLength -= 1
534
-
535
- if (!arraysLength)
536
- databasesLength -= 1
537
-
538
- if (!databasesLength && !arraysLength) {
539
- data = createData(data, documents, type)
540
- resolve(data)
377
+ document = ''
541
378
  }
379
+ } catch (error) {
380
+ errorHandler(data, error, database, array)
542
381
  }
543
-
544
382
  }
383
+ }
545
384
 
546
- if (action == 'deleteObject') {
547
- if (_ids.length == 1)
548
- query['_id'] = ObjectId(_ids[0])
549
- else if (_ids.length > 0)
550
- query['_id'] = { $in: _ids }
551
- arrayObj.deleteMany(query, function (error, result) {
552
- arraysLength -= 1
553
- if (!arraysLength)
554
- databasesLength -= 1
555
-
556
- if (!databasesLength && !arraysLength) {
557
- data = createData(data, documents, type)
558
- resolve(data)
559
- }
560
-
561
- })
385
+ if (action === 'createObject') {
386
+ try {
387
+ dataTransferedOut += getBytes(data[type])
388
+ const result = await arrayObj.insertMany(data[type]);
389
+ dataTransferedIn += getBytes(result)
390
+ } catch (error) {
391
+ errorHandler(data, error, database, array)
562
392
  }
563
-
564
393
  }
565
394
 
566
395
  }
567
396
  }
568
397
 
398
+ data = createData(data, documents, type, dataTransferedIn, dataTransferedOut)
399
+ resolve(data)
400
+
569
401
  } catch (error) {
570
402
  errorHandler(data, error)
571
403
  console.log(action, 'error', error);
@@ -577,110 +409,136 @@ function object(action, data) {
577
409
 
578
410
  }
579
411
 
580
- function createUpdate(data, type) {
581
- let update = {}, projection = {};
582
- if (data[type][0]) {
583
- update['$set'] = data[type][0]
584
- // update['$set']['organization_id'] = data['organization_id'];
585
- if (update['$set']['_id'])
586
- delete update['$set']['_id']
587
- Object.keys(update['$set']).forEach(key => {
588
-
589
- if (key.includes('[u]')) {
590
- update['$addToSet'] = { [key.replace('[u]', '')]: update['$set'][key] }
591
- delete update['$set'][key]
592
- } else if (key.includes('[]')) {
593
- if (!Array.isArray(update['$set'][key]))
594
- update['$set'][key] = [update['$set'][key]]
595
-
596
- update['$push'] = {
597
- [key.replace('[]', '')]: { $each: update['$set'][key] }
598
- }
599
- delete update['$set'][key]
600
- }
601
- // { $push: { "skills": { $each: ["Sports", "Acting"] } } })
602
- // { $addToSet: { "skills": "GST" } }) // adds "GST"to all arrays if not exist
603
- projection[key] = 1
604
- })
605
- }
412
+ function createUpdate(update, options, data, isGlobal) {
413
+ if (data.upsert)
414
+ options.upsert = data.upsert
415
+ if (data.$upsert)
416
+ options.upsert = data.$upsert
417
+
418
+ Object.keys(data).forEach(key => {
419
+ if (isGlobal && !key.startsWith('$') || key === '_id')
420
+ return
421
+
422
+ let operator
423
+ if (key.endsWith(']')) {
424
+ const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
425
+ var match = key.match(regex);
426
+ var index = parseInt(match[2], 10);
427
+ if (index === NaN)
428
+ operator = match[2]
429
+ var arrayKey = match[1].replace(/\[(\d+)\]/g, '.$1');
430
+ }
606
431
 
607
- if (data['deleteName']) {
608
- update['$unset'] = replaceArray(data['deleteName']);
609
- }
432
+ if (key.startsWith('$'))
433
+ operator = key.split('.')[0]
434
+ else if (!operator && typeof data[key] === 'string' && data[key].startsWith('$'))
435
+ operator = data[key]
610
436
 
611
- if (data['updateName']) {
612
- update['$rename'] = replaceArray(data['updateName'])
613
- for (const [key, value] of Object.entries(update['$rename'])) {
614
- if (/\.([0-9]*)/g.test(key) || /\[([0-9]*)\]/g.test(value)) {
615
- console.log('key is array', /\[([0-9]*)\]/g.test(value), /\.([0-9]*)/g.test(key))
616
- } else {
617
- let newValue = replaceArray({ [value]: value })
618
- let oldkey = key;
619
- for (const [key] of Object.entries(newValue)) {
620
- update['$rename'][oldkey] = key
437
+ if (!update['$set'])
438
+ update['$set'] = {}
439
+
440
+ let originalKey = key
441
+ key = key.replace(/\[(\d+)\]/g, '.$1');
442
+
443
+ let operators = ['$rename', '$inc', '$push', '$splice', '$unset', '$delete', '$slice', '$pop']
444
+ if (!operators.includes(operator) && typeof index !== 'number') {
445
+ if (!isGlobal)
446
+ update['$set'][key] = data[originalKey]
447
+ return
448
+ }
449
+
450
+ let updates = {}
451
+ if (operator === '$rename') {
452
+ if (key === '$rename')
453
+ for (let oldkey of Object.keys(data[originalKey])) {
454
+ key = '$rename.' + oldkey
455
+ updates[key] = data[originalKey][oldkey].replace(/\[(\d+)\]/g, '.$1')
621
456
  }
622
- }
457
+ else
458
+ updates[key] = data[originalKey].replace(/\[(\d+)\]/g, '.$1')
459
+
460
+ } else if (operator === '$delete' || operator === '$unset' || operator === '$slice') {
461
+ operator = '$unset'
462
+ updates[key] = 1
463
+ if (!updates['$pull'])
464
+ updates['$pull'] = {}
465
+ updates['$pull'][key] = null
466
+ } else if (operator === '$pop') {
467
+ key = arrayKey
468
+ updates[key] = index || 1
469
+ } else if (operator === '$addToSet' || operator === '$pull') {
470
+ key = arrayKey
471
+ updates[key] = data[originalKey]
472
+ } else if (operator === '$push' || typeof index === 'number') {
473
+ if (!Array.isArray(data[originalKey]))
474
+ updates[key] = [data[originalKey]]
475
+ else
476
+ updates[key] = data[originalKey]
477
+
478
+ let insert = { $each: updates[key] }
479
+ if (typeof index === 'number' && index >= 0)
480
+ insert.$postion = index
481
+
482
+ updates[key] = insert
483
+ } else if (operator === '$inc') {
484
+ updates[key] = data[originalKey]
623
485
  }
624
- }
625
486
 
626
- return { update, projection }
487
+ if (!update[operator])
488
+ update[operator] = {}
627
489
 
490
+ if (key === operator)
491
+ update[operator] = { ...update[operator], ...replaceArray(updates[key]) }
492
+ else
493
+ update[operator][key.replace(operator, '')] = updates[key]
494
+ })
628
495
  }
629
496
 
630
- function createData(data, array, type) {
631
- if (!data.request)
632
- data.request = data[type] || {}
497
+ async function createFilter(data, arrayObj) {
498
+ let query = {}, sort = {}, index = 0, limit = 0, count
633
499
 
634
- if (data.filter && data.filter.sort)
635
- data[type] = sortData(array, data.filter.sort)
636
- else
637
- data[type] = array
500
+ if (data.$filter) {
501
+ if (data.$filter.query)
502
+ query = createQuery(data.$filter.query);
638
503
 
639
- if (data.returnLog) {
640
- if (!data.log)
641
- data.log = []
642
- data.log.push(...data[type])
643
- }
644
504
 
645
- return data
646
- }
505
+ if (data.$filter.sort) {
506
+ for (let i = 0; i < data.$filter.sort.length; i++) {
507
+ let direction = data.$filter.sort[i].direction
508
+ if (direction == 'desc' || direction == -1)
509
+ direction = -1;
510
+ else
511
+ direction = 1;
647
512
 
648
- function getFilters(data) {
649
- let query = {}, sort = {}
650
- let filter = {
651
- query: [],
652
- sort: [],
653
- search: {
654
- value: [],
655
- type: "or"
656
- },
657
- index: 0,
658
- ...data.filter
659
- };
660
-
661
- query = createQuery(filter.query);
662
-
663
-
664
- if (filter.sort) {
665
- for (let i = 0; i < filter.sort.length; i++) {
666
- let direction = filter.sort[i].direction
667
- if (direction == 'desc' || direction == -1)
668
- direction = -1;
669
- else
670
- direction = 1;
513
+ sort[data.$filter.sort[i].key] = direction
514
+ }
515
+ }
671
516
 
672
- sort[filter.sort[i].key] = filter.sort[i].direction
517
+ if (arrayObj) {
518
+ count = await arrayObj.estimatedDocumentCount()
519
+ data.$filter.count = count
673
520
  }
521
+
522
+ if (data.$filter.index)
523
+ index = data.$filter.index
524
+ if (data.$filter.limit)
525
+ limit = data.$filter.limit
526
+ if (limit)
527
+ limit = index + limit;
674
528
  }
675
- return { query, sort }
529
+
530
+ if (data['organization_id'])
531
+ query['organization_id'] = { $eq: data['organization_id'] }
532
+
533
+ return { query, sort, index, limit, count }
676
534
  }
677
535
 
678
- // TODO: create impved mongodb query to cover many cases
679
- function createQuery(filters) {
680
- let query = new Object();
681
536
 
537
+ // TODO: improve mongodb query to cover many cases
538
+ function createQuery(queries) {
539
+ let query = new Object();
682
540
 
683
- for (let item of filters) {
541
+ for (let item of queries) {
684
542
 
685
543
  if (!item.key)
686
544
  continue
@@ -731,6 +589,13 @@ function createQuery(filters) {
731
589
  else
732
590
  query[key] = { $in: item.value }
733
591
  break;
592
+ case '$or':
593
+ if (!query[item.operator])
594
+ query[item.operator] = [{ [key]: item.value }];
595
+ else
596
+ query[item.operator].push({ [key]: item.value })
597
+ delete query[key]
598
+ break;
734
599
  case '$geoWithin':
735
600
  try {
736
601
  let value = JSON.parse(item.value);
@@ -755,6 +620,63 @@ function createQuery(filters) {
755
620
  return query;
756
621
  }
757
622
 
623
+ function createProjection(data) {
624
+ let projection = {}
625
+
626
+ Object.keys(data).forEach((key) => {
627
+ if (!['_id', 'organization_id'].includes(key) && !key.startsWith('$'))
628
+ projection[key.replace(/\[(\d+)\]/g, '.$1')] = 1
629
+ });
630
+
631
+ return projection;
632
+ }
633
+
634
+ function replaceArray(data) {
635
+ let object = {}
636
+
637
+ Object.keys(data).forEach((key) => {
638
+ object[key.replace(/\[(\d+)\]/g, '.$1')] = data[key]
639
+ });
640
+
641
+ return object;
642
+ }
643
+
644
+ function createData(data, array, type, dataTransferedIn, dataTransferedOut) {
645
+ if (dataTransferedIn) {
646
+ process.emit("setBandwidth", {
647
+ type: 'in',
648
+ data: dataTransferedIn,
649
+ organization_id: data.organization_id
650
+ });
651
+ }
652
+
653
+ if (dataTransferedOut) {
654
+ process.emit("setBandwidth", {
655
+ type: 'out',
656
+ data: dataTransferedOut,
657
+ organization_id: data.organization_id
658
+ });
659
+ }
660
+
661
+ if (!data.request)
662
+ data.request = data[type] || {}
663
+
664
+ data[type] = array
665
+
666
+ if (data.returnLog) {
667
+ if (!data.log)
668
+ data.log = []
669
+ data.log.push(...data[type])
670
+ }
671
+
672
+ return data
673
+ }
674
+
675
+ function getBytes(data) {
676
+ const jsonString = JSON.stringify(data);
677
+ return Buffer.byteLength(jsonString, 'utf8');
678
+ }
679
+
758
680
  function errorHandler(data, error, database, array) {
759
681
  if (typeof error == 'object')
760
682
  error['storage'] = 'mongodb'
@@ -771,40 +693,4 @@ function errorHandler(data, error, database, array) {
771
693
  data.error = [error]
772
694
  }
773
695
 
774
- function replaceArray(data) {
775
- let keys = Object.keys(data);
776
- let objectData = {};
777
-
778
- keys.forEach((k) => {
779
- let nk = k
780
- if (/\[([0-9]*)\]/g.test(k)) {
781
- nk = nk.replace(/\[/g, '.');
782
- if (nk.endsWith(']'))
783
- nk = nk.slice(0, -1)
784
- nk = nk.replace(/\]./g, '.');
785
- nk = nk.replace(/\]/g, '.');
786
- }
787
- objectData[nk] = data[k];
788
- });
789
-
790
- return objectData;
791
- }
792
-
793
-
794
- module.exports = {
795
- databaseStats,
796
- createDatabase,
797
- readDatabase,
798
- updateDatabase,
799
- deleteDatabase,
800
-
801
- createCollection,
802
- readCollection,
803
- updateCollection,
804
- deleteCollection,
805
-
806
- createObject,
807
- readObject,
808
- updateObject,
809
- deleteObject,
810
- }
696
+ module.exports = { send }