@cocreate/mongodb 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/package.json +5 -5
- package/src/array.js +201 -0
- package/src/database.js +110 -0
- package/src/index.js +20 -918
- package/src/object.js +509 -0
- package/src/utilities.js +296 -0
package/src/index.js
CHANGED
|
@@ -1,40 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
MongoClient.connect(data.storageUrl);
|
|
22
|
-
|
|
23
|
-
organizations[data.organization_id][data.storageUrl] =
|
|
24
|
-
await organizations[data.organization_id][data.storageUrl];
|
|
25
|
-
return organizations[data.organization_id][data.storageUrl];
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error(
|
|
28
|
-
`${data.organization_id}: storageName ${data.storageName} failed to connect to mongodb`
|
|
29
|
-
);
|
|
30
|
-
errorHandler(data, error);
|
|
31
|
-
return { status: false };
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
errorHandler(data, "missing StorageUrl");
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2023 CoCreate and Contributors.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU Affero General Public License as published
|
|
6
|
+
* by the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
********************************************************************************/
|
|
17
|
+
|
|
18
|
+
import database from "./database.js"
|
|
19
|
+
import array from "./array.js"
|
|
20
|
+
import object from "./object.js"
|
|
38
21
|
|
|
39
22
|
function send(data) {
|
|
40
23
|
let [type, method] = data.method.split(".");
|
|
@@ -43,885 +26,4 @@ function send(data) {
|
|
|
43
26
|
if (type === "object") return object(method, data);
|
|
44
27
|
}
|
|
45
28
|
|
|
46
|
-
function database(method, data) {
|
|
47
|
-
return new Promise(
|
|
48
|
-
async (resolve, reject) => {
|
|
49
|
-
let type = "database";
|
|
50
|
-
let databaseArray = [];
|
|
51
|
-
let dataTransferedIn = 0;
|
|
52
|
-
let dataTransferedOut = 0;
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
const client = await dbClient(data);
|
|
56
|
-
if (!client || client.status === false) return data;
|
|
57
|
-
if (method == "read") {
|
|
58
|
-
const db = client.db().admin();
|
|
59
|
-
// TODO: support if a database name is defined then return the database details and stats
|
|
60
|
-
// else apply filter and return dbs for which each should have stats and details
|
|
61
|
-
// if (data.database) {
|
|
62
|
-
// const db = client.db(data.organization_id)
|
|
63
|
-
// const stats = await db.stats()
|
|
64
|
-
// }
|
|
65
|
-
|
|
66
|
-
// List all the available databases
|
|
67
|
-
try {
|
|
68
|
-
const dbs = await db.listDatabases();
|
|
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
|
-
} catch (error) {
|
|
91
|
-
errorHandler(data, error);
|
|
92
|
-
resolve(data);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (method == "delete") {
|
|
96
|
-
const db = client.db(data.database);
|
|
97
|
-
try {
|
|
98
|
-
const result = await db.dropDatabase();
|
|
99
|
-
dataTransferedIn += getBytes(result);
|
|
100
|
-
resolve(result);
|
|
101
|
-
} catch(error) {
|
|
102
|
-
errorHandler(data, error);
|
|
103
|
-
resolve(data);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
errorHandler(data, error);
|
|
108
|
-
console.log(method, "error", error);
|
|
109
|
-
resolve(data);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
(error) => {
|
|
113
|
-
errorHandler(data, error);
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function array(method, data) {
|
|
119
|
-
return new Promise(
|
|
120
|
-
async (resolve, reject) => {
|
|
121
|
-
let type = "array";
|
|
122
|
-
let arrayArray = [];
|
|
123
|
-
let dataTransferedIn = 0;
|
|
124
|
-
let dataTransferedOut = 0;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
const client = await dbClient(data);
|
|
128
|
-
if (!client || client.status === false) return resolve(data);
|
|
129
|
-
|
|
130
|
-
if (data.request) data.array = data.request;
|
|
131
|
-
|
|
132
|
-
let databases = data.database;
|
|
133
|
-
if (!Array.isArray(databases)) databases = [databases];
|
|
134
|
-
|
|
135
|
-
for (let database of databases) {
|
|
136
|
-
const db = client.db(database);
|
|
137
|
-
|
|
138
|
-
if (method == "read") {
|
|
139
|
-
let { query, sort } = await createFilter(data);
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const result = await db.listCollections().toArray();
|
|
143
|
-
if (result) {
|
|
144
|
-
dataTransferedIn += getBytes(result);
|
|
145
|
-
|
|
146
|
-
for (let res of result) {
|
|
147
|
-
if (data.$filter && data.$filter.query) {
|
|
148
|
-
let isFilter = queryData(
|
|
149
|
-
res,
|
|
150
|
-
data.$filter.query
|
|
151
|
-
);
|
|
152
|
-
if (isFilter)
|
|
153
|
-
arrayArray.push({
|
|
154
|
-
name: res.name,
|
|
155
|
-
database,
|
|
156
|
-
storage: data.storageName
|
|
157
|
-
});
|
|
158
|
-
} else
|
|
159
|
-
arrayArray.push({
|
|
160
|
-
name: res.name,
|
|
161
|
-
database,
|
|
162
|
-
storage: data.storageName
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
} catch (error) {
|
|
167
|
-
errorHandler(data, error, database);
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
let arrays;
|
|
171
|
-
let value;
|
|
172
|
-
if (method == "update")
|
|
173
|
-
arrays = Object.entries(data.array);
|
|
174
|
-
else arrays = data.array;
|
|
175
|
-
|
|
176
|
-
if (!Array.isArray(arrays)) arrays = [arrays];
|
|
177
|
-
|
|
178
|
-
for (let array of arrays) {
|
|
179
|
-
if (method == "create") {
|
|
180
|
-
dataTransferedOut += getBytes(array);
|
|
181
|
-
try {
|
|
182
|
-
const result = await db.createCollection(array);
|
|
183
|
-
if (result) {
|
|
184
|
-
dataTransferedIn += getBytes(result);
|
|
185
|
-
arrayArray.push({
|
|
186
|
-
name: array,
|
|
187
|
-
database,
|
|
188
|
-
storage: data.storageName
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
} catch (error) {
|
|
192
|
-
errorHandler(data, error, database, array);
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
if (method == "update") {
|
|
196
|
-
[array, value] = array;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const arrayObj = db.collection(array);
|
|
200
|
-
|
|
201
|
-
if (method == "update") {
|
|
202
|
-
dataTransferedOut += getBytes({ rename: value });
|
|
203
|
-
try {
|
|
204
|
-
const result = await arrayObj.rename(value);
|
|
205
|
-
if (result) {
|
|
206
|
-
dataTransferedIn += getBytes(result);
|
|
207
|
-
arrayArray.push({
|
|
208
|
-
name: value,
|
|
209
|
-
oldName: array,
|
|
210
|
-
database,
|
|
211
|
-
storage: data.storageName
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
} catch (error) {
|
|
215
|
-
errorHandler(data, error, database, array);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (method == "delete") {
|
|
220
|
-
try {
|
|
221
|
-
const result = await arrayObj.drop();
|
|
222
|
-
if (result) {
|
|
223
|
-
dataTransferedOut += getBytes(result);
|
|
224
|
-
arrayArray.push({
|
|
225
|
-
name: array,
|
|
226
|
-
database,
|
|
227
|
-
storage: data.storageName
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
} catch (error) {
|
|
231
|
-
errorHandler(data, error, database, array);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
data = createData(
|
|
240
|
-
data,
|
|
241
|
-
arrayArray,
|
|
242
|
-
type,
|
|
243
|
-
dataTransferedIn,
|
|
244
|
-
dataTransferedOut
|
|
245
|
-
);
|
|
246
|
-
resolve(data);
|
|
247
|
-
} catch (error) {
|
|
248
|
-
errorHandler(data, error);
|
|
249
|
-
console.log(method, "error", error);
|
|
250
|
-
resolve(data);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function object(method, data) {
|
|
257
|
-
return new Promise(
|
|
258
|
-
async (resolve, reject) => {
|
|
259
|
-
try {
|
|
260
|
-
const client = await dbClient(data);
|
|
261
|
-
|
|
262
|
-
if (!client || client.status === false) return resolve(data);
|
|
263
|
-
|
|
264
|
-
let dataTransferedIn = 0;
|
|
265
|
-
let dataTransferedOut = 0;
|
|
266
|
-
let type = "object";
|
|
267
|
-
let documents = [];
|
|
268
|
-
|
|
269
|
-
if (!data["timeStamp"])
|
|
270
|
-
data["timeStamp"] = new Date().toISOString();
|
|
271
|
-
|
|
272
|
-
let databases = data.database;
|
|
273
|
-
if (!Array.isArray(databases)) databases = [databases];
|
|
274
|
-
|
|
275
|
-
for (let database of databases) {
|
|
276
|
-
let arrays = data.array;
|
|
277
|
-
if (!Array.isArray(arrays)) arrays = [arrays];
|
|
278
|
-
|
|
279
|
-
for (let array of arrays) {
|
|
280
|
-
const db = client.db(database);
|
|
281
|
-
const arrayObj = db.collection(array);
|
|
282
|
-
const reference = {
|
|
283
|
-
$storage: data.storageName,
|
|
284
|
-
$database: database,
|
|
285
|
-
$array: array
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
if (!data[type]) data[type] = [];
|
|
289
|
-
else if (typeof data[type] === "string")
|
|
290
|
-
data[type] = [{ _id: data[type] }];
|
|
291
|
-
else if (!Array.isArray(data[type]))
|
|
292
|
-
data[type] = [data[type]];
|
|
293
|
-
|
|
294
|
-
let isFilter;
|
|
295
|
-
if (data.$filter) isFilter = true;
|
|
296
|
-
if ((isFilter && !data[type].length) || data.isFilter)
|
|
297
|
-
data[type].splice(0, 0, {
|
|
298
|
-
isFilter: "isEmptyObjectFilter"
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
let filter = await createFilter(data, arrayObj);
|
|
302
|
-
|
|
303
|
-
let projections = {},
|
|
304
|
-
projection = {},
|
|
305
|
-
globalUpdate = {},
|
|
306
|
-
options = {};
|
|
307
|
-
|
|
308
|
-
if (data.$filter && data.$filter.key)
|
|
309
|
-
projection = data.$filter.key;
|
|
310
|
-
|
|
311
|
-
if (method === "update")
|
|
312
|
-
createUpdate(globalUpdate, options, data, true);
|
|
313
|
-
|
|
314
|
-
for (let i = 0; i < data[type].length; i++) {
|
|
315
|
-
let $storage = data[type][i].$storage || [];
|
|
316
|
-
let $database = data[type][i].$database || [];
|
|
317
|
-
let $array = data[type][i].$array || [];
|
|
318
|
-
let update = { ...globalUpdate };
|
|
319
|
-
|
|
320
|
-
if (!Array.isArray($storage))
|
|
321
|
-
$storage = [data[type][i].$storage];
|
|
322
|
-
if (!Array.isArray($database))
|
|
323
|
-
$database = [data[type][i].$database];
|
|
324
|
-
if (!Array.isArray($array))
|
|
325
|
-
$array = [data[type][i].$array];
|
|
326
|
-
|
|
327
|
-
if (!$storage.includes(data.storageName))
|
|
328
|
-
$storage.push(data.storageName);
|
|
329
|
-
if (!$database.includes(database))
|
|
330
|
-
$database.push(database);
|
|
331
|
-
if (!$array.includes(array)) $array.push(array);
|
|
332
|
-
|
|
333
|
-
delete data[type][i].$storage;
|
|
334
|
-
delete data[type][i].$database;
|
|
335
|
-
delete data[type][i].$array;
|
|
336
|
-
|
|
337
|
-
if (method !== "create" && data[type][i].$filter) {
|
|
338
|
-
isFilter = true;
|
|
339
|
-
reference["$filter"] = data[type][i].$filter;
|
|
340
|
-
filter = await createFilter(
|
|
341
|
-
{ $filter: data[type][i].$filter },
|
|
342
|
-
arrayObj
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
let { query, sort, index, limit } = filter;
|
|
347
|
-
|
|
348
|
-
if (method === "create") {
|
|
349
|
-
// Safety check for replaceArray execution
|
|
350
|
-
if (typeof replaceArray === 'function') {
|
|
351
|
-
data[type][i] = replaceArray(data[type][i]);
|
|
352
|
-
}
|
|
353
|
-
data[type][i] = dotNotationToObject(
|
|
354
|
-
data[type][i]
|
|
355
|
-
);
|
|
356
|
-
data[type][i]["organization_id"] =
|
|
357
|
-
data["organization_id"];
|
|
358
|
-
data[type][i]["created"] = {
|
|
359
|
-
on: new Date(data.timeStamp),
|
|
360
|
-
by: data.user_id || data.clientId
|
|
361
|
-
};
|
|
362
|
-
} else if (method === "update") {
|
|
363
|
-
if (!data[type][i].modified)
|
|
364
|
-
data[type][i].modified = {
|
|
365
|
-
on: new Date(data.timeStamp),
|
|
366
|
-
by: data.user_id || data.clientId
|
|
367
|
-
};
|
|
368
|
-
else
|
|
369
|
-
data[type][i].modified.on = new Date(
|
|
370
|
-
data[type][i].modified.on
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
data[type][i].organization_id =
|
|
374
|
-
data.organization_id;
|
|
375
|
-
createUpdate(update, options, data[type][i]);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
if (data[type][i]._id || method === "create" || isFilter) {
|
|
379
|
-
if (method !== "create") {
|
|
380
|
-
try {
|
|
381
|
-
if (data[type][i]._id) {
|
|
382
|
-
query._id = new ObjectId(data[type][i]._id);
|
|
383
|
-
}
|
|
384
|
-
} catch (error) {
|
|
385
|
-
if (
|
|
386
|
-
method === "update" &&
|
|
387
|
-
options.upsert
|
|
388
|
-
) {
|
|
389
|
-
data[type][i]._id = new ObjectId();
|
|
390
|
-
query._id = data[type][i]._id;
|
|
391
|
-
} else {
|
|
392
|
-
errorHandler(
|
|
393
|
-
data,
|
|
394
|
-
error,
|
|
395
|
-
database,
|
|
396
|
-
array
|
|
397
|
-
);
|
|
398
|
-
continue;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
dataTransferedOut += getBytes({
|
|
405
|
-
query,
|
|
406
|
-
update,
|
|
407
|
-
projection,
|
|
408
|
-
options
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
let result;
|
|
412
|
-
if (method === "create") {
|
|
413
|
-
if (data[type][i]._id) {
|
|
414
|
-
try {
|
|
415
|
-
data[type][i]._id = new ObjectId(
|
|
416
|
-
data[type][i]._id
|
|
417
|
-
);
|
|
418
|
-
} catch (error) {
|
|
419
|
-
delete data[type][i]._id;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
result = await arrayObj.insertOne(
|
|
423
|
-
data[type][i]
|
|
424
|
-
);
|
|
425
|
-
data[type][i]._id =
|
|
426
|
-
result.insertedId.toString();
|
|
427
|
-
documents.push({ ...data[type][i], ...reference });
|
|
428
|
-
} else {
|
|
429
|
-
// Modern cursor iteration for v7.5
|
|
430
|
-
let cursor = arrayObj.find(query, { projection });
|
|
431
|
-
if (sort && Object.keys(sort).length > 0) cursor = cursor.sort(sort);
|
|
432
|
-
if (limit) cursor = cursor.limit(limit);
|
|
433
|
-
|
|
434
|
-
let hasDocuments = false;
|
|
435
|
-
|
|
436
|
-
for await (const document of cursor) {
|
|
437
|
-
hasDocuments = true;
|
|
438
|
-
dataTransferedIn += getBytes(document);
|
|
439
|
-
|
|
440
|
-
if (data.$filter && data.$filter.search) {
|
|
441
|
-
let isMatch = searchData(
|
|
442
|
-
document,
|
|
443
|
-
data.$filter.search
|
|
444
|
-
);
|
|
445
|
-
if (!isMatch) continue;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (method === "read") {
|
|
449
|
-
document._id = document._id.toString();
|
|
450
|
-
let object = data[type].find(
|
|
451
|
-
(obj) =>
|
|
452
|
-
obj._id &&
|
|
453
|
-
obj._id.toString() === document._id.toString()
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
if (object && object.$storage && object.modified && object.modified.on) {
|
|
457
|
-
if (document.modified && new Date(object.modified.on) > new Date(document.modified.on)) {
|
|
458
|
-
object = { ...document, ...object };
|
|
459
|
-
let docUpdate = {};
|
|
460
|
-
let docOptions = {};
|
|
461
|
-
createUpdate(docUpdate, docOptions, object);
|
|
462
|
-
let updateResult = await arrayObj.updateOne(
|
|
463
|
-
{ _id: new ObjectId(document._id) },
|
|
464
|
-
docUpdate,
|
|
465
|
-
docOptions
|
|
466
|
-
);
|
|
467
|
-
dataTransferedIn += getBytes(updateResult);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
documents.push({ ...document, ...reference });
|
|
471
|
-
} else {
|
|
472
|
-
dataTransferedOut += getBytes({
|
|
473
|
-
_id: document._id,
|
|
474
|
-
update,
|
|
475
|
-
options
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
if (method === "update") {
|
|
479
|
-
if (update["$pull"] && update["$unset"]) {
|
|
480
|
-
result = await arrayObj.updateOne(
|
|
481
|
-
{ _id: document._id },
|
|
482
|
-
{ $unset: update["$unset"] },
|
|
483
|
-
options
|
|
484
|
-
);
|
|
485
|
-
delete update["$unset"];
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (options.returnNewDocument) {
|
|
489
|
-
// returnDocument: 'after' replaces returnOriginal: false for v7.5
|
|
490
|
-
let updatedObj = await arrayObj.findOneAndUpdate(
|
|
491
|
-
{ _id: document._id },
|
|
492
|
-
update,
|
|
493
|
-
{ ...options, returnDocument: 'after' }
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
if (updatedObj && updatedObj.value) {
|
|
497
|
-
for (let key of Object.keys(updatedObj.value)) {
|
|
498
|
-
if (key === "_id" || !options.newArray) continue;
|
|
499
|
-
let newArrayKey = options.newArray[key];
|
|
500
|
-
if (newArrayKey) {
|
|
501
|
-
let idx = updatedObj.value[key].length - 1;
|
|
502
|
-
if (idx >= 0) {
|
|
503
|
-
data[type][i][newArrayKey.replace("[]", `[${idx}]`)] = data[type][i][newArrayKey];
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
} else {
|
|
509
|
-
result = await arrayObj.updateOne(
|
|
510
|
-
{ _id: document._id },
|
|
511
|
-
update,
|
|
512
|
-
options
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
} else if (method === "delete") {
|
|
516
|
-
result = await arrayObj.deleteOne({
|
|
517
|
-
_id: document._id
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
dataTransferedIn += getBytes(result);
|
|
522
|
-
documents.push({
|
|
523
|
-
...data[type][i],
|
|
524
|
-
...reference,
|
|
525
|
-
_id: document._id.toString()
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// Upsert fallback if missing
|
|
531
|
-
if (!hasDocuments && method === "update" && (data.upsert || options.upsert)) {
|
|
532
|
-
let upsertId = data[type][i]._id ? new ObjectId(data[type][i]._id) : new ObjectId();
|
|
533
|
-
let result = await arrayObj.updateOne(
|
|
534
|
-
{ _id: upsertId },
|
|
535
|
-
update,
|
|
536
|
-
{ ...options, upsert: true }
|
|
537
|
-
);
|
|
538
|
-
dataTransferedIn += getBytes(result);
|
|
539
|
-
documents.push({
|
|
540
|
-
...data[type][i],
|
|
541
|
-
...reference,
|
|
542
|
-
_id: upsertId.toString()
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
} catch (error) {
|
|
547
|
-
errorHandler(data, error, database, array);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
data = createData(
|
|
554
|
-
data,
|
|
555
|
-
documents,
|
|
556
|
-
type,
|
|
557
|
-
dataTransferedIn,
|
|
558
|
-
dataTransferedOut
|
|
559
|
-
);
|
|
560
|
-
resolve(data);
|
|
561
|
-
} catch (error) {
|
|
562
|
-
errorHandler(data, error);
|
|
563
|
-
console.log(method, "error", error);
|
|
564
|
-
resolve(data);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
function createUpdate(update, options, data, isGlobal) {
|
|
571
|
-
if (data.upsert) options.upsert = data.upsert;
|
|
572
|
-
if (data.$upsert) options.upsert = data.$upsert;
|
|
573
|
-
if (data.$update) delete data.$update;
|
|
574
|
-
|
|
575
|
-
Object.keys(data).forEach((key) => {
|
|
576
|
-
if ((isGlobal && !key.startsWith("$")) || key === "_id") return;
|
|
577
|
-
|
|
578
|
-
if (isValidDate(data[key])) data[key] = new Date(data[key]);
|
|
579
|
-
|
|
580
|
-
let operator;
|
|
581
|
-
if (key.endsWith("]")) {
|
|
582
|
-
const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
|
|
583
|
-
var match = key.match(regex);
|
|
584
|
-
var index = parseInt(match[2], 10);
|
|
585
|
-
if (index === NaN) operator = match[2];
|
|
586
|
-
var arrayKey = match[1].replace(/\[(\d+)\]/g, ".$1");
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
if (key.startsWith("$")) operator = key.split(".")[0];
|
|
590
|
-
else if (
|
|
591
|
-
!operator &&
|
|
592
|
-
typeof data[key] === "string" &&
|
|
593
|
-
data[key].startsWith("$")
|
|
594
|
-
)
|
|
595
|
-
operator = data[key];
|
|
596
|
-
|
|
597
|
-
if (!update["$set"]) update["$set"] = {};
|
|
598
|
-
|
|
599
|
-
let originalKey = key;
|
|
600
|
-
key = key.replace(/\[(\d+)\]/g, ".$1");
|
|
601
|
-
|
|
602
|
-
if (originalKey.endsWith("[]")) {
|
|
603
|
-
if (!options.projection) {
|
|
604
|
-
options.projection = {};
|
|
605
|
-
options.arrayKey = {};
|
|
606
|
-
options.returnNewDocument = true;
|
|
607
|
-
} else {
|
|
608
|
-
options.projection[key.replace(operator + ".", "")] = 1;
|
|
609
|
-
options.arrayKey[key.replace(operator + ".", "")] = originalKey;
|
|
610
|
-
}
|
|
611
|
-
if (!key.startsWith("$")) operator = "$push";
|
|
612
|
-
if (key.endsWith("[]")) key = key.replace("[]", "");
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
let operators = [
|
|
616
|
-
"$rename",
|
|
617
|
-
"$inc",
|
|
618
|
-
"$push",
|
|
619
|
-
"$each",
|
|
620
|
-
"$splice",
|
|
621
|
-
"$unset",
|
|
622
|
-
"$delete",
|
|
623
|
-
"$slice",
|
|
624
|
-
"$pop",
|
|
625
|
-
"$shift",
|
|
626
|
-
"$addToSet",
|
|
627
|
-
"$pull",
|
|
628
|
-
"$currentDate"
|
|
629
|
-
];
|
|
630
|
-
if (!operators.includes(operator) && typeof index !== "number") {
|
|
631
|
-
if (!isGlobal) update["$set"][key] = data[originalKey];
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
let updates = {};
|
|
636
|
-
if (operator === "$rename") {
|
|
637
|
-
if (key === "$rename")
|
|
638
|
-
for (let oldkey of Object.keys(data[originalKey])) {
|
|
639
|
-
key = "$rename." + oldkey;
|
|
640
|
-
updates[key] = data[originalKey][oldkey].replace(
|
|
641
|
-
/\[(\d+)\]/g,
|
|
642
|
-
".$1"
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
else updates[key] = data[originalKey].replace(/\[(\d+)\]/g, ".$1");
|
|
646
|
-
} else if (
|
|
647
|
-
operator === "$delete" ||
|
|
648
|
-
operator === "$unset" ||
|
|
649
|
-
operator === "$slice"
|
|
650
|
-
) {
|
|
651
|
-
operator = "$unset";
|
|
652
|
-
updates[key] = 1;
|
|
653
|
-
// if (!updates["$pull"]) updates["$pull"] = {};
|
|
654
|
-
const pullkey = key.split(".");
|
|
655
|
-
pullkey.shift();
|
|
656
|
-
pullkey.pop();
|
|
657
|
-
// updates["$pull"][pullkey.join('.')] = null;
|
|
658
|
-
// updates["$pull"][pullkey.join('.')] = { $in: [null] };
|
|
659
|
-
if (!update["$pull"]) update["$pull"] = {};
|
|
660
|
-
update["$pull"][pullkey.join(".")] = null;
|
|
661
|
-
} else if (operator === "$pop") {
|
|
662
|
-
key = arrayKey;
|
|
663
|
-
updates[key] = index || 1;
|
|
664
|
-
} else if (operator === "$addToSet" || operator === "$pull") {
|
|
665
|
-
updates[key] = data[originalKey];
|
|
666
|
-
} else if (
|
|
667
|
-
operator === "$push" ||
|
|
668
|
-
operator === "$each" ||
|
|
669
|
-
typeof index === "number"
|
|
670
|
-
) {
|
|
671
|
-
updates[key] = data[originalKey];
|
|
672
|
-
if (typeof index === "number" && index >= 0) {
|
|
673
|
-
if (!operator) operator = "$set";
|
|
674
|
-
else {
|
|
675
|
-
if (operator === "$push")
|
|
676
|
-
updates[key] = [data[originalKey]];
|
|
677
|
-
|
|
678
|
-
let insert = { $each: updates[key] };
|
|
679
|
-
insert.$postion = index;
|
|
680
|
-
if (index >= 0) updates[arrayKey] = insert;
|
|
681
|
-
else updates[key] = insert;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
} else if (operator === "$inc") {
|
|
685
|
-
updates[key] = data[originalKey];
|
|
686
|
-
} else if (operator === "$currentDate") {
|
|
687
|
-
updates[key] = data[originalKey];
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (!update[operator]) update[operator] = {};
|
|
691
|
-
|
|
692
|
-
if (key === operator)
|
|
693
|
-
update[operator] = {
|
|
694
|
-
...update[operator],
|
|
695
|
-
...replaceArray(updates[key])
|
|
696
|
-
};
|
|
697
|
-
else update[operator][key.replace(operator + ".", "")] = updates[key];
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
async function createFilter(data, arrayObj) {
|
|
702
|
-
let query = {},
|
|
703
|
-
sort = {},
|
|
704
|
-
index = 0,
|
|
705
|
-
limit = 0,
|
|
706
|
-
count;
|
|
707
|
-
|
|
708
|
-
if (data.$filter) {
|
|
709
|
-
function convertIfDate(value) {
|
|
710
|
-
if (
|
|
711
|
-
typeof value === "string" &&
|
|
712
|
-
value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/)
|
|
713
|
-
) {
|
|
714
|
-
return new Date(value);
|
|
715
|
-
}
|
|
716
|
-
return value;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// Recursive function to merge keys into dot notation
|
|
720
|
-
function mergeToDotNotation(obj, parentKey = "", result = {}) {
|
|
721
|
-
for (let key in obj) {
|
|
722
|
-
const isOperator = key.startsWith("$");
|
|
723
|
-
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
|
724
|
-
|
|
725
|
-
if (
|
|
726
|
-
obj[key] &&
|
|
727
|
-
typeof obj[key] === "object" &&
|
|
728
|
-
!Array.isArray(obj[key])
|
|
729
|
-
) {
|
|
730
|
-
if (isOperator) {
|
|
731
|
-
// Ensure operators are grouped under their parent key
|
|
732
|
-
result[parentKey] = result[parentKey] || {};
|
|
733
|
-
result[parentKey][key] = obj[key];
|
|
734
|
-
} else {
|
|
735
|
-
// Recurse into nested objects
|
|
736
|
-
mergeToDotNotation(obj[key], currentKey, result);
|
|
737
|
-
}
|
|
738
|
-
} else {
|
|
739
|
-
// Assign to result, merging into dot notation if applicable
|
|
740
|
-
if (isOperator) {
|
|
741
|
-
result[parentKey] = result[parentKey] || {};
|
|
742
|
-
result[parentKey][key] = obj[key];
|
|
743
|
-
} else {
|
|
744
|
-
result[currentKey] = obj[key];
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
return result;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
if (data.$filter.query) {
|
|
752
|
-
for (let key in data.$filter.query) {
|
|
753
|
-
if (Array.isArray(data.$filter.query[key])) {
|
|
754
|
-
// Handle $or operator with an array of conditions
|
|
755
|
-
query[key] = data.$filter.query[key].map((condition) => {
|
|
756
|
-
let newCondition = {};
|
|
757
|
-
mergeToDotNotation(condition, "", newCondition);
|
|
758
|
-
return newCondition;
|
|
759
|
-
});
|
|
760
|
-
} else if (
|
|
761
|
-
typeof data.$filter.query[key] === "object" &&
|
|
762
|
-
data.$filter.query[key] !== null
|
|
763
|
-
) {
|
|
764
|
-
// Handle general object conditions
|
|
765
|
-
mergeToDotNotation(data.$filter.query[key], key, query);
|
|
766
|
-
} else {
|
|
767
|
-
// Handle direct values
|
|
768
|
-
query[key] =
|
|
769
|
-
key === "_id"
|
|
770
|
-
? ObjectId(data.$filter.query[key])
|
|
771
|
-
: convertIfDate(data.$filter.query[key]);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
if (data.$filter.sort) {
|
|
777
|
-
for (let i = 0; i < data.$filter.sort.length; i++) {
|
|
778
|
-
let direction = data.$filter.sort[i].direction;
|
|
779
|
-
direction = direction === "desc" || direction === -1 ? -1 : 1;
|
|
780
|
-
|
|
781
|
-
sort[data.$filter.sort[i].key] = direction;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
if (arrayObj) {
|
|
786
|
-
count = await arrayObj.estimatedDocumentCount();
|
|
787
|
-
data.$filter.count = count;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (data.$filter.index) index = data.$filter.index;
|
|
791
|
-
if (data.$filter.limit) limit = data.$filter.limit;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
if (data["organization_id"])
|
|
795
|
-
query["organization_id"] = data["organization_id"];
|
|
796
|
-
|
|
797
|
-
return { query, sort, index, limit, count };
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
function parseRegExp(regExpString) {
|
|
801
|
-
let matches = regExpString.match(/\/(.*)\/(.*)/);
|
|
802
|
-
return {
|
|
803
|
-
pattern: matches[1],
|
|
804
|
-
options: matches[2]
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
function createProjection(projection, data) {
|
|
809
|
-
Object.keys(data).forEach((key) => {
|
|
810
|
-
if (
|
|
811
|
-
!["_id", "organization_id", "isFIlter"].includes(key) &&
|
|
812
|
-
!key.startsWith("$")
|
|
813
|
-
)
|
|
814
|
-
projection[key.replace(/\[(\d+)\]/g, ".$1")] = 1;
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
return projection;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
function replaceArray(data = {}) {
|
|
821
|
-
let object = {};
|
|
822
|
-
|
|
823
|
-
Object.keys(data).forEach((key) => {
|
|
824
|
-
object[key.replace(/\[(\d+)\]/g, ".$1")] = data[key];
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
return object;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
function createData(data, array, type, dataTransferedIn, dataTransferedOut) {
|
|
831
|
-
if (dataTransferedIn) {
|
|
832
|
-
process.emit("setBandwidth", {
|
|
833
|
-
type: "in",
|
|
834
|
-
data: dataTransferedIn,
|
|
835
|
-
organization_id: data.organization_id
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
if (dataTransferedOut) {
|
|
840
|
-
process.emit("setBandwidth", {
|
|
841
|
-
type: "out",
|
|
842
|
-
data: dataTransferedOut,
|
|
843
|
-
organization_id: data.organization_id
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
if (
|
|
848
|
-
data[type] &&
|
|
849
|
-
data[type][0] &&
|
|
850
|
-
data[type][0].isFilter === "isEmptyObjectFilter"
|
|
851
|
-
) {
|
|
852
|
-
data[type].shift();
|
|
853
|
-
data.isFilter = true;
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// if (!data.request)
|
|
857
|
-
// data.request = data[type] || {}
|
|
858
|
-
|
|
859
|
-
let key = "_id";
|
|
860
|
-
if (type !== "object") key = "name";
|
|
861
|
-
|
|
862
|
-
// TODO: handle case where data[type] is not an array
|
|
863
|
-
if (!Array.isArray(data[type]))
|
|
864
|
-
console.log("data[type] is not an array", type);
|
|
865
|
-
else {
|
|
866
|
-
for (let i = 0; i < array.length; i++) {
|
|
867
|
-
const matchIndex = data[type].findIndex(
|
|
868
|
-
(item) => item[key] === array[i][key]
|
|
869
|
-
);
|
|
870
|
-
if (matchIndex !== -1) {
|
|
871
|
-
for (let $type of ["$storage", "$database", "$array"]) {
|
|
872
|
-
if (!data[type][matchIndex][$type])
|
|
873
|
-
data[type][matchIndex][$type] = [];
|
|
874
|
-
if (!Array.isArray(data[type][matchIndex][$type])) {
|
|
875
|
-
data[type][matchIndex][$type] = [
|
|
876
|
-
data[type][matchIndex][$type]
|
|
877
|
-
];
|
|
878
|
-
if (
|
|
879
|
-
!data[type][matchIndex][$type].includes(
|
|
880
|
-
array[i][$type]
|
|
881
|
-
)
|
|
882
|
-
) {
|
|
883
|
-
data[type][matchIndex][$type].push(array[i][$type]);
|
|
884
|
-
}
|
|
885
|
-
} else {
|
|
886
|
-
data[type][matchIndex][$type].push(array[i][$type]);
|
|
887
|
-
}
|
|
888
|
-
delete array[i][$type];
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
// TODO: compare dates and merge and and updates to keep all synced and up to date
|
|
892
|
-
data[type][matchIndex] = {
|
|
893
|
-
...data[type][matchIndex],
|
|
894
|
-
...array[i]
|
|
895
|
-
};
|
|
896
|
-
} else data[type].push(array[i]);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
return data;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
function getBytes(data) {
|
|
904
|
-
const jsonString = JSON.stringify(data);
|
|
905
|
-
return Buffer.byteLength(jsonString, "utf8");
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
function errorHandler(data, error, database, array) {
|
|
909
|
-
let errorMessage =
|
|
910
|
-
typeof error === "object" && error.message ? error.message : error;
|
|
911
|
-
|
|
912
|
-
let errorObject = {
|
|
913
|
-
message: errorMessage,
|
|
914
|
-
storage: "mongodb"
|
|
915
|
-
};
|
|
916
|
-
|
|
917
|
-
if (database) errorObject.database = database;
|
|
918
|
-
if (array) errorObject.array = array;
|
|
919
|
-
|
|
920
|
-
if (Array.isArray(data.error)) {
|
|
921
|
-
data.error.push(errorObject);
|
|
922
|
-
} else {
|
|
923
|
-
data.error = [errorObject];
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
29
|
export default { send };
|