@cocreate/mongodb 1.20.0 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +1 -1
  3. package/src/index.js +1152 -801
package/src/index.js CHANGED
@@ -1,843 +1,1194 @@
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 (data.$filter && data.$filter.key)
378
+ projection = data.$filter.key
379
+
380
+ if (method === "update")
381
+ createUpdate(update, options, data, true);
382
+
383
+ for (let i = 0; i < data[type].length; i++) {
384
+ let $storage = data[type][i].$storage || [];
385
+ let $database = data[type][i].$database || [];
386
+ let $array = data[type][i].$array || [];
387
+
388
+ if (!Array.isArray($storage))
389
+ $storage = [data[type][i].$storage];
390
+ if (!Array.isArray($database))
391
+ $database = [data[type][i].$database];
392
+ if (!Array.isArray($array))
393
+ $array = [data[type][i].$array];
394
+
395
+ if (!$storage.includes(data.storageName))
396
+ $storage.push(data.storageName);
397
+ if (!$database.includes(database))
398
+ $database.push(database);
399
+ if (!$array.includes(array)) $array.push(array);
400
+
401
+ delete data[type][i].$storage;
402
+ delete data[type][i].$database;
403
+ delete data[type][i].$array;
404
+
405
+ if (method !== "create" && data[type][i].$filter) {
406
+ isFilter = true;
407
+ reference["$filter"] = data[type][i].$filter;
408
+ filter = await createFilter(
409
+ { $filter: data[type][i].$filter },
410
+ arrayObj
411
+ );
412
+ }
413
+
414
+ let { query, sort, index, limit } = filter;
415
+
416
+ if (method === "create") {
417
+ data[type][i] = replaceArray(data[type][i]);
418
+ data[type][i] = dotNotationToObject(
419
+ data[type][i]
420
+ );
421
+ data[type][i]["organization_id"] =
422
+ data["organization_id"];
423
+ data[type][i]["created"] = {
424
+ on: new Date(data.timeStamp),
425
+ by: data.user_id || data.clientId
426
+ };
427
+ } else if (method === "read") {
428
+ // projection = createProjection(projection, data[type][i]);
429
+ } else if (method === "update") {
430
+ if (!data[type][i].modified)
431
+ data[type][i].modified = {
432
+ on: new Date(data.timeStamp),
433
+ by: data.user_id || data.clientId
434
+ };
435
+ else
436
+ data[type][i].modified.on = new Date(
437
+ data[type][i].modified.on
438
+ );
439
+
440
+ data[type][i].organization_id =
441
+ data.organization_id;
442
+ createUpdate(update, options, data[type][i]);
443
+ }
444
+
445
+ if (data[type][i]._id || method === "create") {
446
+ if (method !== "create") {
447
+ try {
448
+ query._id = ObjectId(data[type][i]._id);
449
+ } catch (error) {
450
+ if (
451
+ method === "update" &&
452
+ options.upsert
453
+ ) {
454
+ data[type][i]._id = ObjectId();
455
+ query._id = data[type][i]._id;
456
+ } else {
457
+ errorHandler(
458
+ data,
459
+ error,
460
+ database,
461
+ array
462
+ );
463
+ continue;
464
+ }
465
+ }
466
+ }
467
+
468
+ try {
469
+ dataTransferedOut += getBytes({
470
+ query,
471
+ update,
472
+ projection,
473
+ options
474
+ });
475
+
476
+ let result;
477
+ if (method === "create") {
478
+ if (data[type][i]._id) {
479
+ try {
480
+ data[type][i]._id =
481
+ new ObjectId(
482
+ data[type][i]._id
483
+ );
484
+ } catch (error) {
485
+ delete data[type][i]._id;
486
+ }
487
+ }
488
+ result = await arrayObj.insertOne(
489
+ data[type][i]
490
+ );
491
+ // TODO: type error occuring when pushing the item pushes but throws an error
492
+ data[type][i]._id =
493
+ result.insertedId.toString();
494
+ // documents.push({ ...data[type][i], ...reference })
495
+ } else if (method === "read") {
496
+ result = await arrayObj.findOne(
497
+ query,
498
+ {projection}
499
+ );
500
+ if (result)
501
+ result._id = result._id.toString();
502
+
503
+ if (
504
+ data[type][i].$storage &&
505
+ data[type][i].modified &&
506
+ data[type][i].modified.on
507
+ ) {
508
+ if (!result) {
509
+ result =
510
+ await arrayObj.insertOne(
511
+ data[type][i]
512
+ );
513
+ data[type][i]._id =
514
+ result.insertedId.toString();
515
+ } else if (
516
+ result &&
517
+ new Date(
518
+ data[type][i].modified.on
519
+ ) > new Date(result.modified.on)
520
+ ) {
521
+ data[type][i] = {
522
+ ...result,
523
+ ...data[type][i]
524
+ };
525
+ createUpdate(
526
+ update,
527
+ options,
528
+ data[type][i]
529
+ );
530
+ result =
531
+ await arrayObj.updateOne(
532
+ query,
533
+ update,
534
+ options
535
+ );
536
+ } else
537
+ data[type][i] = {
538
+ ...data[type][i],
539
+ ...result
540
+ };
541
+ } else if (result)
542
+ data[type][i] = {
543
+ ...data[type][i],
544
+ ...result
545
+ };
546
+ else {
547
+ data[type].splice(i, 1);
548
+ continue;
549
+ }
550
+ } else if (method === "update") {
551
+ if (update['$pull'] && update['$unset']) {
552
+ result = await arrayObj.updateOne(
553
+ query,
554
+ {$unset: update['$unset']},
555
+ options
556
+ );
557
+ delete update['$unset']
558
+ }
559
+ result = await arrayObj.updateOne(
560
+ query,
561
+ update,
562
+ options
563
+ );
564
+
565
+ // TODO: handle upsert false and id does not exist
566
+ data[type][i]._id =
567
+ query._id.toString();
568
+ // documents.push({ ...data[type][i], ...reference })
569
+ } else if (method === "delete") {
570
+ result = await arrayObj.deleteOne(
571
+ query
572
+ );
573
+ // documents.push({ ...reference, _id: data[type][i]._id })
574
+ }
575
+
576
+ data[type][i].$storage = $storage;
577
+ data[type][i].$database = $database;
578
+ data[type][i].$array = $array;
579
+
580
+ dataTransferedIn += getBytes(result);
581
+ } catch (error) {
582
+ errorHandler(data, error, database, array);
583
+ }
584
+ } else if (isFilter) {
585
+ try {
586
+ // TODO: index is 1 if indexeddb already returned an item interfering with query
587
+ // if (data.array === "keys")
588
+ // index = 0
589
+
590
+ if (method === "read")
591
+ projection = {
592
+ ...projections,
593
+ ...projection
594
+ };
595
+
596
+ if (
597
+ data.$filter &&
598
+ data.$filter.startingIndex >= 0
599
+ )
600
+ index = data.$filter.startingIndex;
601
+
602
+ dataTransferedOut += getBytes({
603
+ query,
604
+ projection,
605
+ sort,
606
+ index,
607
+ limit
608
+ });
609
+
610
+ let cursor,
611
+ document = "";
612
+ if (Object.keys(sort).length > 0)
613
+ cursor = arrayObj
614
+ .find(query, {projection})
615
+ .sort(sort)
616
+ .skip(index)
617
+ .limit(limit)
618
+ .allowDiskUse(true);
619
+ else
620
+ cursor = arrayObj
621
+ .find(query, {projection})
622
+ .sort(sort)
623
+ .skip(index)
624
+ .limit(limit);
625
+
626
+ if (
627
+ !(await cursor.hasNext()) &&
628
+ method === "update" &&
629
+ data.upsert
630
+ )
631
+ document = {
632
+ _id: ObjectId(data[type][i]._id)
633
+ };
634
+
635
+ while (
636
+ (await cursor.hasNext()) ||
637
+ document
638
+ ) {
639
+ if (!document)
640
+ document = await cursor.next();
641
+
642
+ dataTransferedIn += getBytes(document);
643
+
644
+ if (
645
+ data.$filter &&
646
+ data.$filter.search
647
+ ) {
648
+ let isMatch = searchData(
649
+ document,
650
+ data.$filter.search
651
+ );
652
+ if (!isMatch) continue;
653
+ }
654
+
655
+ if (method === "read") {
656
+ document._id =
657
+ document._id.toString();
658
+ let object = data[type].find(
659
+ (obj) =>
660
+ obj._id &&
661
+ obj._id.toString() ===
662
+ document._id.toString()
663
+ );
664
+ if (object) {
665
+ if (
666
+ object.$storage &&
667
+ object.modified &&
668
+ object.modified.on
669
+ ) {
670
+ if (
671
+ document &&
672
+ document.modified &&
673
+ new Date(
674
+ object.modified.on
675
+ ) >
676
+ new Date(
677
+ document.modified.on
678
+ )
679
+ ) {
680
+ object = {
681
+ ...document,
682
+ ...object
683
+ };
684
+ createUpdate(
685
+ update,
686
+ options,
687
+ object
688
+ );
689
+ document =
690
+ await arrayObj.updateOne(
691
+ query,
692
+ update,
693
+ options
694
+ );
695
+ dataTransferedIn +=
696
+ getBytes(document);
697
+ } else
698
+ documents.push({
699
+ ...document,
700
+ ...reference
701
+ });
702
+ } else
703
+ documents.push({
704
+ ...document,
705
+ ...reference
706
+ });
707
+ } else
708
+ documents.push({
709
+ ...document,
710
+ ...reference
711
+ });
712
+ } else {
713
+ dataTransferedOut += getBytes({
714
+ _id: document._id,
715
+ update,
716
+ options
717
+ });
718
+
719
+ let result;
720
+ if (method === "update") {
721
+ if (update['$pull'] && update['$unset']) {
722
+ result = await arrayObj.updateOne(
723
+ {
724
+ _id: document._id
725
+ },
726
+ {$unset: update['$unset']},
727
+ options
728
+ );
729
+ delete update['$unset']
730
+ }
731
+
732
+ if (options.returnNewDocument) {
733
+ let object =
734
+ await arrayObj.findOneAndUpdate(
735
+ {
736
+ _id: document._id
737
+ },
738
+ update,
739
+ options
740
+ );
741
+ for (let key of Object.keys(
742
+ object
743
+ )) {
744
+ if (key === "_id")
745
+ continue;
746
+ let newArrayKey =
747
+ options.newArray[
748
+ key
749
+ ];
750
+ // TODO: get index based on $operator
751
+ let index =
752
+ object[key].length -
753
+ 1;
754
+ if (index >= 0)
755
+ data[type][i][
756
+ newArrayKey.replace(
757
+ "[]",
758
+ `[${index}]`
759
+ )
760
+ ] =
761
+ data[type][i][
762
+ newArrayKey
763
+ ];
764
+ }
765
+ } else
766
+ result =
767
+ await arrayObj.updateOne(
768
+ {
769
+ _id: document._id
770
+ },
771
+ update,
772
+ options
773
+ );
774
+ // TODO: if update.$push or update.$each read document with projection to get index and update the keys [] to include index
775
+ } else if (method === "delete") {
776
+ result =
777
+ await arrayObj.deleteOne({
778
+ _id: document._id
779
+ });
780
+ }
781
+
782
+ dataTransferedIn +=
783
+ getBytes(result);
784
+ documents.push({
785
+ ...data[type][i],
786
+ ...reference,
787
+ _id: document._id.toString()
788
+ });
789
+ // data[type].push({ ...data[type][i], ...reference, _id: document._id.toString() })
790
+ }
791
+ document = "";
792
+ }
793
+ } catch (error) {
794
+ errorHandler(data, error, database, array);
795
+ }
796
+ }
797
+ }
798
+
799
+ // if (method === 'create') {
800
+ // try {
801
+ // dataTransferedOut += getBytes(data[type])
802
+ // const result = await arrayObj.insertMany(data[type]);
803
+ // dataTransferedIn += getBytes(result)
804
+
805
+ // for (let i = 0; i < data[type].length; i++) {
806
+ // data[type][i]._id = data[type][i]._id.toString()
807
+ // }
808
+ // } catch (error) {
809
+ // errorHandler(data, error, database, array)
810
+ // }
811
+ // }
812
+ }
813
+ }
814
+ data = createData(
815
+ data,
816
+ documents,
817
+ type,
818
+ dataTransferedIn,
819
+ dataTransferedOut
820
+ );
821
+ resolve(data);
822
+ } catch (error) {
823
+ errorHandler(data, error);
824
+ console.log(method, "error", error);
825
+ resolve(data);
826
+ }
827
+ },
828
+ (error) => {
829
+ errorHandler(data, error);
830
+ }
831
+ );
531
832
  }
