@cocreate/mongodb 1.20.0 → 1.21.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/src/index.js +1149 -799
package/src/index.js CHANGED
@@ -1,843 +1,1193 @@
1
- const { MongoClient, ObjectId } = require('mongodb');
2
- const { dotNotationToObject, queryData, searchData, sortData, isValidDate } = require('@cocreate/utils')
3
- const clients = new Map()
4
- const organizations = {}
1
+ const { MongoClient, ObjectId } = require("mongodb");
2
+ const {
3
+ dotNotationToObject,
4
+ queryData,
5
+ searchData,
6
+ sortData,
7
+ isValidDate
8
+ } = require("@cocreate/utils");
9
+ const clients = new Map();
10
+ const organizations = {};
5
11
 
6
12
  async function dbClient(data) {
7
- if (data.storageUrl) {
8
- if (!organizations[data.organization_id])
9
- organizations[data.organization_id] = {}
10
- try {
11
- if (!organizations[data.organization_id][data.storageUrl])
12
- organizations[data.organization_id][data.storageUrl] = MongoClient.connect(data.storageUrl, { useNewUrlParser: true, useUnifiedTopology: true })
13
-
14
- organizations[data.organization_id][data.storageUrl] = await organizations[data.organization_id][data.storageUrl]
15
- return organizations[data.organization_id][data.storageUrl]
16
-
17
- } catch (error) {
18
- console.error(`${data.organization_id}: storageName ${data.storageName} failed to connect to mongodb`)
19
- errorHandler(data, error)
20
- return { status: false }
21
- }
22
- }
23
-
24
- errorHandler(data, 'missing StorageUrl')
25
- return
13
+ if (data.storageUrl) {
14
+ if (!organizations[data.organization_id])
15
+ organizations[data.organization_id] = {};
16
+ try {
17
+ if (!organizations[data.organization_id][data.storageUrl])
18
+ organizations[data.organization_id][data.storageUrl] =
19
+ MongoClient.connect(data.storageUrl, {
20
+ useNewUrlParser: true,
21
+ useUnifiedTopology: true
22
+ });
23
+
24
+ organizations[data.organization_id][data.storageUrl] =
25
+ await organizations[data.organization_id][data.storageUrl];
26
+ return organizations[data.organization_id][data.storageUrl];
27
+ } catch (error) {
28
+ console.error(
29
+ `${data.organization_id}: storageName ${data.storageName} failed to connect to mongodb`
30
+ );
31
+ errorHandler(data, error);
32
+ return { status: false };
33
+ }
34
+ }
35
+
36
+ errorHandler(data, "missing StorageUrl");
37
+ return;
26
38
  }
27
39
 
28
40
  function send(data) {
29
- let [type, method] = data.method.split('.')
30
- if (type === 'database')
31
- return database(method, data)
32
- if (type === 'array')
33
- return array(method, data)
34
- if (type === 'object')
35
- return object(method, data)
41
+ let [type, method] = data.method.split(".");
42
+ if (type === "database") return database(method, data);
43
+ if (type === "array") return array(method, data);
44
+ if (type === "object") return object(method, data);
36
45
  }
37
46
 
38
47
  function database(method, data) {
39
- return new Promise(async (resolve, reject) => {
40
- let type = 'database'
41
- let databaseArray = []
42
- let dataTransferedIn = 0
43
- let dataTransferedOut = 0
44
-
45
- try {
46
- const client = await dbClient(data)
47
- if (!client || client.status === false)
48
- return data
49
- if (method == 'read') {
50
- const db = client.db().admin();
51
- // TODO: support if a database name is defined then return the database details and stats
52
- // else apply filter and return dbs for which each should have stats and details
53
- // if (data.database) {
54
- // const db = client.db(data.organization_id)
55
- // const stats = await db.stats()
56
- // }
57
-
58
- // List all the available databases
59
- db.listDatabases(function (err, dbs) {
60
- dataTransferedIn += getBytes(dbs)
61
-
62
- for (let database of dbs.databases) {
63
- if (data.$filter && data.$filter.query) {
64
- let isFilter = queryData(database, data.$filter.query)
65
- if (isFilter)
66
- databaseArray.push({ database, storage: data.storageName })
67
- } else
68
- databaseArray.push({ database, storage: data.storageName })
69
- }
70
-
71
- resolve(createData(data, databaseArray, type))
72
- })
73
- }
74
- if (method == 'delete') {
75
- const db = client.db(data.database);
76
- db.dropDatabase().then(restult => {
77
- dataTransferedIn += getBytes(restult)
78
- resolve(restult)
79
- })
80
- }
81
- } catch (error) {
82
- errorHandler(data, error)
83
- console.log(method, 'error', error);
84
- resolve(data);
85
- }
86
-
87
- }, (error) => {
88
- errorHandler(data, error)
89
- });
48
+ return new Promise(
49
+ async (resolve, reject) => {
50
+ let type = "database";
51
+ let databaseArray = [];
52
+ let dataTransferedIn = 0;
53
+ let dataTransferedOut = 0;
54
+
55
+ try {
56
+ const client = await dbClient(data);
57
+ if (!client || client.status === false) return data;
58
+ if (method == "read") {
59
+ const db = client.db().admin();
60
+ // TODO: support if a database name is defined then return the database details and stats
61
+ // else apply filter and return dbs for which each should have stats and details
62
+ // if (data.database) {
63
+ // const db = client.db(data.organization_id)
64
+ // const stats = await db.stats()
65
+ // }
66
+
67
+ // List all the available databases
68
+ db.listDatabases(function (err, dbs) {
69
+ dataTransferedIn += getBytes(dbs);
70
+
71
+ for (let database of dbs.databases) {
72
+ if (data.$filter && data.$filter.query) {
73
+ let isFilter = queryData(
74
+ database,
75
+ data.$filter.query
76
+ );
77
+ if (isFilter)
78
+ databaseArray.push({
79
+ database,
80
+ storage: data.storageName
81
+ });
82
+ } else
83
+ databaseArray.push({
84
+ database,
85
+ storage: data.storageName
86
+ });
87
+ }
88
+
89
+ resolve(createData(data, databaseArray, type));
90
+ });
91
+ }
92
+ if (method == "delete") {
93
+ const db = client.db(data.database);
94
+ db.dropDatabase().then((restult) => {
95
+ dataTransferedIn += getBytes(restult);
96
+ resolve(restult);
97
+ });
98
+ }
99
+ } catch (error) {
100
+ errorHandler(data, error);
101
+ console.log(method, "error", error);
102
+ resolve(data);
103
+ }
104
+ },
105
+ (error) => {
106
+ errorHandler(data, error);
107
+ }
108
+ );
90
109
  }
91
110
 