532
833
 
533
834
  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
- })
835
+ if (data.upsert) options.upsert = data.upsert;
836
+ if (data.$upsert) options.upsert = data.$upsert;
837
+ if (data.$update) delete data.$update;
838
+
839
+ Object.keys(data).forEach((key) => {
840
+ if ((isGlobal && !key.startsWith("$")) || key === "_id") return;
841
+
842
+ if (isValidDate(data[key])) data[key] = new Date(data[key]);
843
+
844
+ let operator;
845
+ if (key.endsWith("]")) {
846
+ const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
847
+ var match = key.match(regex);
848
+ var index = parseInt(match[2], 10);
849
+ if (index === NaN) operator = match[2];
850
+ var arrayKey = match[1].replace(/\[(\d+)\]/g, ".$1");
851
+ }
852
+
853
+ if (key.startsWith("$")) operator = key.split(".")[0];
854
+ else if (
855
+ !operator &&
856
+ typeof data[key] === "string" &&
857
+ data[key].startsWith("$")
858
+ )
859
+ operator = data[key];
860
+
861
+ if (!update["$set"]) update["$set"] = {};
862
+
863
+ let originalKey = key;
864
+ key = key.replace(/\[(\d+)\]/g, ".$1");
865
+
866
+ if (originalKey.endsWith("[]")) {
867
+ if (!options.projection) {
868
+ options.projection = {};
869
+ options.arrayKey = {};
870
+ options.returnNewDocument = true;
871
+ } else {
872
+ options.projection[key.replace(operator + ".", "")] = 1;
873
+ options.arrayKey[key.replace(operator + ".", "")] = originalKey;
874
+ }
875
+ if (!key.startsWith("$")) operator = "$push";
876
+ if (key.endsWith("[]")) key = key.replace("[]", "");
877
+ }
878
+
879
+ let operators = [
880
+ "$rename",
881
+ "$inc",
882
+ "$push",
883
+ "$each",
884
+ "$splice",
885
+ "$unset",
886
+ "$delete",
887
+ "$slice",
888
+ "$pop",
889
+ "$shift",
890
+ "$addToSet",
891
+ "$pull",
892
+ "$currentDate"
893
+ ];
894
+ if (!operators.includes(operator) && typeof index !== "number") {
895
+ if (!isGlobal) update["$set"][key] = data[originalKey];
896
+ return;
897
+ }
898
+
899
+ let updates = {};
900
+ if (operator === "$rename") {
901
+ if (key === "$rename")
902
+ for (let oldkey of Object.keys(data[originalKey])) {
903
+ key = "$rename." + oldkey;
904
+ updates[key] = data[originalKey][oldkey].replace(
905
+ /\[(\d+)\]/g,
906
+ ".$1"
907
+ );
908
+ }
909
+ else updates[key] = data[originalKey].replace(/\[(\d+)\]/g, ".$1");
910
+ } else if (
911
+ operator === "$delete" ||
912
+ operator === "$unset" ||
913
+ operator === "$slice"
914
+ ) {
915
+ operator = "$unset";
916
+ updates[key] = 1;
917
+ // if (!updates["$pull"]) updates["$pull"] = {};
918
+ const pullkey = key.split('.');
919
+ pullkey.shift();
920
+ pullkey.pop();
921
+ // updates["$pull"][pullkey.join('.')] = null;
922
+ // updates["$pull"][pullkey.join('.')] = { $in: [null] };
923
+ if (!update["$pull"]) update["$pull"] = {};
924
+ update["$pull"][pullkey.join('.')] = null;
925
+ } else if (operator === "$pop") {
926
+ key = arrayKey;
927
+ updates[key] = index || 1;
928
+ } else if (operator === "$addToSet" || operator === "$pull") {
929
+ updates[key] = data[originalKey];
930
+ } else if (
931
+ operator === "$push" ||
932
+ operator === "$each" ||
933
+ typeof index === "number"
934
+ ) {
935
+ updates[key] = data[originalKey];
936
+ if (typeof index === "number" && index >= 0) {
937
+ if (!operator) operator = "$set";
938
+ else {
939
+ if (operator === "$push")
940
+ updates[key] = [data[originalKey]];
941
+
942
+ let insert = { $each: updates[key] };
943
+ insert.$postion = index;
944
+ if (index >= 0) updates[arrayKey] = insert;
945
+ else updates[key] = insert;
946
+ }
947
+ }
948
+ } else if (operator === "$inc") {
949
+ updates[key] = data[originalKey];
950
+ } else if (operator === "$currentDate") {
951
+ updates[key] = data[originalKey];
952
+ }
953
+
954
+ if (!update[operator]) update[operator] = {};
955
+
956
+ if (key === operator)
957
+ update[operator] = {
958
+ ...update[operator],
959
+ ...replaceArray(updates[key])
960
+ };
961
+ else update[operator][key.replace(operator + ".", "")] = updates[key];
962
+ });
644
963
  }
645
964
 
646
965
  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 }
966
+ let query = {},
967
+ sort = {},
968
+ index = 0,
969
+ limit = 0,
970
+ count;
971
+
972
+ if (data.$filter) {
973
+ function convertIfDate(value) {
974
+ if (
975
+ typeof value === "string" &&
976
+ value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/)
977
+ ) {
978
+ return new Date(value);
979
+ }
980
+ return value;
981
+ }
982
+
983
+ if (data.$filter.query) {
984
+ for (let key in data.$filter.query) {
985
+ if (Array.isArray(data.$filter.query[key])) {
986
+ // Handle $or operator with an array of conditions
987
+ query[key] = data.$filter.query[key].map((condition) => {
988
+ let newCondition = {};
989
+ for (let subKey in condition) {
990
+ if (
991
+ typeof condition[subKey] === "object" &&
992
+ condition[subKey] !== null
993
+ ) {
994
+ newCondition[subKey] = {};
995
+ for (let subCondition in condition[subKey]) {
996
+ if (subKey == "_id")
997
+ newCondition[subKey][subCondition] =
998
+ ObjectId(
999
+ condition[subKey][subCondition]
1000
+ );
1001
+ else
1002
+ newCondition[subKey][subCondition] =
1003
+ convertIfDate(
1004
+ condition[subKey][subCondition]
1005
+ );
1006
+ }
1007
+ } else {
1008
+ if (subKey == "_id")
1009
+ newCondition[subKey] = ObjectId(
1010
+ condition[subKey]
1011
+ );
1012
+ else
1013
+ newCondition[subKey] = convertIfDate(
1014
+ condition[subKey]
1015
+ );
1016
+ }
1017
+ }
1018
+ return newCondition;
1019
+ });
1020
+ } else if (
1021
+ typeof data.$filter.query[key] === "object" &&
1022
+ data.$filter.query[key] !== null
1023
+ ) {
1024
+ // Handle general object conditions
1025
+ query[key] = {};
1026
+ for (let condition in data.$filter.query[key]) {
1027
+ if (key == "_id")
1028
+ query[key][condition] = ObjectId(
1029
+ data.$filter.query[key][condition]
1030
+ );
1031
+ else
1032
+ query[key][condition] = convertIfDate(
1033
+ data.$filter.query[key][condition]
1034
+ );
1035
+ }
1036
+ } else {
1037
+ // Handle direct values
1038
+ if (key == "_id")
1039
+ query[key] = ObjectId(data.$filter.query[key]);
1040
+ else query[key] = convertIfDate(data.$filter.query[key]);
1041
+ }
1042
+ }
1043
+ }
1044
+
1045
+ if (data.$filter.sort) {
1046
+ for (let i = 0; i < data.$filter.sort.length; i++) {
1047
+ let direction = data.$filter.sort[i].direction;
1048
+ if (direction == "desc" || direction == -1) direction = -1;
1049
+ else direction = 1;
1050
+
1051
+ sort[data.$filter.sort[i].key] = direction;
1052
+ }
1053
+ }
1054
+
1055
+ if (arrayObj) {
1056
+ count = await arrayObj.estimatedDocumentCount();
1057
+ data.$filter.count = count;
1058
+ }
1059
+
1060
+ if (data.$filter.index) index = data.$filter.index;
1061
+ if (data.$filter.limit) limit = data.$filter.limit;
1062
+ }
1063
+
1064
+ if (data["organization_id"])
1065
+ query["organization_id"] = data["organization_id"];
1066
+
1067
+ return { query, sort, index, limit, count };
727
1068
  }