92
111
  function array(method, data) {
93
- return new Promise(async (resolve, reject) => {
94
- let type = 'array'
95
- let arrayArray = [];
96
- let dataTransferedIn = 0
97
- let dataTransferedOut = 0
98
-
99
- try {
100
- const client = await dbClient(data)
101
- if (!client || client.status === false)
102
- return data
103
-
104
- if (data.request)
105
- data.array = data.request
106
-
107
- let databases = data.database;
108
- if (!Array.isArray(databases))
109
- databases = [databases]
110
-
111
- let databasesLength = databases.length
112
- for (let database of databases) {
113
- const db = client.db(database);
114
-
115
- if (method == 'read') {
116
-
117
- let { query, sort } = await createFilter(data);
118
-
119
- db.listCollections().toArray(function (error, result) {
120
- if (error)
121
- errorHandler(data, error, database)
122
-
123
- if (result) {
124
- dataTransferedIn += getBytes(result)
125
-
126
- for (let res of result) {
127
- if (data.$filter && data.$filter.query) {
128
- let isFilter = queryData(res, data.$filter.query)
129
- if (isFilter)
130
- arrayArray.push({ name: res.name, database, storage: data.storageName })
131
- } else
132
- arrayArray.push({ name: res.name, database, storage: data.storageName })
133
- }
134
- }
135
-
136
- databasesLength -= 1
137
- if (!databasesLength) {
138
- data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
139
- resolve(data)
140
- }
141
- })
142
- } else {
143
- let arrays
144
- let value
145
- if (method == 'update')
146
- arrays = Object.entries(data.array)
147
- else
148
- arrays = data.array;
149
-
150
- if (!Array.isArray(arrays))
151
- arrays = [arrays]
152
-
153
- let arraysLength = arrays.length
154
- for (let array of arrays) {
155
-
156
- if (method == 'create') {
157
- dataTransferedOut += getBytes(array)
158
- db.createCollection(array, function (error, result) {
159
- if (error)
160
- errorHandler(data, error, database, array)
161
-
162
- if (result) {
163
- dataTransferedIn += getBytes(result)
164
- arrayArray.push({ name: array, database, storage: data.storageName })
165
- }
166
-
167
- arraysLength -= 1
168
- if (!arraysLength)
169
- databasesLength -= 1
170
-
171
- if (!databasesLength && !arraysLength) {
172
- data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
173
- resolve(data)
174
- }
175
- })
176
- } else {
177
- if (method == 'update') {
178
- [array, value] = array
179
- }
180
-
181
- const arrayObj = db.collection(array);
182
-
183
- if (method == 'update') {
184
- dataTransferedOut += getBytes(result)
185
- arrayObj.rename(value, function (error, result) {
186
- if (error)
187
- errorHandler(data, error, database, array)
188
-
189
- if (result) {
190
- dataTransferedIn += getBytes(result)
191
- arrayArray.push({ name: value, oldName: array, database, storage: data.storageName })
192
- }
193
- arraysLength -= 1
194
- if (!arraysLength)
195
- databasesLength -= 1
196
-
197
- if (!databasesLength && !arraysLength) {
198
- data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
199
- resolve(data)
200
- }
201
-
202
- })
203
- }
204
-
205
- if (method == 'delete') {
206
- arrayObj.drop(function (error, result) {
207
- if (error)
208
- errorHandler(data, error, database, array)
209
-
210
- if (result) {
211
- dataTransferedOut += getBytes(result)
212
- arrayArray.push({ name: array, database, storage: data.storageName })
213
- }
214
-
215
- arraysLength -= 1
216
- if (!arraysLength)
217
- databasesLength -= 1
218
-
219
- if (!databasesLength && !arraysLength) {
220
- data = createData(data, arrayArray, type, dataTransferedIn, dataTransferedOut)
221
- resolve(data)
222
- }
223
-
224
- })
225
-
226
- }
227
- }
228
-
229
- }
230
- }
231
- }
232
-
233
- } catch (error) {
234
- errorHandler(data, error)
235
- console.log(method, 'error', error);
236
- resolve(data);
237
- }
238
- }, (error) => {
239
- errorHandler(data, error)
240
- });
112
+ return new Promise(
113
+ async (resolve, reject) => {
114
+ let type = "array";
115
+ let arrayArray = [];
116
+ let dataTransferedIn = 0;
117
+ let dataTransferedOut = 0;
118
+
119
+ try {
120
+ const client = await dbClient(data);
121
+ if (!client || client.status === false) return data;
122
+
123
+ if (data.request) data.array = data.request;
124
+
125
+ let databases = data.database;
126
+ if (!Array.isArray(databases)) databases = [databases];
127
+
128
+ let databasesLength = databases.length;
129
+ for (let database of databases) {
130
+ const db = client.db(database);
131
+
132
+ if (method == "read") {
133
+ let { query, sort } = await createFilter(data);
134
+
135
+ db.listCollections().toArray(function (error, result) {
136
+ if (error) errorHandler(data, error, database);
137
+
138
+ if (result) {
139
+ dataTransferedIn += getBytes(result);
140
+
141
+ for (let res of result) {
142
+ if (data.$filter && data.$filter.query) {
143
+ let isFilter = queryData(
144
+ res,
145
+ data.$filter.query
146
+ );
147
+ if (isFilter)
148
+ arrayArray.push({
149
+ name: res.name,
150
+ database,
151
+ storage: data.storageName
152
+ });
153
+ } else
154
+ arrayArray.push({
155
+ name: res.name,
156
+ database,
157
+ storage: data.storageName
158
+ });
159
+ }
160
+ }
161
+
162
+ databasesLength -= 1;
163
+ if (!databasesLength) {
164
+ data = createData(
165
+ data,
166
+ arrayArray,
167
+ type,
168
+ dataTransferedIn,
169
+ dataTransferedOut
170
+ );
171
+ resolve(data);
172
+ }
173
+ });
174
+ } else {
175
+ let arrays;
176
+ let value;
177
+ if (method == "update")
178
+ arrays = Object.entries(data.array);
179
+ else arrays = data.array;
180
+
181
+ if (!Array.isArray(arrays)) arrays = [arrays];
182
+
183
+ let arraysLength = arrays.length;
184
+ for (let array of arrays) {
185
+ if (method == "create") {
186
+ dataTransferedOut += getBytes(array);
187
+ db.createCollection(
188
+ array,
189
+ function (error, result) {
190
+ if (error)
191
+ errorHandler(
192
+ data,
193
+ error,
194
+ database,
195
+ array
196
+ );
197
+
198
+ if (result) {
199
+ dataTransferedIn +=
200
+ getBytes(result);
201
+ arrayArray.push({
202
+ name: array,
203
+ database,
204
+ storage: data.storageName
205
+ });
206
+ }
207
+
208
+ arraysLength -= 1;
209
+ if (!arraysLength) databasesLength -= 1;
210
+
211
+ if (!databasesLength && !arraysLength) {
212
+ data = createData(
213
+ data,
214
+ arrayArray,
215
+ type,
216
+ dataTransferedIn,
217
+ dataTransferedOut
218
+ );
219
+ resolve(data);
220
+ }
221
+ }
222
+ );
223
+ } else {
224
+ if (method == "update") {
225
+ [array, value] = array;
226
+ }
227
+
228
+ const arrayObj = db.collection(array);
229
+
230
+ if (method == "update") {
231
+ dataTransferedOut += getBytes(result);
232
+ arrayObj.rename(
233
+ value,
234
+ function (error, result) {
235
+ if (error)
236
+ errorHandler(
237
+ data,
238
+ error,
239
+ database,
240
+ array
241
+ );
242
+
243
+ if (result) {
244
+ dataTransferedIn +=
245
+ getBytes(result);
246
+ arrayArray.push({
247
+ name: value,
248
+ oldName: array,
249
+ database,
250
+ storage: data.storageName
251
+ });
252
+ }
253
+ arraysLength -= 1;
254
+ if (!arraysLength)
255
+ databasesLength -= 1;
256
+
257
+ if (
258
+ !databasesLength &&
259
+ !arraysLength
260
+ ) {
261
+ data = createData(
262
+ data,
263
+ arrayArray,
264
+ type,
265
+ dataTransferedIn,
266
+ dataTransferedOut
267
+ );
268
+ resolve(data);
269
+ }
270
+ }
271
+ );
272
+ }
273
+
274
+ if (method == "delete") {
275
+ arrayObj.drop(function (error, result) {
276
+ if (error)
277
+ errorHandler(
278
+ data,
279
+ error,
280
+ database,
281
+ array
282
+ );
283
+
284
+ if (result) {
285
+ dataTransferedOut +=
286
+ getBytes(result);
287
+ arrayArray.push({
288
+ name: array,
289
+ database,
290
+ storage: data.storageName
291
+ });
292
+ }
293
+
294
+ arraysLength -= 1;
295
+ if (!arraysLength) databasesLength -= 1;
296
+
297
+ if (!databasesLength && !arraysLength) {
298
+ data = createData(
299
+ data,
300
+ arrayArray,
301
+ type,
302
+ dataTransferedIn,
303
+ dataTransferedOut
304
+ );
305
+ resolve(data);
306
+ }
307
+ });
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ } catch (error) {
314
+ errorHandler(data, error);
315
+ console.log(method, "error", error);
316
+ resolve(data);
317
+ }
318
+ },
319
+ (error) => {
320
+ errorHandler(data, error);
321
+ }
322
+ );
241
323
  }
242
324
 
243
325
  function object(method, data) {
244
- return new Promise(async (resolve, reject) => {
245
- try {
246
- const client = await dbClient(data)
247
-
248
- if (!client || client.status === false)
249
- return data
250
-
251
- let dataTransferedIn = 0
252
- let dataTransferedOut = 0
253
- let type = 'object'
254
- let documents = [];
255
-
256
- if (!data['timeStamp'])
257
- data['timeStamp'] = new Date().toISOString();
258
-
259
- let databases = data.database;
260
- if (!Array.isArray(databases))
261
- databases = [databases]
262
-
263
- for (let database of databases) {
264
- let arrays = data.array;
265
- if (!Array.isArray(arrays))
266
- arrays = [arrays]
267
-
268
- for (let array of arrays) {
269
- const db = client.db(database);
270
- const arrayObj = db.collection(array);
271
- const reference = { $storage: data.storageName, $database: database, $array: array }
272
-
273
- if (!data[type])
274
- data[type] = []
275
- else if (typeof data[type] === 'string')
276
- data[type] = [{ _id: data[type] }]
277
- else if (!Array.isArray(data[type]))
278
- data[type] = [data[type]]
279
-
280
- let isFilter
281
- if (data.$filter)
282
- isFilter = true
283
- if ((isFilter && !data[type].length) || data.isFilter)
284
- data[type].splice(0, 0, { isFilter: 'isEmptyObjectFilter' });
285
-
286
- let filter = await createFilter(data, arrayObj);
287
-
288
- let projections = {}, projection = {}, update = {}, options = {}
289
-
290
- if (method === 'update')
291
- createUpdate(update, options, data, true)
292
-
293
- for (let i = 0; i < data[type].length; i++) {
294
- let $storage = data[type][i].$storage || []
295
- let $database = data[type][i].$database || []
296
- let $array = data[type][i].$array || []
297
-
298
- if (!Array.isArray($storage))
299
- $storage = [data[type][i].$storage]
300
- if (!Array.isArray($database))
301
- $database = [data[type][i].$database]
302
- if (!Array.isArray($array))
303
- $array = [data[type][i].$array]
304
-
305
- if (!$storage.includes(data.storageName))
306
- $storage.push(data.storageName)
307
- if (!$database.includes(database))
308
- $database.push(database)
309
- if (!$array.includes(array))
310
- $array.push(array)
311
-
312
- delete data[type][i].$storage
313
- delete data[type][i].$database
314
- delete data[type][i].$array
315
-
316
- if (method !== 'create' && data[type][i].$filter) {
317
- isFilter = true
318
- reference['$filter'] = data[type][i].$filter
319
- filter = await createFilter({ $filter: data[type][i].$filter }, arrayObj)
320
- }
321
-
322
- let { query, sort, index, limit } = filter
323
-
324
- if (method === 'create') {
325
- data[type][i] = replaceArray(data[type][i])
326
- data[type][i] = dotNotationToObject(data[type][i])
327
- data[type][i]['organization_id'] = data['organization_id'];
328
- data[type][i]['created'] = { on: new Date(data.timeStamp), by: data.user_id || data.clientId }
329
- } else if (method === 'read') {
330
- projection = createProjection(data[type][i])
331
- } else if (method === 'update') {
332
- if (!data[type][i].modified)
333
- data[type][i].modified = { on: new Date(data.timeStamp), by: data.user_id || data.clientId }
334
- else
335
- data[type][i].modified.on = new Date(data[type][i].modified.on)
336
-
337
- data[type][i].organization_id = data.organization_id
338
- createUpdate(update, options, data[type][i])
339
- }
340
-
341
- if (data[type][i]._id || method === 'create') {
342
- if (method !== 'create') {
343
- try {
344
- query._id = ObjectId(data[type][i]._id);
345
- } catch (error) {
346
- if (method === 'update' && options.upsert) {
347
- data[type][i]._id = ObjectId()
348
- query._id = data[type][i]._id;
349
- } else {
350
- errorHandler(data, error, database, array)
351
- continue;
352
- }
353
- }
354
- }
355
-
356
- try {
357
-
358
- dataTransferedOut += getBytes({ query, update, projection, options })
359
-
360
- let result
361
- if (method === 'create') {
362
- if (data[type][i]._id) {
363
- try {
364
- data[type][i]._id = new ObjectId(data[type][i]._id);
365
- } catch (error) {
366
- delete data[type][i]._id
367
- }
368
- }
369
- result = await arrayObj.insertOne(data[type][i]);
370
- // TODO: type error occuring when pushing the item pushes but throws an error
371
- data[type][i]._id = result.insertedId.toString()
372
- // documents.push({ ...data[type][i], ...reference })
373
- } else if (method === 'read') {
374
- result = await arrayObj.findOne(query, projection);
375
- if (result)
376
- result._id = result._id.toString()
377
-
378
- if (data[type][i].$storage && data[type][i].modified && data[type][i].modified.on) {
379
- if (!result) {
380
- result = await arrayObj.insertOne(data[type][i]);
381
- data[type][i]._id = result.insertedId.toString()
382
- } else if (result && new Date(data[type][i].modified.on) > new Date(result.modified.on)) {
383
- data[type][i] = { ...result, ...data[type][i] }
384
- createUpdate(update, options, data[type][i])
385
- result = await arrayObj.updateOne(query, update, options);
386
- } else
387
- data[type][i] = { ...data[type][i], ...result }
388
- } else if (result)
389
- data[type][i] = { ...data[type][i], ...result }
390
- else {
391
- data[type].splice(i, 1);
392
- continue;
393
- }
394
- } else if (method === 'update') {
395
- result = await arrayObj.updateOne(query, update, options);
396
-
397
- // TODO: handle upsert false and id does not exist
398
- data[type][i]._id = query._id.toString()
399
- // documents.push({ ...data[type][i], ...reference })
400
- } else if (method === 'delete') {
401
- result = await arrayObj.deleteOne(query);
402
- // documents.push({ ...reference, _id: data[type][i]._id })
403
- }
404
-
405
- data[type][i].$storage = $storage
406
- data[type][i].$database = $database
407
- data[type][i].$array = $array
408
-
409
- dataTransferedIn += getBytes(result)
410
-
411
- } catch (error) {
412
- errorHandler(data, error, database, array)
413
- }
414
- } else if (isFilter) {
415
- try {
416
- // TODO: index is 1 if indexeddb already returned an item interfering with query
417
- // if (data.array === "keys")
418
- // index = 0
419
-
420
- if (method === 'read')
421
- projection = { ...projections, ...projection }
422
-
423
- if (data.$filter && data.$filter.startingIndex >= 0)
424
- index = data.$filter.startingIndex
425
-
426
- dataTransferedOut += getBytes({ query, projection, sort, index, limit })
427
-
428
- let cursor, document = ''
429
- if (Object.keys(sort).length > 0)
430
- cursor = arrayObj.find(query, projection).sort(sort).skip(index).limit(limit).allowDiskUse(true);
431
- else
432
- cursor = arrayObj.find(query, projection).sort(sort).skip(index).limit(limit);
433
-
434
- if (!(await cursor.hasNext()) && method === 'update' && data.upsert)
435
- document = { _id: ObjectId(data[type][i]._id) }
436
-
437
- while (await cursor.hasNext() || document) {
438
- if (!document)
439
- document = await cursor.next();
440
-
441
- dataTransferedIn += getBytes(document)
442
-
443
- if (data.$filter && data.$filter.search) {
444
- let isMatch = searchData(document, data.$filter.search)
445
- if (!isMatch)
446
- continue;
447
- }
448
-
449
- if (method === 'read') {
450
- document._id = document._id.toString()
451
- let object = data[type].find(obj => obj._id && obj._id.toString() === document._id.toString())
452
- if (object) {
453
- if (object.$storage && object.modified && object.modified.on) {
454
- if (document && document.modified && new Date(object.modified.on) > new Date(document.modified.on)) {
455
- object = { ...document, ...object }
456
- createUpdate(update, options, object)
457
- document = await arrayObj.updateOne(query, update, options);
458
- dataTransferedIn += getBytes(document)
459
- } else
460
- documents.push({ ...document, ...reference })
461
- } else
462
- documents.push({ ...document, ...reference })
463
-
464
- } else
465
- documents.push({ ...document, ...reference })
466
- } else {
467
- dataTransferedOut += getBytes({ _id: document._id, update, options })
468
-
469
- let result
470
- if (method === 'update') {
471
- if (options.returnNewDocument) {
472
- let object = await arrayObj.findOneAndUpdate({ _id: document._id }, update, options);
473
- for (let key of Object.keys(object)) {
474
- if (key === '_id')
475
- continue
476
- let newArrayKey = options.newArray[key]
477
- // TODO: get index based on $operator
478
- let index = object[key].length - 1
479
- if (index >= 0)
480
- data[type][i][newArrayKey.replace('[]', `[${index}]`)] = data[type][i][newArrayKey]
481
- }
482
- } else
483
- result = await arrayObj.updateOne({ _id: document._id }, update, options);
484
- // TODO: if update.$push or update.$each read document with projection to get index and update the keys [] to include index
485
- } else if (method === 'delete') {
486
- result = await arrayObj.deleteOne({ _id: document._id });
487
- }
488
-
489
- dataTransferedIn += getBytes(result)
490
- documents.push({ ...data[type][i], ...reference, _id: document._id.toString() })
491
- // data[type].push({ ...data[type][i], ...reference, _id: document._id.toString() })
492
-
493
- }
494
- document = ''
495
- }
496
- } catch (error) {
497
- errorHandler(data, error, database, array)
498
- }
499
-
500
- }
501
- }
502
-
503
- // if (method === 'create') {
504
- // try {
505
- // dataTransferedOut += getBytes(data[type])
506
- // const result = await arrayObj.insertMany(data[type]);
507
- // dataTransferedIn += getBytes(result)
508
-
509
- // for (let i = 0; i < data[type].length; i++) {
510
- // data[type][i]._id = data[type][i]._id.toString()
511
- // }
512
- // } catch (error) {
513
- // errorHandler(data, error, database, array)
514
- // }
515
- // }
516
-
517
- }
518
- }
519
- data = createData(data, documents, type, dataTransferedIn, dataTransferedOut)
520
- resolve(data)
521
-
522
- } catch (error) {
523
- errorHandler(data, error)
524
- console.log(method, 'error', error);
525
- resolve(data);
526
- }
527
- }, (error) => {
528
- errorHandler(data, error)
529
- });
530
-
326
+ return new Promise(
327
+ async (resolve, reject) => {
328
+ try {
329
+ const client = await dbClient(data);
330
+
331
+ if (!client || client.status === false) return data;
332
+
333
+ let dataTransferedIn = 0;
334
+ let dataTransferedOut = 0;
335
+ let type = "object";
336
+ let documents = [];
337
+
338
+ if (!data["timeStamp"])
339
+ data["timeStamp"] = new Date().toISOString();
340
+
341
+ let databases = data.database;
342
+ if (!Array.isArray(databases)) databases = [databases];
343
+
344
+ for (let database of databases) {
345
+ let arrays = data.array;
346
+ if (!Array.isArray(arrays)) arrays = [arrays];
347
+
348
+ for (let array of arrays) {
349
+ const db = client.db(database);
350
+ const arrayObj = db.collection(array);
351
+ const reference = {
352
+ $storage: data.storageName,
353
+ $database: database,
354
+ $array: array
355
+ };
356
+
357
+ if (!data[type]) data[type] = [];
358
+ else if (typeof data[type] === "string")
359
+ data[type] = [{ _id: data[type] }];
360
+ else if (!Array.isArray(data[type]))
361
+ data[type] = [data[type]];
362
+
363
+ let isFilter;
364
+ if (data.$filter) isFilter = true;
365
+ if ((isFilter && !data[type].length) || data.isFilter)
366
+ data[type].splice(0, 0, {
367
+ isFilter: "isEmptyObjectFilter"
368
+ });
369
+
370
+ let filter = await createFilter(data, arrayObj);
371
+
372
+ let projections = {},
373
+ projection = {},
374
+ update = {},
375
+ options = {};
376
+
377
+ if (method === "update")
378
+ createUpdate(update, options, data, true);
379
+
380
+ for (let i = 0; i < data[type].length; i++) {
381
+ let $storage = data[type][i].$storage || [];
382
+ let $database = data[type][i].$database || [];
383
+ let $array = data[type][i].$array || [];
384
+
385
+ if (!Array.isArray($storage))
386
+ $storage = [data[type][i].$storage];
387
+ if (!Array.isArray($database))
388
+ $database = [data[type][i].$database];
389
+ if (!Array.isArray($array))
390
+ $array = [data[type][i].$array];
391
+
392
+ if (!$storage.includes(data.storageName))
393
+ $storage.push(data.storageName);
394
+ if (!$database.includes(database))
395
+ $database.push(database);
396
+ if (!$array.includes(array)) $array.push(array);
397
+
398
+ delete data[type][i].$storage;
399
+ delete data[type][i].$database;
400
+ delete data[type][i].$array;
401
+
402
+ if (method !== "create" && data[type][i].$filter) {
403
+ isFilter = true;
404
+ reference["$filter"] = data[type][i].$filter;
405
+ filter = await createFilter(
406
+ { $filter: data[type][i].$filter },
407
+ arrayObj
408
+ );
409
+ }
410
+
411
+ let { query, sort, index, limit } = filter;
412
+
413
+ if (method === "create") {
414
+ data[type][i] = replaceArray(data[type][i]);
415
+ data[type][i] = dotNotationToObject(
416
+ data[type][i]
417
+ );
418
+ data[type][i]["organization_id"] =
419
+ data["organization_id"];
420
+ data[type][i]["created"] = {
421
+ on: new Date(data.timeStamp),
422
+ by: data.user_id || data.clientId
423
+ };
424
+ } else if (method === "read") {
425
+ projection = createProjection(data[type][i]);
426
+ } else if (method === "update") {
427
+ if (!data[type][i].modified)
428
+ data[type][i].modified = {
429
+ on: new Date(data.timeStamp),
430
+ by: data.user_id || data.clientId
431
+ };
432
+ else
433
+ data[type][i].modified.on = new Date(
434
+ data[type][i].modified.on
435
+ );
436
+
437
+ data[type][i].organization_id =
438
+ data.organization_id;
439
+ createUpdate(update, options, data[type][i]);
440
+ }
441
+
442
+ if (data[type][i]._id || method === "create") {
443
+ if (method !== "create") {
444
+ try {
445
+ query._id = ObjectId(data[type][i]._id);
446
+ } catch (error) {
447
+ if (
448
+ method === "update" &&
449
+ options.upsert
450
+ ) {
451
+ data[type][i]._id = ObjectId();
452
+ query._id = data[type][i]._id;
453
+ } else {
454
+ errorHandler(
455
+ data,
456
+ error,
457
+ database,
458
+ array
459
+ );
460
+ continue;
461
+ }
462
+ }
463
+ }
464
+
465
+ try {
466
+ dataTransferedOut += getBytes({
467
+ query,
468
+ update,
469
+ projection,
470
+ options
471
+ });
472
+
473
+ let result;
474
+ if (method === "create") {
475
+ if (data[type][i]._id) {
476
+ try {
477
+ data[type][i]._id =
478
+ new ObjectId(
479
+ data[type][i]._id
480
+ );
481
+ } catch (error) {
482
+ delete data[type][i]._id;
483
+ }
484
+ }
485
+ result = await arrayObj.insertOne(
486
+ data[type][i]
487
+ );
488
+ // TODO: type error occuring when pushing the item pushes but throws an error
489
+ data[type][i]._id =
490
+ result.insertedId.toString();
491
+ // documents.push({ ...data[type][i], ...reference })
492
+ } else if (method === "read") {
493
+ result = await arrayObj.findOne(
494
+ query,
495
+ projection
496
+ );
497
+ if (result)
498
+ result._id = result._id.toString();
499
+
500
+ if (
501
+ data[type][i].$storage &&
502
+ data[type][i].modified &&
503
+ data[type][i].modified.on
504
+ ) {
505
+ if (!result) {
506
+ result =
507
+ await arrayObj.insertOne(
508
+ data[type][i]
509
+ );
510
+ data[type][i]._id =
511
+ result.insertedId.toString();
512
+ } else if (
513
+ result &&
514
+ new Date(
515
+ data[type][i].modified.on
516
+ ) > new Date(result.modified.on)
517
+ ) {
518
+ data[type][i] = {
519
+ ...result,
520
+ ...data[type][i]
521
+ };
522
+ createUpdate(
523
+ update,
524
+ options,
525
+ data[type][i]
526
+ );
527
+ result =
528
+ await arrayObj.updateOne(
529
+ query,
530
+ update,
531
+ options
532
+ );
533
+ } else
534
+ data[type][i] = {
535
+ ...data[type][i],
536
+ ...result
537
+ };
538
+ } else if (result)
539
+ data[type][i] = {
540
+ ...data[type][i],
541
+ ...result
542
+ };
543
+ else {
544
+ data[type].splice(i, 1);
545
+ continue;
546
+ }
547
+ } else if (method === "update") {
548
+ if (update['$pull'] && update['$unset']) {
549
+ result = await arrayObj.updateOne(
550
+ query,
551
+ {$unset: update['$unset']},
552
+ options
553
+ );
554
+ delete update['$unset']
555
+ }
556
+ result = await arrayObj.updateOne(
557
+ query,
558
+ update,
559
+ options
560
+ );
561
+
562
+ // TODO: handle upsert false and id does not exist
563
+ data[type][i]._id =
564
+ query._id.toString();
565
+ // documents.push({ ...data[type][i], ...reference })
566
+ } else if (method === "delete") {
567
+ result = await arrayObj.deleteOne(
568
+ query
569
+ );
570
+ // documents.push({ ...reference, _id: data[type][i]._id })
571
+ }
572
+
573
+ data[type][i].$storage = $storage;
574
+ data[type][i].$database = $database;
575
+ data[type][i].$array = $array;
576
+
577
+ dataTransferedIn += getBytes(result);
578
+ } catch (error) {
579
+ errorHandler(data, error, database, array);
580
+ }
581
+ } else if (isFilter) {
582
+ try {
583
+ // TODO: index is 1 if indexeddb already returned an item interfering with query
584
+ // if (data.array === "keys")
585
+ // index = 0
586
+
587
+ if (method === "read")
588
+ projection = {
589
+ ...projections,
590
+ ...projection
591
+ };
592
+
593
+ if (
594
+ data.$filter &&
595
+ data.$filter.startingIndex >= 0
596
+ )
597
+ index = data.$filter.startingIndex;
598
+
599
+ dataTransferedOut += getBytes({
600
+ query,
601
+ projection,
602
+ sort,
603
+ index,
604
+ limit
605
+ });
606
+
607
+ let cursor,
608
+ document = "";
609
+ if (Object.keys(sort).length > 0)
610
+ cursor = arrayObj
611
+ .find(query, projection)
612
+ .sort(sort)
613
+ .skip(index)
614
+ .limit(limit)
615
+ .allowDiskUse(true);
616
+ else
617
+ cursor = arrayObj
618
+ .find(query, projection)
619
+ .sort(sort)
620
+ .skip(index)
621
+ .limit(limit);
622
+
623
+ if (
624
+ !(await cursor.hasNext()) &&
625
+ method === "update" &&
626
+ data.upsert
627
+ )
628
+ document = {
629
+ _id: ObjectId(data[type][i]._id)
630
+ };
631
+
632
+ while (
633
+ (await cursor.hasNext()) ||
634
+ document
635
+ ) {
636
+ if (!document)
637
+ document = await cursor.next();
638
+
639
+ dataTransferedIn += getBytes(document);
640
+
641
+ if (
642
+ data.$filter &&
643
+ data.$filter.search
644
+ ) {
645
+ let isMatch = searchData(
646
+ document,
647
+ data.$filter.search
648
+ );
649
+ if (!isMatch) continue;
650
+ }
651
+
652
+ if (method === "read") {
653
+ document._id =
654
+ document._id.toString();
655
+ let object = data[type].find(
656
+ (obj) =>
657
+ obj._id &&
658
+ obj._id.toString() ===
659
+ document._id.toString()
660
+ );
661
+ if (object) {
662
+ if (
663
+ object.$storage &&
664
+ object.modified &&
665
+ object.modified.on
666
+ ) {
667
+ if (
668
+ document &&
669
+ document.modified &&
670
+ new Date(
671
+ object.modified.on
672
+ ) >
673
+ new Date(
674
+ document.modified.on
675
+ )
676
+ ) {
677
+ object = {
678
+ ...document,
679
+ ...object
680
+ };
681
+ createUpdate(
682
+ update,
683
+ options,
684
+ object
685
+ );
686
+ document =
687
+ await arrayObj.updateOne(
688
+ query,
689
+ update,
690
+ options
691
+ );
692
+ dataTransferedIn +=
693
+ getBytes(document);
694
+ } else
695
+ documents.push({
696
+ ...document,
697
+ ...reference
698
+ });
699
+ } else
700
+ documents.push({
701
+ ...document,
702
+ ...reference
703
+ });
704
+ } else
705
+ documents.push({
706
+ ...document,
707
+ ...reference
708
+ });
709
+ } else {
710
+ dataTransferedOut += getBytes({
711
+ _id: document._id,
712
+ update,
713
+ options
714
+ });
715
+
716
+ let result;
717
+ if (method === "update") {
718
+ if (update['$pull'] && update['$unset']) {
719
+ result = await arrayObj.updateOne(
720
+ {
721
+ _id: document._id
722
+ },
723
+ {$unset: update['$unset']},
724
+ options
725
+ );
726
+ delete update['$unset']
727
+ }
728
+
729
+ if (options.returnNewDocument) {
730
+ let object =
731
+ await arrayObj.findOneAndUpdate(
732
+ {
733
+ _id: document._id
734
+ },
735
+ update,
736
+ options
737
+ );
738
+ for (let key of Object.keys(
739
+ object
740
+ )) {
741
+ if (key === "_id")
742
+ continue;
743
+ let newArrayKey =
744
+ options.newArray[
745
+ key
746
+ ];
747
+ // TODO: get index based on $operator
748
+ let index =
749
+ object[key].length -
750
+ 1;
751
+ if (index >= 0)
752
+ data[type][i][
753
+ newArrayKey.replace(
754
+ "[]",
755
+ `[${index}]`
756
+ )
757
+ ] =
758
+ data[type][i][
759
+ newArrayKey
760
+ ];
761
+ }
762
+ } else
763
+ result =
764
+ await arrayObj.updateOne(
765
+ {
766
+ _id: document._id
767
+ },
768
+ update,
769
+ options
770
+ );
771
+ // TODO: if update.$push or update.$each read document with projection to get index and update the keys [] to include index
772
+ } else if (method === "delete") {
773
+ result =
774
+ await arrayObj.deleteOne({
775
+ _id: document._id
776
+ });
777
+ }
778
+
779
+ dataTransferedIn +=
780
+ getBytes(result);
781
+ documents.push({
782
+ ...data[type][i],
783
+ ...reference,
784
+ _id: document._id.toString()
785
+ });
786
+ // data[type].push({ ...data[type][i], ...reference, _id: document._id.toString() })
787
+ }
788
+ document = "";
789
+ }
790
+ } catch (error) {
791
+ errorHandler(data, error, database, array);
792
+ }
793
+ }
794
+ }
795
+
796
+ // if (method === 'create') {
797
+ // try {
798
+ // dataTransferedOut += getBytes(data[type])
799
+ // const result = await arrayObj.insertMany(data[type]);
800
+ // dataTransferedIn += getBytes(result)
801
+
802
+ // for (let i = 0; i < data[type].length; i++) {
803
+ // data[type][i]._id = data[type][i]._id.toString()
804
+ // }
805
+ // } catch (error) {
806
+ // errorHandler(data, error, database, array)
807
+ // }
808
+ // }
809
+ }
810
+ }
811
+ data = createData(
812
+ data,
813
+ documents,
814
+ type,
815
+ dataTransferedIn,
816
+ dataTransferedOut
817
+ );
818
+ resolve(data);
819
+ } catch (error) {
820
+ errorHandler(data, error);
821
+ console.log(method, "error", error);
822
+ resolve(data);
823
+ }
824
+ },
825
+ (error) => {
826
+ errorHandler(data, error);
827
+ }
828
+ );
531
829
  }
532
830
 
533
831
  function createUpdate(update, options, data, isGlobal) {
534
- if (data.upsert)
535
- options.upsert = data.upsert
536
- if (data.$upsert)
537
- options.upsert = data.$upsert
538
- if (data.$update)
539
- delete data.$update
540
-
541
- Object.keys(data).forEach(key => {
542
- if (isGlobal && !key.startsWith('$') || key === '_id')
543
- return
544
-
545
- if (isValidDate(data[key]))
546
- data[key] = new Date(data[key])
547
-
548
- let operator
549
- if (key.endsWith(']')) {
550
- const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
551
- var match = key.match(regex);
552
- var index = parseInt(match[2], 10);
553
- if (index === NaN)
554
- operator = match[2]
555
- var arrayKey = match[1].replace(/\[(\d+)\]/g, '.$1');
556
- }
557
-
558
- if (key.startsWith('$'))
559
- operator = key.split('.')[0]
560
- else if (!operator && typeof data[key] === 'string' && data[key].startsWith('$'))
561
- operator = data[key]
562
-
563
- if (!update['$set'])
564
- update['$set'] = {}
565
-
566
- let originalKey = key
567
- key = key.replace(/\[(\d+)\]/g, '.$1');
568
-
569
- if (originalKey.endsWith('[]')) {
570
- if (!options.projection) {
571
- options.projection = {}
572
- options.arrayKey = {}
573
- options.returnNewDocument = true
574
- } else {
575
- options.projection[key.replace(operator + '.', '')] = 1
576
- options.arrayKey[key.replace(operator + '.', '')] = originalKey
577
- }
578
- if (!key.startsWith('$'))
579
- operator = '$push'
580
- if (key.endsWith('[]'))
581
- key = key.replace('[]', '');
582
- }
583
-
584
- let operators = ['$rename', '$inc', '$push', '$each', '$splice', '$unset', '$delete', '$slice', '$pop', '$shift', '$addToSet', '$pull', '$currentDate']
585
- if (!operators.includes(operator) && typeof index !== 'number') {
586
- if (!isGlobal)
587
- update['$set'][key] = data[originalKey]
588
- return
589
- }
590
-
591
- let updates = {}
592
- if (operator === '$rename') {
593
- if (key === '$rename')
594
- for (let oldkey of Object.keys(data[originalKey])) {
595
- key = '$rename.' + oldkey
596
- updates[key] = data[originalKey][oldkey].replace(/\[(\d+)\]/g, '.$1')
597
- }
598
- else
599
- updates[key] = data[originalKey].replace(/\[(\d+)\]/g, '.$1')
600
-
601
- } else if (operator === '$delete' || operator === '$unset' || operator === '$slice') {
602
- operator = '$unset'
603
- updates[key] = 1
604
- if (!updates['$pull'])
605
- updates['$pull'] = {}
606
- updates['$pull'][key] = null
607
- } else if (operator === '$pop') {
608
- key = arrayKey
609
- updates[key] = index || 1
610
- } else if (operator === '$addToSet' || operator === '$pull') {
611
- updates[key] = data[originalKey]
612
- } else if (operator === '$push' || operator === '$each' || typeof index === 'number') {
613
- updates[key] = data[originalKey]
614
- if (typeof index === 'number' && index >= 0) {
615
- if (!operator)
616
- operator = "$set"
617
- else {
618
- if (operator === '$push')
619
- updates[key] = [data[originalKey]]
620
-
621
-
622
- let insert = { $each: updates[key] }
623
- insert.$postion = index
624
- if (index >= 0)
625
- updates[arrayKey] = insert
626
- else
627
- updates[key] = insert
628
- }
629
- }
630
- } else if (operator === '$inc') {
631
- updates[key] = data[originalKey]
632
- } else if (operator === '$currentDate') {
633
- updates[key] = data[originalKey]
634
- }
635
-
636
- if (!update[operator])
637
- update[operator] = {}
638
-
639
- if (key === operator)
640
- update[operator] = { ...update[operator], ...replaceArray(updates[key]) }
641
- else
642
- update[operator][key.replace(operator + '.', '')] = updates[key]
643
- })
832
+ if (data.upsert) options.upsert = data.upsert;
833
+ if (data.$upsert) options.upsert = data.$upsert;
834
+ if (data.$update) delete data.$update;
835
+
836
+ Object.keys(data).forEach((key) => {
837
+ if ((isGlobal && !key.startsWith("$")) || key === "_id") return;
838
+
839
+ if (isValidDate(data[key])) data[key] = new Date(data[key]);
840
+
841
+ let operator;
842
+ if (key.endsWith("]")) {
843
+ const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
844
+ var match = key.match(regex);
845
+ var index = parseInt(match[2], 10);
846
+ if (index === NaN) operator = match[2];
847
+ var arrayKey = match[1].replace(/\[(\d+)\]/g, ".$1");
848
+ }
849
+
850
+ if (key.startsWith("$")) operator = key.split(".")[0];
851
+ else if (
852
+ !operator &&
853
+ typeof data[key] === "string" &&
854
+ data[key].startsWith("$")
855
+ )
856
+ operator = data[key];
857
+
858
+ if (!update["$set"]) update["$set"] = {};
859
+
860
+ let originalKey = key;
861
+ key = key.replace(/\[(\d+)\]/g, ".$1");
862
+
863
+ if (originalKey.endsWith("[]")) {
864
+ if (!options.projection) {
865
+ options.projection = {};
866
+ options.arrayKey = {};
867
+ options.returnNewDocument = true;
868
+ } else {
869
+ options.projection[key.replace(operator + ".", "")] = 1;
870
+ options.arrayKey[key.replace(operator + ".", "")] = originalKey;
871
+ }
872
+ if (!key.startsWith("$")) operator = "$push";
873
+ if (key.endsWith("[]")) key = key.replace("[]", "");
874
+ }
875
+
876
+ let operators = [
877
+ "$rename",
878
+ "$inc",
879
+ "$push",
880
+ "$each",
881
+ "$splice",
882
+ "$unset",
883
+ "$delete",
884
+ "$slice",
885
+ "$pop",
886
+ "$shift",
887
+ "$addToSet",
888
+ "$pull",
889
+ "$currentDate"
890
+ ];
891
+ if (!operators.includes(operator) && typeof index !== "number") {
892
+ if (!isGlobal) update["$set"][key] = data[originalKey];
893
+ return;
894
+ }
895
+
896
+ let updates = {};
897
+ if (operator === "$rename") {
898
+ if (key === "$rename")
899
+ for (let oldkey of Object.keys(data[originalKey])) {
900
+ key = "$rename." + oldkey;
901
+ updates[key] = data[originalKey][oldkey].replace(
902
+ /\[(\d+)\]/g,
903
+ ".$1"
904
+ );
905
+ }
906
+ else updates[key] = data[originalKey].replace(/\[(\d+)\]/g, ".$1");
907
+ } else if (
908
+ operator === "$delete" ||
909
+ operator === "$unset" ||
910
+ operator === "$slice"
911
+ ) {
912
+ operator = "$unset";
913
+ updates[key] = 1;
914
+ // if (!updates["$pull"]) updates["$pull"] = {};
915
+ const pullkey = key.split('.');
916
+ pullkey.shift();
917
+ pullkey.pop();
918
+ // updates["$pull"][pullkey.join('.')] = null;
919
+ // updates["$pull"][pullkey.join('.')] = { $in: [null] };
920
+ if (!update["$pull"]) update["$pull"] = {};
921
+ update["$pull"][pullkey.join('.')] = null;
922
+ } else if (operator === "$pop") {
923
+ key = arrayKey;
924
+ updates[key] = index || 1;
925
+ } else if (operator === "$addToSet" || operator === "$pull") {
926
+ updates[key] = data[originalKey];
927
+ } else if (
928
+ operator === "$push" ||
929
+ operator === "$each" ||
930
+ typeof index === "number"
931
+ ) {
932
+ updates[key] = data[originalKey];
933
+ if (typeof index === "number" && index >= 0) {
934
+ if (!operator) operator = "$set";
935
+ else {
936
+ if (operator === "$push")
937
+ updates[key] = [data[originalKey]];
938
+
939
+ let insert = { $each: updates[key] };
940
+ insert.$postion = index;
941
+ if (index >= 0) updates[arrayKey] = insert;
942
+ else updates[key] = insert;
943
+ }
944
+ }
945
+ } else if (operator === "$inc") {
946
+ updates[key] = data[originalKey];
947
+ } else if (operator === "$currentDate") {
948
+ updates[key] = data[originalKey];
949
+ }
950
+
951
+ if (!update[operator]) update[operator] = {};
952
+
953
+ if (key === operator)
954
+ update[operator] = {
955
+ ...update[operator],
956
+ ...replaceArray(updates[key])
957
+ };
958
+ else update[operator][key.replace(operator + ".", "")] = updates[key];
959
+ });
644
960
  }
645
961
 
646
962
  async function createFilter(data, arrayObj) {
647
- let query = {}, sort = {}, index = 0, limit = 0, count
648
-
649
- if (data.$filter) {
650
- function convertIfDate(value) {
651
- if (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/)) {
652
- return new Date(value);
653
- }
654
- return value;
655
- }
656
-
657
- if (data.$filter.query) {
658
- for (let key in data.$filter.query) {
659
- if (Array.isArray(data.$filter.query[key])) {
660
- // Handle $or operator with an array of conditions
661
- query[key] = data.$filter.query[key].map(condition => {
662
- let newCondition = {};
663
- for (let subKey in condition) {
664
- if (typeof condition[subKey] === 'object' && condition[subKey] !== null) {
665
- newCondition[subKey] = {};
666
- for (let subCondition in condition[subKey]) {
667
- if (subKey == "_id")
668
- newCondition[subKey][subCondition] = ObjectId(condition[subKey][subCondition])
669
- else
670
- newCondition[subKey][subCondition] = convertIfDate(condition[subKey][subCondition]);
671
- }
672
- } else {
673
- if (subKey == "_id")
674
- newCondition[subKey] = ObjectId(condition[subKey])
675
- else
676
- newCondition[subKey] = convertIfDate(condition[subKey]);
677
- }
678
- }
679
- return newCondition;
680
- });
681
- } else if (typeof data.$filter.query[key] === 'object' && data.$filter.query[key] !== null) {
682
- // Handle general object conditions
683
- query[key] = {};
684
- for (let condition in data.$filter.query[key]) {
685
- if (key == "_id")
686
- query[key][condition] = ObjectId(data.$filter.query[key][condition])
687
- else
688
- query[key][condition] = convertIfDate(data.$filter.query[key][condition]);
689
- }
690
- } else {
691
- // Handle direct values
692
- if (key == "_id")
693
- query[key] = ObjectId(data.$filter.query[key])
694
- else
695
- query[key] = convertIfDate(data.$filter.query[key]);
696
- }
697
- }
698
- }
699
-
700
- if (data.$filter.sort) {
701
- for (let i = 0; i < data.$filter.sort.length; i++) {
702
- let direction = data.$filter.sort[i].direction
703
- if (direction == 'desc' || direction == -1)
704
- direction = -1;
705
- else
706
- direction = 1;
707
-
708
- sort[data.$filter.sort[i].key] = direction
709
- }
710
- }
711
-
712
- if (arrayObj) {
713
- count = await arrayObj.estimatedDocumentCount()
714
- data.$filter.count = count
715
- }
716
-
717
- if (data.$filter.index)
718
- index = data.$filter.index
719
- if (data.$filter.limit)
720
- limit = data.$filter.limit
721
- }
722
-
723
- if (data['organization_id'])
724
- query['organization_id'] = data['organization_id']
725
-
726
- return { query, sort, index, limit, count }
963
+ let query = {},
964
+ sort = {},
965
+ index = 0,
966
+ limit = 0,
967
+ count;
968
+
969
+ if (data.$filter) {
970
+ function convertIfDate(value) {
971
+ if (
972
+ typeof value === "string" &&
973
+ value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/)
974
+ ) {
975
+ return new Date(value);
976
+ }
977
+ return value;
978
+ }
979
+
980
+ if (data.$filter.query) {
981
+ for (let key in data.$filter.query) {
982
+ if (Array.isArray(data.$filter.query[key])) {
983
+ // Handle $or operator with an array of conditions
984
+ query[key] = data.$filter.query[key].map((condition) => {
985
+ let newCondition = {};
986
+ for (let subKey in condition) {
987
+ if (
988
+ typeof condition[subKey] === "object" &&
989
+ condition[subKey] !== null
990
+ ) {
991
+ newCondition[subKey] = {};
992
+ for (let subCondition in condition[subKey]) {
993
+ if (subKey == "_id")
994
+ newCondition[subKey][subCondition] =
995
+ ObjectId(
996
+ condition[subKey][subCondition]
997
+ );
998
+ else
999
+ newCondition[subKey][subCondition] =
1000
+ convertIfDate(
1001
+ condition[subKey][subCondition]
1002
+ );
1003
+ }
1004
+ } else {
1005
+ if (subKey == "_id")
1006
+ newCondition[subKey] = ObjectId(
1007
+ condition[subKey]
1008
+ );
1009
+ else
1010
+ newCondition[subKey] = convertIfDate(
1011
+ condition[subKey]
1012
+ );
1013
+ }
1014
+ }
1015
+ return newCondition;
1016
+ });
1017
+ } else if (
1018
+ typeof data.$filter.query[key] === "object" &&
1019
+ data.$filter.query[key] !== null
1020
+ ) {
1021
+ // Handle general object conditions
1022
+ query[key] = {};
1023
+ for (let condition in data.$filter.query[key]) {
1024
+ if (key == "_id")
1025
+ query[key][condition] = ObjectId(
1026
+ data.$filter.query[key][condition]
1027
+ );
1028
+ else
1029
+ query[key][condition] = convertIfDate(
1030
+ data.$filter.query[key][condition]
1031
+ );
1032
+ }
1033
+ } else {
1034
+ // Handle direct values
1035
+ if (key == "_id")
1036
+ query[key] = ObjectId(data.$filter.query[key]);
1037
+ else query[key] = convertIfDate(data.$filter.query[key]);
1038
+ }
1039
+ }
1040
+ }
1041
+
1042
+ if (data.$filter.sort) {
1043
+ for (let i = 0; i < data.$filter.sort.length; i++) {
1044
+ let direction = data.$filter.sort[i].direction;
1045
+ if (direction == "desc" || direction == -1) direction = -1;
1046
+ else direction = 1;
1047
+
1048
+ sort[data.$filter.sort[i].key] = direction;
1049
+ }
1050
+ }
1051
+
1052
+ if (arrayObj) {
1053
+ count = await arrayObj.estimatedDocumentCount();
1054
+ data.$filter.count = count;
1055
+ }
1056
+
1057
+ if (data.$filter.index) index = data.$filter.index;
1058
+ if (data.$filter.limit) limit = data.$filter.limit;
1059
+ }
1060
+
1061
+ if (data["organization_id"])
1062
+ query["organization_id"] = data["organization_id"];
1063
+
1064
+ return { query, sort, index, limit, count };
727
1065
  }
728
1066
 
729
1067
  function parseRegExp(regExpString) {
730
- let matches = regExpString.match(/\/(.*)\/(.*)/);
731
- return {
732
- pattern: matches[1],
733
- options: matches[2]
734
- };
1068
+ let matches = regExpString.match(/\/(.*)\/(.*)/);
1069
+ return {
1070
+ pattern: matches[1],
1071
+ options: matches[2]
1072
+ };
735
1073
  }
736
1074
 
737
1075
  function createProjection(data) {
738
- let projection = {}
1076
+ let projection = {};
739
1077
 
740
- Object.keys(data).forEach((key) => {
741
- if (!['_id', 'organization_id'].includes(key) && !key.startsWith('$'))
742
- projection[key.replace(/\[(\d+)\]/g, '.$1')] = 1
743
- });
1078
+ Object.keys(data).forEach((key) => {
1079
+ if (!["_id", "organization_id"].includes(key) && !key.startsWith("$"))
1080
+ projection[key.replace(/\[(\d+)\]/g, ".$1")] = 1;
1081
+ });
744
1082
 
745
- return projection;
1083
+ return projection;
746
1084
  }
747
1085
 
748
1086
  function replaceArray(data = {}) {
749
- let object = {}
1087
+ let object = {};
750
1088
 
751
- Object.keys(data).forEach((key) => {
752
- object[key.replace(/\[(\d+)\]/g, '.$1')] = data[key]
753
- });
1089
+ Object.keys(data).forEach((key) => {
1090
+ object[key.replace(/\[(\d+)\]/g, ".$1")] = data[key];
1091
+ });
754
1092
 
755
- return object;
1093
+ return object;
756
1094
  }
757
1095
 
758
1096
  function createData(data, array, type, dataTransferedIn, dataTransferedOut) {
759
- if (dataTransferedIn) {
760
- process.emit("setBandwidth", {
761
- type: 'in',
762
- data: dataTransferedIn,
763
- organization_id: data.organization_id
764
- });
765
- }
766
-
767
- if (dataTransferedOut) {
768
- process.emit("setBandwidth", {
769
- type: 'out',
770
- data: dataTransferedOut,
771
- organization_id: data.organization_id
772
- });
773
- }
774
-
775
- if (data[type] && data[type][0] && data[type][0].isFilter === 'isEmptyObjectFilter') {
776
- data[type].shift()
777
- data.isFilter = true
778
- }
779
-
780
- // if (!data.request)
781
- // data.request = data[type] || {}
782
-
783
- let key = '_id'
784
- if (type !== 'object')
785
- key = 'name'
786
-
787
- // TODO: handle case where data[type] is not an array
788
- if (!Array.isArray(data[type]))
789
- console.log('data[type] is not an array', type)
790
- else {
791
- for (let i = 0; i < array.length; i++) {
792
- const matchIndex = data[type].findIndex((item) => item[key] === array[i][key]);
793
- if (matchIndex !== -1) {
794
- for (let $type of ['$storage', '$database', '$array']) {
795
- if (!data[type][matchIndex][$type])
796
- data[type][matchIndex][$type] = []
797
- if (!Array.isArray(data[type][matchIndex][$type])) {
798
- data[type][matchIndex][$type] = [data[type][matchIndex][$type]]
799
- if (!data[type][matchIndex][$type].includes(array[i][$type])) {
800
- data[type][matchIndex][$type].push(array[i][$type])
801
- }
802
- } else {
803
- data[type][matchIndex][$type].push(array[i][$type])
804
- }
805
- delete array[i][$type]
806
- }
807
-
808
- // TODO: compare dates and merge and and updates to keep all synced and up to date
809
- data[type][matchIndex] = { ...data[type][matchIndex], ...array[i] };
810
- } else
811
- data[type].push(array[i])
812
- }
813
- }
814
-
815
- return data
1097
+ if (dataTransferedIn) {
1098
+ process.emit("setBandwidth", {
1099
+ type: "in",
1100
+ data: dataTransferedIn,
1101
+ organization_id: data.organization_id
1102
+ });
1103
+ }
1104
+
1105
+ if (dataTransferedOut) {
1106
+ process.emit("setBandwidth", {
1107
+ type: "out",
1108
+ data: dataTransferedOut,
1109
+ organization_id: data.organization_id
1110
+ });
1111
+ }
1112
+
1113
+ if (
1114
+ data[type] &&
1115
+ data[type][0] &&
1116
+ data[type][0].isFilter === "isEmptyObjectFilter"
1117
+ ) {
1118
+ data[type].shift();
1119
+ data.isFilter = true;
1120
+ }
1121
+
1122
+ // if (!data.request)
1123
+ // data.request = data[type] || {}
1124
+
1125
+ let key = "_id";
1126
+ if (type !== "object") key = "name";
1127
+
1128
+ // TODO: handle case where data[type] is not an array
1129
+ if (!Array.isArray(data[type]))
1130
+ console.log("data[type] is not an array", type);
1131
+ else {
1132
+ for (let i = 0; i < array.length; i++) {
1133
+ const matchIndex = data[type].findIndex(
1134
+ (item) => item[key] === array[i][key]
1135
+ );
1136
+ if (matchIndex !== -1) {
1137
+ for (let $type of ["$storage", "$database", "$array"]) {
1138
+ if (!data[type][matchIndex][$type])
1139
+ data[type][matchIndex][$type] = [];
1140
+ if (!Array.isArray(data[type][matchIndex][$type])) {
1141
+ data[type][matchIndex][$type] = [
1142
+ data[type][matchIndex][$type]
1143
+ ];
1144
+ if (
1145
+ !data[type][matchIndex][$type].includes(
1146
+ array[i][$type]
1147
+ )
1148
+ ) {
1149
+ data[type][matchIndex][$type].push(array[i][$type]);
1150
+ }
1151
+ } else {
1152
+ data[type][matchIndex][$type].push(array[i][$type]);
1153
+ }
1154
+ delete array[i][$type];
1155
+ }
1156
+
1157
+ // TODO: compare dates and merge and and updates to keep all synced and up to date
1158
+ data[type][matchIndex] = {
1159
+ ...data[type][matchIndex],
1160
+ ...array[i]
1161
+ };
1162
+ } else data[type].push(array[i]);
1163
+ }
1164
+ }
1165
+
1166
+ return data;
816
1167
  }
817
1168
 
818
1169
  function getBytes(data) {
819
- const jsonString = JSON.stringify(data);
820
- return Buffer.byteLength(jsonString, 'utf8');
1170
+ const jsonString = JSON.stringify(data);
1171
+ return Buffer.byteLength(jsonString, "utf8");
821
1172
  }
822
1173
 
823
1174
  function errorHandler(data, error, database, array) {
824
- let errorMessage = typeof error === 'object' && error.message ? error.message : error;
825
-
826
- let errorObject = {
827
- message: errorMessage,
828
- storage: 'mongodb'
829
- };
830
-
831
- if (database)
832
- errorObject.database = database;
833
- if (array)
834
- errorObject.array = array;
835
-
836
- if (Array.isArray(data.error)) {
837
- data.error.push(errorObject);
838
- } else {
839
- data.error = [errorObject];
840
- }
1175
+ let errorMessage =
1176
+ typeof error === "object" && error.message ? error.message : error;
1177
+
1178
+ let errorObject = {
1179
+ message: errorMessage,
1180
+ storage: "mongodb"
1181
+ };
1182
+
1183
+ if (database) errorObject.database = database;
1184
+ if (array) errorObject.array = array;
1185
+
1186
+ if (Array.isArray(data.error)) {
1187
+ data.error.push(errorObject);
1188
+ } else {
1189
+ data.error = [errorObject];
1190
+ }
841
1191
  }
842
1192
 
843
- module.exports = { send }
1193
+ module.exports = { send };