728
1069
 
729
1070
  function parseRegExp(regExpString) {
730
- let matches = regExpString.match(/\/(.*)\/(.*)/);
731
- return {
732
- pattern: matches[1],
733
- options: matches[2]
734
- };
1071
+ let matches = regExpString.match(/\/(.*)\/(.*)/);
1072
+ return {
1073
+ pattern: matches[1],
1074
+ options: matches[2]
1075
+ };
735
1076
  }
736
1077
 
737
- function createProjection(data) {
738
- let projection = {}
739
-
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
+ function createProjection(projection, data) {
1079
+ Object.keys(data).forEach((key) => {
1080
+ if (!["_id", "organization_id", "isFIlter"].includes(key) && !key.startsWith("$"))
1081
+ projection[key.replace(/\[(\d+)\]/g, ".$1")] = 1;
1082
+ });
744
1083
 
745
- return projection;
1084
+ return projection;
746
1085
  }
747
1086
 
748
1087
  function replaceArray(data = {}) {
749
- let object = {}
1088
+ let object = {};
750
1089
 
751
- Object.keys(data).forEach((key) => {
752
- object[key.replace(/\[(\d+)\]/g, '.$1')] = data[key]
753
- });
1090
+ Object.keys(data).forEach((key) => {
1091
+ object[key.replace(/\[(\d+)\]/g, ".$1")] = data[key];
1092
+ });
754
1093
 
755
- return object;
1094
+ return object;
756
1095
  }
757
1096
 
758
1097
  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
1098
+ if (dataTransferedIn) {
1099
+ process.emit("setBandwidth", {
1100
+ type: "in",
1101
+ data: dataTransferedIn,
1102
+ organization_id: data.organization_id
1103
+ });
1104
+ }
1105
+
1106
+ if (dataTransferedOut) {
1107
+ process.emit("setBandwidth", {
1108
+ type: "out",
1109
+ data: dataTransferedOut,
1110
+ organization_id: data.organization_id
1111
+ });
1112
+ }
1113
+
1114
+ if (
1115
+ data[type] &&
1116
+ data[type][0] &&
1117
+ data[type][0].isFilter === "isEmptyObjectFilter"
1118
+ ) {
1119
+ data[type].shift();
1120
+ data.isFilter = true;
1121
+ }
1122
+
1123
+ // if (!data.request)
1124
+ // data.request = data[type] || {}
1125
+
1126
+ let key = "_id";
1127
+ if (type !== "object") key = "name";
1128
+
1129
+ // TODO: handle case where data[type] is not an array
1130
+ if (!Array.isArray(data[type]))
1131
+ console.log("data[type] is not an array", type);
1132
+ else {
1133
+ for (let i = 0; i < array.length; i++) {
1134
+ const matchIndex = data[type].findIndex(
1135
+ (item) => item[key] === array[i][key]
1136
+ );
1137
+ if (matchIndex !== -1) {
1138
+ for (let $type of ["$storage", "$database", "$array"]) {
1139
+ if (!data[type][matchIndex][$type])
1140
+ data[type][matchIndex][$type] = [];
1141
+ if (!Array.isArray(data[type][matchIndex][$type])) {
1142
+ data[type][matchIndex][$type] = [
1143
+ data[type][matchIndex][$type]
1144
+ ];
1145
+ if (
1146
+ !data[type][matchIndex][$type].includes(
1147
+ array[i][$type]
1148
+ )
1149
+ ) {
1150
+ data[type][matchIndex][$type].push(array[i][$type]);
1151
+ }
1152
+ } else {
1153
+ data[type][matchIndex][$type].push(array[i][$type]);
1154
+ }
1155
+ delete array[i][$type];
1156
+ }
1157
+
1158
+ // TODO: compare dates and merge and and updates to keep all synced and up to date
1159
+ data[type][matchIndex] = {
1160
+ ...data[type][matchIndex],
1161
+ ...array[i]
1162
+ };
1163
+ } else data[type].push(array[i]);
1164
+ }
1165
+ }
1166
+
1167
+ return data;
816
1168
  }
817
1169
 
818
1170
  function getBytes(data) {
819
- const jsonString = JSON.stringify(data);
820
- return Buffer.byteLength(jsonString, 'utf8');
1171
+ const jsonString = JSON.stringify(data);
1172
+ return Buffer.byteLength(jsonString, "utf8");
821
1173
  }
822
1174
 
823
1175
  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
- }
1176
+ let errorMessage =
1177
+ typeof error === "object" && error.message ? error.message : error;
1178
+
1179
+ let errorObject = {
1180
+ message: errorMessage,
1181
+ storage: "mongodb"
1182
+ };
1183
+
1184
+ if (database) errorObject.database = database;
1185
+ if (array) errorObject.array = array;
1186
+
1187
+ if (Array.isArray(data.error)) {
1188
+ data.error.push(errorObject);
1189
+ } else {
1190
+ data.error = [errorObject];
1191
+ }
841
1192
  }
842
1193
 
843
- module.exports = { send }
1194
+ module.exports = { send };