blixify-server 0.3.28 → 1.0.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/dist/apis/authWrapper.d.ts.map +1 -1
- package/dist/apis/authWrapper.js +1 -228
- package/dist/apis/crypto.d.ts.map +1 -1
- package/dist/apis/crypto.js +1 -63
- package/dist/apis/dayjs.d.ts +3 -0
- package/dist/apis/dayjs.d.ts.map +1 -0
- package/dist/apis/dayjs.js +1 -0
- package/dist/apis/fbWrapper.d.ts +6 -6
- package/dist/apis/fbWrapper.d.ts.map +1 -1
- package/dist/apis/fbWrapper.js +1 -839
- package/dist/apis/googleAnalyticsWrapper.d.ts.map +1 -1
- package/dist/apis/googleAnalyticsWrapper.js +1 -223
- package/dist/apis/index.js +1 -21
- package/dist/apis/mondayWrapper.d.ts +2 -2
- package/dist/apis/mondayWrapper.d.ts.map +1 -1
- package/dist/apis/mondayWrapper.js +32 -527
- package/dist/apis/mongoWrapper.d.ts +6 -6
- package/dist/apis/mongoWrapper.d.ts.map +1 -1
- package/dist/apis/mongoWrapper.js +1 -1524
- package/dist/apis/postgresqlWrapper.d.ts +3 -3
- package/dist/apis/postgresqlWrapper.d.ts.map +1 -1
- package/dist/apis/postgresqlWrapper.js +1 -514
- package/dist/apis/security.d.ts.map +1 -1
- package/dist/apis/security.js +1 -80
- package/dist/apis/trackVisionWrapper.d.ts.map +1 -1
- package/dist/apis/trackVisionWrapper.js +1 -150
- package/dist/apis/uploadWrapper.d.ts.map +1 -1
- package/dist/apis/uploadWrapper.js +1 -481
- package/dist/apis/utils.d.ts +1 -1
- package/dist/apis/utils.d.ts.map +1 -1
- package/dist/apis/utils.js +1 -25
- package/dist/buildtsconfig.tsbuildinfo +1 -0
- package/dist/model/Log.js +1 -2
- package/dist/model/QueryModel.d.ts.map +1 -1
- package/dist/model/QueryModel.js +1 -118
- package/dist/model/SecurityConfig.js +1 -2
- package/package.json +21 -12
|
@@ -1,1524 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.MongoWrapper = void 0;
|
|
16
|
-
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
17
|
-
const uuid_1 = require("uuid");
|
|
18
|
-
const QueryModel_1 = require("../model/QueryModel");
|
|
19
|
-
const utils_1 = require("./utils");
|
|
20
|
-
const handleParseQueryFilter = (queryList, prefix) => {
|
|
21
|
-
const queryFilter = {};
|
|
22
|
-
const queryGroupValues = {};
|
|
23
|
-
if (queryList && queryList.length > 0) {
|
|
24
|
-
queryList.map((eachQuery) => {
|
|
25
|
-
var _a, _b, _c;
|
|
26
|
-
let queryId = (_a = eachQuery.queryId) !== null && _a !== void 0 ? _a : "";
|
|
27
|
-
if (prefix)
|
|
28
|
-
queryId = `${prefix}.${queryId}`;
|
|
29
|
-
const value = eachQuery.value;
|
|
30
|
-
const queryValues = {};
|
|
31
|
-
let orOption = eachQuery.orQuery ? true : false;
|
|
32
|
-
switch (eachQuery.type) {
|
|
33
|
-
case "search":
|
|
34
|
-
if (eachQuery.searchIds && eachQuery.searchIds.length > 0) {
|
|
35
|
-
eachQuery.searchIds.map((eachSearchId) => {
|
|
36
|
-
orOption = true;
|
|
37
|
-
queryValues[eachSearchId] = {
|
|
38
|
-
$regex: `${(0, utils_1.handleSpecialWordsEscapeRegex)(value)}`,
|
|
39
|
-
$options: "i",
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
if (eachQuery.foreign && eachQuery.foreign.length > 0) {
|
|
44
|
-
(_b = eachQuery === null || eachQuery === void 0 ? void 0 : eachQuery.foreign) === null || _b === void 0 ? void 0 : _b.forEach((foreignLookup) => {
|
|
45
|
-
let foreignAlias = foreignLookup.alias;
|
|
46
|
-
if (prefix) {
|
|
47
|
-
foreignAlias = `${prefix}.${foreignAlias}`;
|
|
48
|
-
}
|
|
49
|
-
if (foreignLookup.searchFields &&
|
|
50
|
-
foreignLookup.searchFields.length > 0) {
|
|
51
|
-
foreignLookup.searchFields.forEach((field) => {
|
|
52
|
-
queryValues[`${foreignAlias}.${field}`] = {
|
|
53
|
-
$regex: eachQuery.value
|
|
54
|
-
.toString()
|
|
55
|
-
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
|
|
56
|
-
$options: "i",
|
|
57
|
-
};
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
break;
|
|
63
|
-
case "=":
|
|
64
|
-
queryValues[queryId] = value;
|
|
65
|
-
break;
|
|
66
|
-
case "!=":
|
|
67
|
-
queryValues[queryId] = {
|
|
68
|
-
$ne: value,
|
|
69
|
-
};
|
|
70
|
-
break;
|
|
71
|
-
case ">":
|
|
72
|
-
queryValues[queryId] = {
|
|
73
|
-
$gt: value,
|
|
74
|
-
};
|
|
75
|
-
break;
|
|
76
|
-
case "<":
|
|
77
|
-
queryValues[queryId] = {
|
|
78
|
-
$lt: value,
|
|
79
|
-
};
|
|
80
|
-
break;
|
|
81
|
-
case "><":
|
|
82
|
-
if (Array.isArray(value) && value.length >= 2) {
|
|
83
|
-
queryValues[queryId] = {
|
|
84
|
-
$gte: value[0],
|
|
85
|
-
$lte: value[1],
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
case "in":
|
|
90
|
-
queryValues[queryId] = {
|
|
91
|
-
$in: value,
|
|
92
|
-
};
|
|
93
|
-
break;
|
|
94
|
-
case "!in":
|
|
95
|
-
queryValues[queryId] = {
|
|
96
|
-
$nin: value,
|
|
97
|
-
};
|
|
98
|
-
break;
|
|
99
|
-
case "exists":
|
|
100
|
-
queryValues[queryId] = {
|
|
101
|
-
$exists: value,
|
|
102
|
-
};
|
|
103
|
-
break;
|
|
104
|
-
case "elemMatch":
|
|
105
|
-
queryValues[queryId] = {
|
|
106
|
-
$elemMatch: value,
|
|
107
|
-
};
|
|
108
|
-
break;
|
|
109
|
-
case ">size":
|
|
110
|
-
if (!queryValues["$expr"])
|
|
111
|
-
queryValues["$expr"] = {};
|
|
112
|
-
queryValues["$expr"]["$gt"] = [{ $size: `$${queryId}` }, value];
|
|
113
|
-
break;
|
|
114
|
-
case "<size":
|
|
115
|
-
if (!queryValues["$expr"])
|
|
116
|
-
queryValues["$expr"] = {};
|
|
117
|
-
queryValues["$expr"]["$lt"] = [{ $size: `$${queryId}` }, value];
|
|
118
|
-
break;
|
|
119
|
-
default:
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
//INFO : Delete Query Values as it's added outside
|
|
123
|
-
if (eachQuery.orQueryGroupId) {
|
|
124
|
-
if (eachQuery.type === "search") {
|
|
125
|
-
(_c = eachQuery === null || eachQuery === void 0 ? void 0 : eachQuery.searchIds) === null || _c === void 0 ? void 0 : _c.map((eachSearchId) => {
|
|
126
|
-
if (eachQuery.orQueryGroupId) {
|
|
127
|
-
if (queryGroupValues[eachQuery === null || eachQuery === void 0 ? void 0 : eachQuery.orQueryGroupId]) {
|
|
128
|
-
queryGroupValues[eachQuery === null || eachQuery === void 0 ? void 0 : eachQuery.orQueryGroupId]["$and"].push({
|
|
129
|
-
[eachSearchId]: queryValues[eachSearchId],
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
queryGroupValues[eachQuery === null || eachQuery === void 0 ? void 0 : eachQuery.orQueryGroupId] = {
|
|
134
|
-
$and: [{ [eachSearchId]: queryValues[eachSearchId] }],
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
delete queryValues[eachSearchId];
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
const groupValue = queryValues[queryId];
|
|
143
|
-
if (groupValue !== undefined) {
|
|
144
|
-
if (queryGroupValues[eachQuery.orQueryGroupId]) {
|
|
145
|
-
queryGroupValues[eachQuery.orQueryGroupId]["$and"].push({
|
|
146
|
-
[queryId]: queryValues[queryId],
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
queryGroupValues[eachQuery.orQueryGroupId] = {
|
|
151
|
-
$and: [{ [queryId]: queryValues[queryId] }],
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
delete queryValues[queryId];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
Object.keys(queryValues).map((eachKey) => {
|
|
159
|
-
if (orOption) {
|
|
160
|
-
if (queryFilter["$or"])
|
|
161
|
-
queryFilter["$or"].push({ [eachKey]: queryValues[eachKey] });
|
|
162
|
-
else
|
|
163
|
-
queryFilter["$or"] = [{ [eachKey]: queryValues[eachKey] }];
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
queryFilter[eachKey] = queryValues[eachKey];
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
Object.keys(queryGroupValues).map((eachKey) => {
|
|
172
|
-
if (queryFilter["$or"])
|
|
173
|
-
queryFilter["$or"].push(queryGroupValues[eachKey]);
|
|
174
|
-
else
|
|
175
|
-
queryFilter["$or"] = [queryGroupValues[eachKey]];
|
|
176
|
-
});
|
|
177
|
-
return queryFilter;
|
|
178
|
-
};
|
|
179
|
-
/**
|
|
180
|
-
* @Wrapper
|
|
181
|
-
* collection - MongoDB Collection
|
|
182
|
-
*
|
|
183
|
-
*/
|
|
184
|
-
class MongoWrapper {
|
|
185
|
-
constructor(mongoDB, collection, isProd, config, modelChecker, lib, tableId, logId, logWorkflow, logCollectIds, debug) {
|
|
186
|
-
this.mongoDB = "";
|
|
187
|
-
this.collection = "";
|
|
188
|
-
this.isProd = false;
|
|
189
|
-
this.config = {
|
|
190
|
-
baseConfig: [],
|
|
191
|
-
opsConfig: {
|
|
192
|
-
read: [],
|
|
193
|
-
create: [],
|
|
194
|
-
update: [],
|
|
195
|
-
delete: [],
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
this.tableId = "";
|
|
199
|
-
this.logId = "";
|
|
200
|
-
this.logCollectIds = [];
|
|
201
|
-
// eslint-disable-next-line
|
|
202
|
-
this.modelChecker = (obj) => {
|
|
203
|
-
return false;
|
|
204
|
-
};
|
|
205
|
-
this.parseModel = (data) => {
|
|
206
|
-
delete data["_id"];
|
|
207
|
-
data["baseUpdatedAt"] = (0, moment_timezone_1.default)().toDate();
|
|
208
|
-
return data;
|
|
209
|
-
};
|
|
210
|
-
this.handleLogging = (mongoId, type, req, value) => __awaiter(this, void 0, void 0, function* () {
|
|
211
|
-
if (!this.logId)
|
|
212
|
-
return;
|
|
213
|
-
try {
|
|
214
|
-
const userId = req.body["bm_userId"];
|
|
215
|
-
const userRole = req.body["bm_userRole"];
|
|
216
|
-
const organisationId = req.body["bm_userOrg"];
|
|
217
|
-
const changeValueList = [];
|
|
218
|
-
const dataDoc = type === "create" ? req.body.data : value === null || value === void 0 ? void 0 : value.new;
|
|
219
|
-
Object.keys(dataDoc).map((eachKey) => {
|
|
220
|
-
var _a, _b;
|
|
221
|
-
const eachChangeValue = {
|
|
222
|
-
newValue: dataDoc[eachKey],
|
|
223
|
-
columnId: eachKey,
|
|
224
|
-
};
|
|
225
|
-
if (type === "update") {
|
|
226
|
-
eachChangeValue["oldValue"] = (_a = value === null || value === void 0 ? void 0 : value.old) === null || _a === void 0 ? void 0 : _a[eachKey];
|
|
227
|
-
//INFO : Double check similar value again as compareUpdatedFields allow UUID
|
|
228
|
-
if (JSON.stringify(dataDoc[eachKey]) ===
|
|
229
|
-
JSON.stringify((_b = value === null || value === void 0 ? void 0 : value.old) === null || _b === void 0 ? void 0 : _b[eachKey]))
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (eachKey !== "_id" && !eachKey.startsWith("base"))
|
|
233
|
-
changeValueList.push(eachChangeValue);
|
|
234
|
-
});
|
|
235
|
-
if (type === "update" && changeValueList.length === 0)
|
|
236
|
-
return;
|
|
237
|
-
const logItem = {
|
|
238
|
-
_id: (0, uuid_1.v4)(),
|
|
239
|
-
type,
|
|
240
|
-
itemId: mongoId,
|
|
241
|
-
collectionId: this.collection,
|
|
242
|
-
createdAt: (0, moment_timezone_1.default)().toDate(),
|
|
243
|
-
values: changeValueList,
|
|
244
|
-
userId,
|
|
245
|
-
userRole,
|
|
246
|
-
organisationId,
|
|
247
|
-
};
|
|
248
|
-
if ((type === "create" || type === "update") &&
|
|
249
|
-
this.logCollectIds.length > 0) {
|
|
250
|
-
this.logCollectIds.forEach((collectId) => {
|
|
251
|
-
if (dataDoc[collectId] !== undefined) {
|
|
252
|
-
logItem[collectId] = dataDoc[collectId];
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
const mongoLogCollection = this.mongoDB
|
|
257
|
-
.db(this.tableId)
|
|
258
|
-
.collection(this.logId);
|
|
259
|
-
yield mongoLogCollection.insertOne(logItem);
|
|
260
|
-
if (this.logWorkflow)
|
|
261
|
-
yield this.logWorkflow(logItem);
|
|
262
|
-
}
|
|
263
|
-
catch (err) { }
|
|
264
|
-
});
|
|
265
|
-
this.initBatchCreate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
266
|
-
var _a;
|
|
267
|
-
try {
|
|
268
|
-
if (Array.isArray(req.body.data)) {
|
|
269
|
-
let valid = true;
|
|
270
|
-
const upsert = req.body.upsert ? true : false;
|
|
271
|
-
req.body.data.map((eachData) => {
|
|
272
|
-
if (!this.modelChecker(eachData)) {
|
|
273
|
-
valid = false;
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
if (!valid) {
|
|
277
|
-
res.status(400).json({ err: "Invalid Model Structure" });
|
|
278
|
-
}
|
|
279
|
-
//INFO : Security Checker
|
|
280
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
281
|
-
let validOpsConfig = true;
|
|
282
|
-
const uniqueDataField = [];
|
|
283
|
-
yield Promise.all(req.body.data.map((eachData) => {
|
|
284
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "update", req, eachData)) {
|
|
285
|
-
validOpsConfig = false;
|
|
286
|
-
}
|
|
287
|
-
if (req.body.unique && (eachData === null || eachData === void 0 ? void 0 : eachData[req.body.unique]))
|
|
288
|
-
uniqueDataField.push(eachData[req.body.unique]);
|
|
289
|
-
}));
|
|
290
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
291
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const mongoCollection = this.mongoDB
|
|
295
|
-
.db(this.tableId)
|
|
296
|
-
.collection(this.collection);
|
|
297
|
-
if (uniqueDataField.length > 0) {
|
|
298
|
-
const existsDataRes = yield mongoCollection.find({
|
|
299
|
-
[req.body.unique]: { $in: uniqueDataField },
|
|
300
|
-
});
|
|
301
|
-
const existsDataList = yield existsDataRes.toArray();
|
|
302
|
-
if (existsDataList.length > 0) {
|
|
303
|
-
res.status(400).json({
|
|
304
|
-
err: `Unique:${existsDataList.map((eachData) => eachData[req.body.unique])} exists`,
|
|
305
|
-
});
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const ids = [];
|
|
310
|
-
const batchCreateDataList = req.body.data.map((eachData) => {
|
|
311
|
-
ids.push(eachData._id);
|
|
312
|
-
return Object.assign(Object.assign({}, eachData), { baseUpdatedAt: (0, moment_timezone_1.default)().toDate() });
|
|
313
|
-
});
|
|
314
|
-
if (workflow)
|
|
315
|
-
yield workflow(batchCreateDataList);
|
|
316
|
-
if (upsert) {
|
|
317
|
-
const bulkOps = batchCreateDataList.map((eachData) => ({
|
|
318
|
-
updateOne: {
|
|
319
|
-
filter: { _id: eachData._id },
|
|
320
|
-
update: { $set: eachData },
|
|
321
|
-
upsert: true,
|
|
322
|
-
},
|
|
323
|
-
}));
|
|
324
|
-
yield mongoCollection.bulkWrite(bulkOps);
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
yield mongoCollection.insertMany(batchCreateDataList);
|
|
328
|
-
}
|
|
329
|
-
const resBody = { success: ids };
|
|
330
|
-
if ((_a = req.body) === null || _a === void 0 ? void 0 : _a.stopRes)
|
|
331
|
-
return resBody;
|
|
332
|
-
res.send(resBody);
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
res.status(400).json({ err: "Invalid Fields" });
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
catch (err) {
|
|
339
|
-
res.status(400).json({ err: err });
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
this.initCreate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
343
|
-
var _b, _c;
|
|
344
|
-
try {
|
|
345
|
-
const valid = this.modelChecker(req.body.data);
|
|
346
|
-
if (valid) {
|
|
347
|
-
//INFO : Security Checker
|
|
348
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
349
|
-
const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "create", req, req.body.data);
|
|
350
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
351
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
const mongoCollection = this.mongoDB
|
|
355
|
-
.db(this.tableId)
|
|
356
|
-
.collection(this.collection);
|
|
357
|
-
req.body.data["baseUpdatedAt"] = (0, moment_timezone_1.default)().toDate();
|
|
358
|
-
if (req.body.unique && ((_b = req.body.data) === null || _b === void 0 ? void 0 : _b[req.body.unique])) {
|
|
359
|
-
const isDataExists = yield mongoCollection.findOne({
|
|
360
|
-
[req.body.unique]: req.body.data[req.body.unique],
|
|
361
|
-
});
|
|
362
|
-
if (isDataExists) {
|
|
363
|
-
res
|
|
364
|
-
.status(400)
|
|
365
|
-
.json({ err: `Unique:${req.body.data[req.body.unique]} exists` });
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (workflow)
|
|
370
|
-
yield workflow(req.body.data);
|
|
371
|
-
const mongoResult = yield mongoCollection.insertOne(req.body.data);
|
|
372
|
-
const mongoId = mongoResult.insertedId.toString();
|
|
373
|
-
yield this.handleLogging(mongoId, "create", req);
|
|
374
|
-
const resBody = { success: true };
|
|
375
|
-
if ((_c = req.body) === null || _c === void 0 ? void 0 : _c.stopRes)
|
|
376
|
-
return resBody;
|
|
377
|
-
res.send(resBody);
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
res.status(400).json({ err: "Invalid Model Structure" });
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
catch (err) {
|
|
384
|
-
res.status(400).json({ err: err });
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
this.initGet = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
388
|
-
var _d;
|
|
389
|
-
try {
|
|
390
|
-
const valid = req.body.id;
|
|
391
|
-
if (valid) {
|
|
392
|
-
//INFO : Security Checker
|
|
393
|
-
const mongoCollection = this.mongoDB
|
|
394
|
-
.db(this.tableId)
|
|
395
|
-
.collection(this.collection);
|
|
396
|
-
const pipeline = this.handleBuildPipeline({
|
|
397
|
-
body: Object.assign(Object.assign({}, req.body), { query: [{ type: "=", queryId: "_id", value: valid }] }),
|
|
398
|
-
});
|
|
399
|
-
const [mongoData] = yield mongoCollection.aggregate(pipeline).toArray();
|
|
400
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
401
|
-
const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "read", req, mongoData);
|
|
402
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
403
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
const resBody = { data: mongoData };
|
|
407
|
-
if ((_d = req.body) === null || _d === void 0 ? void 0 : _d.stopRes)
|
|
408
|
-
return resBody;
|
|
409
|
-
res.send(resBody);
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
res.status(400).json({ err: "Invalid Fields" });
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
catch (err) {
|
|
416
|
-
res.status(400).json({ err: err });
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
this.initBatchUpdate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
420
|
-
var _e, _f, _g;
|
|
421
|
-
try {
|
|
422
|
-
const valid = (this.modelChecker(req.body.data) && req.body.query) ||
|
|
423
|
-
req.body.unsetData;
|
|
424
|
-
if (valid) {
|
|
425
|
-
const unsetData = req.body.unsetData;
|
|
426
|
-
const queryList = (_e = req.body.query) !== null && _e !== void 0 ? _e : [];
|
|
427
|
-
const queryType = req.body.isOr ? "$or" : "$and";
|
|
428
|
-
const queryFilter = {};
|
|
429
|
-
const data = this.parseModel((_f = req.body.data) !== null && _f !== void 0 ? _f : []);
|
|
430
|
-
// INFO : Step 1 - Query
|
|
431
|
-
if (queryList && queryList.length > 0) {
|
|
432
|
-
queryFilter[queryType] = [];
|
|
433
|
-
// INFO : To Ensure There is OR Filter on Search
|
|
434
|
-
if (queryList.some((eachQuery) => eachQuery.type === "search")) {
|
|
435
|
-
queryFilter["$or"] = [];
|
|
436
|
-
}
|
|
437
|
-
queryList.map((eachQuery) => {
|
|
438
|
-
var _a;
|
|
439
|
-
const queryId = (_a = eachQuery.queryId) !== null && _a !== void 0 ? _a : "";
|
|
440
|
-
const value = eachQuery.value;
|
|
441
|
-
switch (eachQuery.type) {
|
|
442
|
-
case "search":
|
|
443
|
-
if (eachQuery.searchIds && eachQuery.searchIds.length > 0) {
|
|
444
|
-
eachQuery.searchIds.map((eachSearchId) => {
|
|
445
|
-
queryFilter["$or"].push({
|
|
446
|
-
[eachSearchId]: {
|
|
447
|
-
$regex: (0, utils_1.handleSpecialWordsEscapeRegex)(value),
|
|
448
|
-
$options: "i",
|
|
449
|
-
},
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
break;
|
|
454
|
-
case "=":
|
|
455
|
-
queryFilter[queryType].push({
|
|
456
|
-
[queryId]: value,
|
|
457
|
-
});
|
|
458
|
-
break;
|
|
459
|
-
case "!=":
|
|
460
|
-
queryFilter[queryType].push({
|
|
461
|
-
[queryId]: { $ne: value },
|
|
462
|
-
});
|
|
463
|
-
break;
|
|
464
|
-
case ">":
|
|
465
|
-
queryFilter[queryType].push({
|
|
466
|
-
[queryId]: { $gt: value },
|
|
467
|
-
});
|
|
468
|
-
break;
|
|
469
|
-
case "<":
|
|
470
|
-
queryFilter[queryType].push({
|
|
471
|
-
[queryId]: { $lt: value },
|
|
472
|
-
});
|
|
473
|
-
break;
|
|
474
|
-
case "><":
|
|
475
|
-
if (Array.isArray(value) && value.length >= 2) {
|
|
476
|
-
queryFilter[queryType] = {
|
|
477
|
-
[queryId]: { $gte: value[0], $lte: value[1] },
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
break;
|
|
481
|
-
case "in":
|
|
482
|
-
queryFilter[queryType].push({
|
|
483
|
-
[queryId]: { $in: value },
|
|
484
|
-
});
|
|
485
|
-
break;
|
|
486
|
-
case "!in":
|
|
487
|
-
queryFilter[queryType].push({
|
|
488
|
-
[queryId]: { $nin: value },
|
|
489
|
-
});
|
|
490
|
-
break;
|
|
491
|
-
case "exists":
|
|
492
|
-
queryFilter[queryType].push({
|
|
493
|
-
$exists: value, // `true` if field should exist, `false` if field should not exist
|
|
494
|
-
});
|
|
495
|
-
break;
|
|
496
|
-
case "elemMatch":
|
|
497
|
-
queryFilter[queryType].push({
|
|
498
|
-
[queryId]: { $elemMatch: value },
|
|
499
|
-
});
|
|
500
|
-
break;
|
|
501
|
-
default:
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
507
|
-
//INFO : Security Checker
|
|
508
|
-
let validOpsConfig = true;
|
|
509
|
-
const mongoCollection = this.mongoDB
|
|
510
|
-
.db(this.tableId)
|
|
511
|
-
.collection(this.collection);
|
|
512
|
-
const mongoDataRes = yield mongoCollection.find(Object.assign({}, queryFilter));
|
|
513
|
-
const mongoDataList = yield mongoDataRes.toArray();
|
|
514
|
-
const workflowUpdateFieldsList = [];
|
|
515
|
-
yield Promise.all(mongoDataList.map((eachData) => {
|
|
516
|
-
// INFO : Check Sensitive
|
|
517
|
-
if (req.body.sensitive) {
|
|
518
|
-
if (!(0, moment_timezone_1.default)(req.body.data.baseUpdatedAt).isAfter((0, moment_timezone_1.default)(eachData.baseUpdatedAt))) {
|
|
519
|
-
res.status(400).json({ err: "Refresh Sensitive Model" });
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
// INFO : Check Ops Config
|
|
523
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "update", req, eachData)) {
|
|
524
|
-
validOpsConfig = false;
|
|
525
|
-
}
|
|
526
|
-
const { workflowUpdateFields } = (0, utils_1.compareUpdatedFields)(eachData, req.body.data);
|
|
527
|
-
workflowUpdateFieldsList.push(Object.assign(Object.assign({}, workflowUpdateFields), { _id: eachData === null || eachData === void 0 ? void 0 : eachData._id }));
|
|
528
|
-
}));
|
|
529
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
530
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
const $unset = {};
|
|
534
|
-
const condition = {};
|
|
535
|
-
if (unsetData) {
|
|
536
|
-
unsetData.forEach((eachField) => {
|
|
537
|
-
$unset[eachField] = "";
|
|
538
|
-
});
|
|
539
|
-
condition["$unset"] = Object.assign({}, $unset);
|
|
540
|
-
}
|
|
541
|
-
if (data) {
|
|
542
|
-
condition["$set"] = Object.assign({}, data);
|
|
543
|
-
}
|
|
544
|
-
if (workflow)
|
|
545
|
-
yield workflow(workflowUpdateFieldsList);
|
|
546
|
-
yield mongoCollection.updateMany(queryFilter, condition);
|
|
547
|
-
const ids = workflowUpdateFieldsList.map((eachData) => eachData._id);
|
|
548
|
-
const resBody = { success: ids };
|
|
549
|
-
if ((_g = req.body) === null || _g === void 0 ? void 0 : _g.stopRes)
|
|
550
|
-
return resBody;
|
|
551
|
-
res.send(resBody);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
catch (err) {
|
|
555
|
-
res.status(400).json({ err: err });
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
this.initUpdate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
559
|
-
var _h, _j, _k;
|
|
560
|
-
try {
|
|
561
|
-
const valid = this.modelChecker(req.body.data) && req.body.id;
|
|
562
|
-
if (valid) {
|
|
563
|
-
const upsert = req.body.upsert ? true : false;
|
|
564
|
-
let mongoData = {};
|
|
565
|
-
const mongoCollection = this.mongoDB
|
|
566
|
-
.db(this.tableId)
|
|
567
|
-
.collection(this.collection);
|
|
568
|
-
if (!upsert)
|
|
569
|
-
mongoData = yield mongoCollection.findOne({
|
|
570
|
-
_id: valid,
|
|
571
|
-
});
|
|
572
|
-
if (this.debug)
|
|
573
|
-
this.debug(req.body, mongoData);
|
|
574
|
-
//INFO : Security Checker
|
|
575
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
576
|
-
const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "update", req, mongoData);
|
|
577
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
578
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
if (req.body.unique && ((_h = req.body.data) === null || _h === void 0 ? void 0 : _h[req.body.unique])) {
|
|
582
|
-
const isDataExists = yield mongoCollection.findOne({
|
|
583
|
-
[req.body.unique]: req.body.data[req.body.unique],
|
|
584
|
-
});
|
|
585
|
-
if (isDataExists && req.body.id !== isDataExists._id) {
|
|
586
|
-
res
|
|
587
|
-
.status(400)
|
|
588
|
-
.json({ err: `${req.body.data[req.body.unique]} exists` });
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
const { updatedFields } = (0, utils_1.compareUpdatedFields)(mongoData, req.body.data);
|
|
593
|
-
const resBody = { success: true };
|
|
594
|
-
if (workflow)
|
|
595
|
-
yield workflow(Object.assign(Object.assign({}, updatedFields), { _id: valid }));
|
|
596
|
-
const data = this.parseModel(updatedFields);
|
|
597
|
-
if (req.body.sensitive) {
|
|
598
|
-
if ((0, moment_timezone_1.default)(req.body.data.baseUpdatedAt).isAfter((0, moment_timezone_1.default)(mongoData.baseUpdatedAt))) {
|
|
599
|
-
yield mongoCollection.updateOne({
|
|
600
|
-
_id: valid,
|
|
601
|
-
}, {
|
|
602
|
-
$set: Object.assign({}, data),
|
|
603
|
-
}, { upsert: upsert });
|
|
604
|
-
if ((_j = req.body) === null || _j === void 0 ? void 0 : _j.stopRes)
|
|
605
|
-
return resBody;
|
|
606
|
-
res.send(resBody);
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
res.status(400).json({ err: "Refresh Sensitive Model" });
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
yield mongoCollection.updateOne({
|
|
614
|
-
_id: valid,
|
|
615
|
-
}, {
|
|
616
|
-
$set: Object.assign({}, data),
|
|
617
|
-
}, { upsert: upsert });
|
|
618
|
-
if ((_k = req.body) === null || _k === void 0 ? void 0 : _k.stopRes)
|
|
619
|
-
return resBody;
|
|
620
|
-
res.send(resBody);
|
|
621
|
-
}
|
|
622
|
-
const oldData = {};
|
|
623
|
-
Object.keys(data).map((eachUpdateKey) => {
|
|
624
|
-
oldData[eachUpdateKey] = mongoData[eachUpdateKey];
|
|
625
|
-
});
|
|
626
|
-
yield this.handleLogging(valid, "update", req, {
|
|
627
|
-
old: oldData,
|
|
628
|
-
new: data,
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
else {
|
|
632
|
-
res.status(400).json({ err: "Invalid Model Structure" });
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
catch (err) {
|
|
636
|
-
if (this.debug)
|
|
637
|
-
this.debug(null, null, err);
|
|
638
|
-
res.status(400).json({ err: err });
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
this.initBatchDelete = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
642
|
-
var _l, _m, _o, _p, _q, _r;
|
|
643
|
-
try {
|
|
644
|
-
if ((!Array.isArray(req.body.id) || ((_m = (_l = req.body.id) === null || _l === void 0 ? void 0 : _l.length) !== null && _m !== void 0 ? _m : 0) === 0) &&
|
|
645
|
-
(!Array.isArray(req.body.query) || ((_p = (_o = req.body.query) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : 0) === 0)) {
|
|
646
|
-
throw "Invalid Batch Delete Config";
|
|
647
|
-
}
|
|
648
|
-
if (Array.isArray(req.body.id)) {
|
|
649
|
-
const mongoCollection = this.mongoDB
|
|
650
|
-
.db(this.tableId)
|
|
651
|
-
.collection(this.collection);
|
|
652
|
-
const mongoQuery = yield mongoCollection.find({
|
|
653
|
-
_id: { $in: req.body.id },
|
|
654
|
-
});
|
|
655
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
656
|
-
const dataList = yield mongoQuery.toArray();
|
|
657
|
-
//INFO : Security Checker
|
|
658
|
-
let validOpsConfig = true;
|
|
659
|
-
if (dataList.length > 0) {
|
|
660
|
-
yield Promise.all(dataList.map((eachData) => {
|
|
661
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "delete", req, eachData)) {
|
|
662
|
-
validOpsConfig = false;
|
|
663
|
-
}
|
|
664
|
-
}));
|
|
665
|
-
}
|
|
666
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
667
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
if (workflow)
|
|
671
|
-
yield workflow(dataList);
|
|
672
|
-
yield mongoCollection.deleteMany({
|
|
673
|
-
_id: { $in: req.body.id },
|
|
674
|
-
});
|
|
675
|
-
const resBody = { success: req.body.id };
|
|
676
|
-
if ((_q = req.body) === null || _q === void 0 ? void 0 : _q.stopRes)
|
|
677
|
-
return resBody;
|
|
678
|
-
res.send(resBody);
|
|
679
|
-
}
|
|
680
|
-
else {
|
|
681
|
-
const queryList = req.body.query;
|
|
682
|
-
const queryFilter = {};
|
|
683
|
-
if (queryList && queryList.length > 0) {
|
|
684
|
-
queryList.map((eachQuery) => {
|
|
685
|
-
var _a;
|
|
686
|
-
const queryId = (_a = eachQuery.queryId) !== null && _a !== void 0 ? _a : "";
|
|
687
|
-
const value = eachQuery.value;
|
|
688
|
-
switch (eachQuery.type) {
|
|
689
|
-
case "search":
|
|
690
|
-
if (eachQuery.searchIds && eachQuery.searchIds.length > 0) {
|
|
691
|
-
queryFilter["$or"] = [];
|
|
692
|
-
eachQuery.searchIds.map((eachSearchId) => {
|
|
693
|
-
queryFilter["$or"].push({
|
|
694
|
-
[eachSearchId]: {
|
|
695
|
-
$regex: (0, utils_1.handleSpecialWordsEscapeRegex)(value),
|
|
696
|
-
$options: "i",
|
|
697
|
-
},
|
|
698
|
-
});
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
break;
|
|
702
|
-
case "=":
|
|
703
|
-
queryFilter[queryId] = value;
|
|
704
|
-
break;
|
|
705
|
-
case "!=":
|
|
706
|
-
queryFilter[queryId] = {
|
|
707
|
-
$ne: value,
|
|
708
|
-
};
|
|
709
|
-
break;
|
|
710
|
-
case ">":
|
|
711
|
-
queryFilter[queryId] = {
|
|
712
|
-
$gt: value,
|
|
713
|
-
};
|
|
714
|
-
break;
|
|
715
|
-
case "<":
|
|
716
|
-
queryFilter[queryId] = {
|
|
717
|
-
$lt: value,
|
|
718
|
-
};
|
|
719
|
-
break;
|
|
720
|
-
case "><":
|
|
721
|
-
if (Array.isArray(value) && value.length >= 2) {
|
|
722
|
-
queryFilter[queryId] = {
|
|
723
|
-
$gte: value[0],
|
|
724
|
-
$lte: value[1],
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
break;
|
|
728
|
-
case "in":
|
|
729
|
-
queryFilter[queryId] = {
|
|
730
|
-
$in: value,
|
|
731
|
-
};
|
|
732
|
-
break;
|
|
733
|
-
case "!in":
|
|
734
|
-
queryFilter[queryId] = {
|
|
735
|
-
$nin: value,
|
|
736
|
-
};
|
|
737
|
-
break;
|
|
738
|
-
case "exists":
|
|
739
|
-
queryFilter[queryId] = {
|
|
740
|
-
$exists: value, // `true` if field should exist, `false` if field should not exist
|
|
741
|
-
};
|
|
742
|
-
break;
|
|
743
|
-
case "elemMatch":
|
|
744
|
-
queryFilter[queryId] = {
|
|
745
|
-
$elemMatch: value,
|
|
746
|
-
};
|
|
747
|
-
break;
|
|
748
|
-
default:
|
|
749
|
-
break;
|
|
750
|
-
}
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
const mongoCollection = this.mongoDB
|
|
754
|
-
.db(this.tableId)
|
|
755
|
-
.collection(this.collection);
|
|
756
|
-
const mongoQuery = mongoCollection.find(queryFilter);
|
|
757
|
-
const dataList = yield mongoQuery.toArray();
|
|
758
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
759
|
-
//INFO : Security Checker
|
|
760
|
-
let validOpsConfig = true;
|
|
761
|
-
const ids = [];
|
|
762
|
-
if (dataList.length > 0) {
|
|
763
|
-
dataList.map((eachData) => {
|
|
764
|
-
ids.push(eachData._id);
|
|
765
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "delete", req, eachData)) {
|
|
766
|
-
validOpsConfig = false;
|
|
767
|
-
}
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
if (workflow)
|
|
771
|
-
yield workflow(dataList);
|
|
772
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
773
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
774
|
-
return;
|
|
775
|
-
}
|
|
776
|
-
yield mongoCollection.deleteMany(queryFilter);
|
|
777
|
-
const resBody = { success: ids };
|
|
778
|
-
if ((_r = req.body) === null || _r === void 0 ? void 0 : _r.stopRes)
|
|
779
|
-
return resBody;
|
|
780
|
-
res.send(resBody);
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
catch (err) {
|
|
784
|
-
res.status(400).json({ err: err });
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
this.initDelete = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
|
|
788
|
-
var _s;
|
|
789
|
-
try {
|
|
790
|
-
const valid = req.body.id;
|
|
791
|
-
if (valid) {
|
|
792
|
-
const mongoCollection = this.mongoDB
|
|
793
|
-
.db(this.tableId)
|
|
794
|
-
.collection(this.collection);
|
|
795
|
-
//INFO : Security Checker
|
|
796
|
-
const mongoData = yield mongoCollection.findOne({
|
|
797
|
-
_id: valid,
|
|
798
|
-
});
|
|
799
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
800
|
-
const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "delete", req, mongoData);
|
|
801
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
802
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
if (workflow)
|
|
806
|
-
yield workflow(mongoData);
|
|
807
|
-
yield mongoCollection.findOneAndDelete({
|
|
808
|
-
_id: valid,
|
|
809
|
-
});
|
|
810
|
-
yield this.handleLogging(mongoData._id, "delete", req, {
|
|
811
|
-
new: mongoData,
|
|
812
|
-
});
|
|
813
|
-
const resBody = { success: true };
|
|
814
|
-
if ((_s = req.body) === null || _s === void 0 ? void 0 : _s.stopRes)
|
|
815
|
-
return resBody;
|
|
816
|
-
res.send(resBody);
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
res.status(400).json({ err: "Invalid Fields" });
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
catch (err) {
|
|
823
|
-
res.status(400).json({ err: err });
|
|
824
|
-
}
|
|
825
|
-
});
|
|
826
|
-
this.initList = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
827
|
-
var _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10;
|
|
828
|
-
try {
|
|
829
|
-
//INFO : Security Checker
|
|
830
|
-
const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
|
|
831
|
-
if (validBaseConfig) {
|
|
832
|
-
const aggregate = req.body.aggregate;
|
|
833
|
-
const unionCollections = (_t = req.body.unionCollections) !== null && _t !== void 0 ? _t : [];
|
|
834
|
-
const queryList = (_u = req.body.query) !== null && _u !== void 0 ? _u : [];
|
|
835
|
-
let queryFilter = {};
|
|
836
|
-
// INFO : Step 1 - Query
|
|
837
|
-
queryFilter = handleParseQueryFilter(queryList);
|
|
838
|
-
if (unionCollections &&
|
|
839
|
-
Array.isArray(unionCollections) &&
|
|
840
|
-
unionCollections.length > 0) {
|
|
841
|
-
if (aggregate) {
|
|
842
|
-
res.status(400).json({
|
|
843
|
-
err: "Union operations cannot be combined with aggregate",
|
|
844
|
-
});
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
const sort = (_v = req.body.sort) !== null && _v !== void 0 ? _v : { date: -1 };
|
|
848
|
-
const limit = (_w = req.body.limit) !== null && _w !== void 0 ? _w : 50;
|
|
849
|
-
const skip = (_y = (_x = req.body.cursor) !== null && _x !== void 0 ? _x : req.body.skip) !== null && _y !== void 0 ? _y : 0;
|
|
850
|
-
const pipeline = [];
|
|
851
|
-
// Build unionWith pipeline
|
|
852
|
-
unionCollections.forEach((collectionConfig, index) => {
|
|
853
|
-
const projectStage = {
|
|
854
|
-
$project: Object.assign({ _id: 1 }, collectionConfig.projection),
|
|
855
|
-
};
|
|
856
|
-
// INFO: sourceLogic can be a string literal or a MongoDB expression object
|
|
857
|
-
if (collectionConfig.sourceLogic) {
|
|
858
|
-
projectStage.$project.source =
|
|
859
|
-
typeof collectionConfig.sourceLogic === "string"
|
|
860
|
-
? { $literal: collectionConfig.sourceLogic }
|
|
861
|
-
: collectionConfig.sourceLogic;
|
|
862
|
-
}
|
|
863
|
-
else {
|
|
864
|
-
projectStage.$project.source = {
|
|
865
|
-
$literal: collectionConfig.source,
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
if (index === 0) {
|
|
869
|
-
if (queryList && queryList.length > 0) {
|
|
870
|
-
pipeline.push({ $match: queryFilter });
|
|
871
|
-
}
|
|
872
|
-
if (collectionConfig.query && collectionConfig.query.length > 0) {
|
|
873
|
-
const collectionQueryFilter = handleParseQueryFilter(collectionConfig.query);
|
|
874
|
-
pipeline.push({ $match: collectionQueryFilter });
|
|
875
|
-
}
|
|
876
|
-
// INFO: addFields must be before $project so computed fields are available for sorting
|
|
877
|
-
if (collectionConfig.addFields) {
|
|
878
|
-
pipeline.push({ $addFields: collectionConfig.addFields });
|
|
879
|
-
// INFO: also include addFields keys in projection so they survive the $project stage
|
|
880
|
-
Object.keys(collectionConfig.addFields).forEach((key) => {
|
|
881
|
-
projectStage.$project[key] = 1;
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
pipeline.push(projectStage);
|
|
885
|
-
}
|
|
886
|
-
else {
|
|
887
|
-
const unionPipeline = [];
|
|
888
|
-
if (collectionConfig.query && collectionConfig.query.length > 0) {
|
|
889
|
-
const collectionQueryFilter = handleParseQueryFilter(collectionConfig.query);
|
|
890
|
-
unionPipeline.push({ $match: collectionQueryFilter });
|
|
891
|
-
}
|
|
892
|
-
// INFO: addFields must be before $project so computed fields are available for sorting
|
|
893
|
-
if (collectionConfig.addFields) {
|
|
894
|
-
unionPipeline.push({ $addFields: collectionConfig.addFields });
|
|
895
|
-
// INFO: also include addFields keys in projection so they survive the $project stage
|
|
896
|
-
Object.keys(collectionConfig.addFields).forEach((key) => {
|
|
897
|
-
projectStage.$project[key] = 1;
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
unionPipeline.push(projectStage);
|
|
901
|
-
const unionStage = {
|
|
902
|
-
$unionWith: {
|
|
903
|
-
coll: collectionConfig.collection,
|
|
904
|
-
pipeline: unionPipeline,
|
|
905
|
-
},
|
|
906
|
-
};
|
|
907
|
-
pipeline.push(unionStage);
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
if (sort) {
|
|
911
|
-
const sortStage = { $sort: {} };
|
|
912
|
-
if (Array.isArray(sort)) {
|
|
913
|
-
sort.forEach((sortItem) => {
|
|
914
|
-
if (sortItem.sortId) {
|
|
915
|
-
sortStage.$sort[sortItem.sortId] =
|
|
916
|
-
sortItem.type === "asc" ? 1 : -1;
|
|
917
|
-
}
|
|
918
|
-
});
|
|
919
|
-
}
|
|
920
|
-
else if (sort.sortId && sort.type) {
|
|
921
|
-
sortStage.$sort[sort.sortId] = sort.type === "asc" ? 1 : -1;
|
|
922
|
-
}
|
|
923
|
-
else {
|
|
924
|
-
sortStage.$sort = sort;
|
|
925
|
-
}
|
|
926
|
-
pipeline.push(sortStage);
|
|
927
|
-
}
|
|
928
|
-
if (skip > 0) {
|
|
929
|
-
pipeline.push({ $skip: skip });
|
|
930
|
-
}
|
|
931
|
-
if (limit > 0) {
|
|
932
|
-
pipeline.push({ $limit: limit });
|
|
933
|
-
}
|
|
934
|
-
const mongoCollection = this.mongoDB
|
|
935
|
-
.db(this.tableId)
|
|
936
|
-
.collection(this.collection);
|
|
937
|
-
const dataList = yield mongoCollection.aggregate(pipeline).toArray();
|
|
938
|
-
const countPipeline = pipeline.filter((stage) => {
|
|
939
|
-
const stageKey = Object.keys(stage)[0];
|
|
940
|
-
return stageKey !== "$skip" && stageKey !== "$limit";
|
|
941
|
-
});
|
|
942
|
-
countPipeline.push({ $count: "total" });
|
|
943
|
-
const countResult = yield mongoCollection
|
|
944
|
-
.aggregate(countPipeline)
|
|
945
|
-
.toArray();
|
|
946
|
-
const count = ((_z = countResult[0]) === null || _z === void 0 ? void 0 : _z.total) || 0;
|
|
947
|
-
let validOpsConfig = true;
|
|
948
|
-
dataList.map((eachData) => {
|
|
949
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "read", req, eachData)) {
|
|
950
|
-
validOpsConfig = false;
|
|
951
|
-
}
|
|
952
|
-
});
|
|
953
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
954
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
955
|
-
return;
|
|
956
|
-
}
|
|
957
|
-
const resBody = {
|
|
958
|
-
data: dataList,
|
|
959
|
-
count,
|
|
960
|
-
};
|
|
961
|
-
if ((_0 = req.body) === null || _0 === void 0 ? void 0 : _0.stopRes)
|
|
962
|
-
return resBody;
|
|
963
|
-
res.send(resBody);
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
966
|
-
if (aggregate) {
|
|
967
|
-
const dataList = [];
|
|
968
|
-
const queryId = (_1 = aggregate.queryId) !== null && _1 !== void 0 ? _1 : "";
|
|
969
|
-
const dateId = (_2 = aggregate.dateId) !== null && _2 !== void 0 ? _2 : "baseUpdatedAt";
|
|
970
|
-
const timezone = aggregate.timezone || "Asia/Kuala_Lumpur";
|
|
971
|
-
const dateRanges = (_3 = aggregate.range) !== null && _3 !== void 0 ? _3 : [
|
|
972
|
-
(0, moment_timezone_1.default)().tz(timezone).format("DD/MM/YYYY HH:mm:ss"),
|
|
973
|
-
];
|
|
974
|
-
for (const dateRange of dateRanges) {
|
|
975
|
-
let matchFilter = {
|
|
976
|
-
$match: Object.assign({}, queryFilter),
|
|
977
|
-
};
|
|
978
|
-
const date = dateRange.split("-");
|
|
979
|
-
const [startDate, endDate = (0, moment_timezone_1.default)().tz(timezone).format("DD/MM/YYYY HH:mm:ss"),] = date;
|
|
980
|
-
const isDuration = date.length === 2;
|
|
981
|
-
const isValidStartDate = moment_timezone_1.default
|
|
982
|
-
.tz(startDate, "DD/MM/YYYY HH:mm:ss", timezone)
|
|
983
|
-
.isValid();
|
|
984
|
-
const isValidEndDate = moment_timezone_1.default
|
|
985
|
-
.tz(endDate, "DD/MM/YYYY HH:mm:ss", timezone)
|
|
986
|
-
.isValid();
|
|
987
|
-
const isoStartDate = moment_timezone_1.default
|
|
988
|
-
.tz(startDate, "DD/MM/YYYY HH:mm:ss", timezone)
|
|
989
|
-
.utc()
|
|
990
|
-
.toDate();
|
|
991
|
-
const isoEndDate = moment_timezone_1.default
|
|
992
|
-
.tz(endDate, "DD/MM/YYYY HH:mm:ss", timezone)
|
|
993
|
-
.utc()
|
|
994
|
-
.toDate();
|
|
995
|
-
if (!isValidStartDate || !isValidEndDate) {
|
|
996
|
-
res
|
|
997
|
-
.status(400)
|
|
998
|
-
.json({ err: "Invalid Aggregate Range Configuration" });
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
matchFilter = isDuration
|
|
1002
|
-
? {
|
|
1003
|
-
$match: Object.assign(Object.assign({}, queryFilter), { [dateId]: {
|
|
1004
|
-
$gte: isoStartDate,
|
|
1005
|
-
$lte: isoEndDate,
|
|
1006
|
-
} }),
|
|
1007
|
-
}
|
|
1008
|
-
: {
|
|
1009
|
-
$match: Object.assign(Object.assign({}, queryFilter), { [dateId]: {
|
|
1010
|
-
$lte: isoStartDate,
|
|
1011
|
-
} }),
|
|
1012
|
-
};
|
|
1013
|
-
const aggregationPipeline = [matchFilter];
|
|
1014
|
-
const id = isDuration
|
|
1015
|
-
? dateRange
|
|
1016
|
-
: `Begining until ${(0, moment_timezone_1.default)(startDate, "DD/MM/YYYY HH:mm:ss").format("DD/MM/YYYY")}`;
|
|
1017
|
-
let unwindUnique = false;
|
|
1018
|
-
if (aggregate.unwind && aggregate.unwind.length > 0) {
|
|
1019
|
-
aggregate.unwind.map((eachUnwind, index) => {
|
|
1020
|
-
var _a, _b, _c;
|
|
1021
|
-
const tempModel = "model" + index;
|
|
1022
|
-
let referenceModel = "";
|
|
1023
|
-
if (index > 0)
|
|
1024
|
-
referenceModel = "model" + (index - 1) + ".";
|
|
1025
|
-
const modelQueryFilter = handleParseQueryFilter((_a = eachUnwind.query) !== null && _a !== void 0 ? _a : [], tempModel);
|
|
1026
|
-
if ((_b = eachUnwind.unique) === null || _b === void 0 ? void 0 : _b.list)
|
|
1027
|
-
aggregationPipeline.push({
|
|
1028
|
-
$unwind: "$" + eachUnwind.localField,
|
|
1029
|
-
});
|
|
1030
|
-
aggregationPipeline.push({
|
|
1031
|
-
$lookup: {
|
|
1032
|
-
from: eachUnwind.collectionId,
|
|
1033
|
-
localField: referenceModel + eachUnwind.localField,
|
|
1034
|
-
foreignField: "_id",
|
|
1035
|
-
as: tempModel,
|
|
1036
|
-
},
|
|
1037
|
-
}, {
|
|
1038
|
-
$unwind: "$" + tempModel,
|
|
1039
|
-
}, {
|
|
1040
|
-
$match: modelQueryFilter,
|
|
1041
|
-
});
|
|
1042
|
-
if ((_c = eachUnwind.unique) === null || _c === void 0 ? void 0 : _c.type) {
|
|
1043
|
-
unwindUnique = true;
|
|
1044
|
-
const uniqueUnwindName = "uniqueUnwindId";
|
|
1045
|
-
aggregationPipeline.push({
|
|
1046
|
-
$group: {
|
|
1047
|
-
_id: id,
|
|
1048
|
-
[uniqueUnwindName]: {
|
|
1049
|
-
$addToSet: "$" + eachUnwind.localField,
|
|
1050
|
-
},
|
|
1051
|
-
},
|
|
1052
|
-
});
|
|
1053
|
-
if (eachUnwind.unique.type === "count")
|
|
1054
|
-
aggregationPipeline.push({
|
|
1055
|
-
$project: {
|
|
1056
|
-
value: { $size: "$" + uniqueUnwindName },
|
|
1057
|
-
},
|
|
1058
|
-
});
|
|
1059
|
-
else
|
|
1060
|
-
aggregationPipeline.push({
|
|
1061
|
-
$project: { _id: 0, value: "$" + uniqueUnwindName },
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
if (!unwindUnique) {
|
|
1067
|
-
let groupId = id;
|
|
1068
|
-
if (aggregate.groupId)
|
|
1069
|
-
groupId = "$" + aggregate.groupId;
|
|
1070
|
-
switch (aggregate.type) {
|
|
1071
|
-
case "avg":
|
|
1072
|
-
aggregationPipeline.push({
|
|
1073
|
-
$group: {
|
|
1074
|
-
_id: groupId,
|
|
1075
|
-
value: { $avg: `$${queryId}` },
|
|
1076
|
-
},
|
|
1077
|
-
});
|
|
1078
|
-
break;
|
|
1079
|
-
case "sum":
|
|
1080
|
-
aggregationPipeline.push({
|
|
1081
|
-
$group: {
|
|
1082
|
-
_id: groupId,
|
|
1083
|
-
value: { $sum: `$${queryId}` },
|
|
1084
|
-
},
|
|
1085
|
-
});
|
|
1086
|
-
break;
|
|
1087
|
-
case "count":
|
|
1088
|
-
aggregationPipeline.push({
|
|
1089
|
-
$group: {
|
|
1090
|
-
_id: groupId,
|
|
1091
|
-
value: { $sum: 1 },
|
|
1092
|
-
ids: { $push: "$_id" },
|
|
1093
|
-
},
|
|
1094
|
-
});
|
|
1095
|
-
break;
|
|
1096
|
-
default:
|
|
1097
|
-
break;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
if (aggregationPipeline.length === 0) {
|
|
1101
|
-
res.status(400).json({ err: "Invalid Aggregate Configuration" });
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
const mongoCollection = this.mongoDB
|
|
1105
|
-
.db(this.tableId)
|
|
1106
|
-
.collection(this.collection);
|
|
1107
|
-
let value = 0;
|
|
1108
|
-
let ids = [];
|
|
1109
|
-
const mongoQuery = mongoCollection.aggregate(aggregationPipeline);
|
|
1110
|
-
const result = yield mongoQuery.toArray();
|
|
1111
|
-
if (aggregate.groupId)
|
|
1112
|
-
value = result;
|
|
1113
|
-
else {
|
|
1114
|
-
value = (_5 = (_4 = result[0]) === null || _4 === void 0 ? void 0 : _4.value) !== null && _5 !== void 0 ? _5 : 0;
|
|
1115
|
-
ids = (_7 = (_6 = result[0]) === null || _6 === void 0 ? void 0 : _6.ids) !== null && _7 !== void 0 ? _7 : [];
|
|
1116
|
-
}
|
|
1117
|
-
dataList.push({
|
|
1118
|
-
_id: id,
|
|
1119
|
-
value,
|
|
1120
|
-
ids,
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
const resBody = {
|
|
1124
|
-
data: dataList,
|
|
1125
|
-
};
|
|
1126
|
-
if ((_8 = req.body) === null || _8 === void 0 ? void 0 : _8.stopRes)
|
|
1127
|
-
return resBody;
|
|
1128
|
-
res.send(resBody);
|
|
1129
|
-
}
|
|
1130
|
-
else {
|
|
1131
|
-
const mongoCollection = this.mongoDB
|
|
1132
|
-
.db(this.tableId)
|
|
1133
|
-
.collection(this.collection);
|
|
1134
|
-
const pipeline = this.handleBuildPipeline(req);
|
|
1135
|
-
const countPipeline = pipeline.filter((stage) => {
|
|
1136
|
-
const stageKey = Object.keys(stage)[0];
|
|
1137
|
-
return stageKey !== "$skip" && stageKey !== "$limit";
|
|
1138
|
-
});
|
|
1139
|
-
countPipeline.push({ $count: "total" });
|
|
1140
|
-
const [dataList, countResult] = yield Promise.all([
|
|
1141
|
-
mongoCollection.aggregate(pipeline).toArray(),
|
|
1142
|
-
mongoCollection.aggregate(countPipeline).toArray(),
|
|
1143
|
-
]);
|
|
1144
|
-
const count = ((_9 = countResult[0]) === null || _9 === void 0 ? void 0 : _9.total) || 0;
|
|
1145
|
-
//INFO : Security Checker
|
|
1146
|
-
let validOpsConfig = true;
|
|
1147
|
-
if (dataList.length > 0) {
|
|
1148
|
-
dataList.map((eachData) => {
|
|
1149
|
-
if (!(0, QueryModel_1.checkOpsConfig)(this.config, "read", req, eachData)) {
|
|
1150
|
-
validOpsConfig = false;
|
|
1151
|
-
}
|
|
1152
|
-
});
|
|
1153
|
-
}
|
|
1154
|
-
if (!validBaseConfig || !validOpsConfig) {
|
|
1155
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
1156
|
-
return;
|
|
1157
|
-
}
|
|
1158
|
-
const resBody = {
|
|
1159
|
-
data: dataList,
|
|
1160
|
-
count,
|
|
1161
|
-
};
|
|
1162
|
-
if ((_10 = req.body) === null || _10 === void 0 ? void 0 : _10.stopRes)
|
|
1163
|
-
return resBody;
|
|
1164
|
-
res.send(resBody);
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
res.status(400).json({ err: "Invalid Security Configuration" });
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
catch (err) {
|
|
1172
|
-
res.status(400).json({
|
|
1173
|
-
err: err.message,
|
|
1174
|
-
});
|
|
1175
|
-
}
|
|
1176
|
-
});
|
|
1177
|
-
this.init = () => {
|
|
1178
|
-
const router = this.lib.express.Router();
|
|
1179
|
-
/**
|
|
1180
|
-
* @Input :
|
|
1181
|
-
* data - Model
|
|
1182
|
-
* unique - string (Optional)
|
|
1183
|
-
*/
|
|
1184
|
-
router.post("/create", (req, res) => {
|
|
1185
|
-
this.initCreate(req, res);
|
|
1186
|
-
});
|
|
1187
|
-
/**
|
|
1188
|
-
* @Input :
|
|
1189
|
-
* data - Model
|
|
1190
|
-
* unique - string (Optional)
|
|
1191
|
-
*/
|
|
1192
|
-
router.post("/batchCreate", (req, res) => {
|
|
1193
|
-
this.initBatchCreate(req, res);
|
|
1194
|
-
});
|
|
1195
|
-
/**
|
|
1196
|
-
* @Input :
|
|
1197
|
-
* id - string
|
|
1198
|
-
*/
|
|
1199
|
-
router.post("/get", (req, res) => {
|
|
1200
|
-
this.initGet(req, res);
|
|
1201
|
-
});
|
|
1202
|
-
/**
|
|
1203
|
-
* @Input :
|
|
1204
|
-
* data - Model
|
|
1205
|
-
* id - string
|
|
1206
|
-
* unique - string (Optional)
|
|
1207
|
-
*/
|
|
1208
|
-
router.post("/update", (req, res) => {
|
|
1209
|
-
this.initUpdate(req, res);
|
|
1210
|
-
});
|
|
1211
|
-
/**
|
|
1212
|
-
* @Input :
|
|
1213
|
-
* data - Model
|
|
1214
|
-
* query - Query[]
|
|
1215
|
-
* unsetData - string[] (Unset Attribute Id) (Optional)
|
|
1216
|
-
* isOr - boolean (Optional)
|
|
1217
|
-
*/
|
|
1218
|
-
router.post("/batchUpdate", (req, res) => {
|
|
1219
|
-
this.initBatchUpdate(req, res);
|
|
1220
|
-
});
|
|
1221
|
-
/**
|
|
1222
|
-
* @Input :
|
|
1223
|
-
* id - string
|
|
1224
|
-
*/
|
|
1225
|
-
router.post("/delete", (req, res) => {
|
|
1226
|
-
this.initDelete(req, res);
|
|
1227
|
-
});
|
|
1228
|
-
/**
|
|
1229
|
-
* @Input :
|
|
1230
|
-
* id - string[]
|
|
1231
|
-
*/
|
|
1232
|
-
router.post("/batchDelete", (req, res) => {
|
|
1233
|
-
this.initBatchDelete(req, res);
|
|
1234
|
-
});
|
|
1235
|
-
/**
|
|
1236
|
-
* @Input
|
|
1237
|
-
* query - Query interface (Optional)
|
|
1238
|
-
* unionCollections - Array of collection configs with source and projection (Optional)
|
|
1239
|
-
* cursor - any (Optional)
|
|
1240
|
-
* limit - number (Optional)
|
|
1241
|
-
* sort - Array Sort or Sort interface (Optional)
|
|
1242
|
-
* stopLimit - boolean to retreive all data (Optional)
|
|
1243
|
-
* uniqueLabel - string to ensure uniqueness of a field across returned documents (Optional)
|
|
1244
|
-
*/
|
|
1245
|
-
router.post("/list", (req, res) => {
|
|
1246
|
-
this.initList(req, res);
|
|
1247
|
-
});
|
|
1248
|
-
return router;
|
|
1249
|
-
};
|
|
1250
|
-
this.mongoDB = mongoDB;
|
|
1251
|
-
this.collection = collection;
|
|
1252
|
-
this.isProd = isProd;
|
|
1253
|
-
this.config = config;
|
|
1254
|
-
this.modelChecker = modelChecker;
|
|
1255
|
-
this.lib = lib;
|
|
1256
|
-
const tableSuffix = this.isProd ? "prod" : "dev";
|
|
1257
|
-
this.tableId = tableId ? `${tableId}-${tableSuffix}` : tableSuffix;
|
|
1258
|
-
this.logId = logId !== null && logId !== void 0 ? logId : "";
|
|
1259
|
-
this.logWorkflow = logWorkflow;
|
|
1260
|
-
this.logCollectIds = logCollectIds !== null && logCollectIds !== void 0 ? logCollectIds : [];
|
|
1261
|
-
this.debug = debug;
|
|
1262
|
-
}
|
|
1263
|
-
handleBuildPipeline(req) {
|
|
1264
|
-
const pipelineList = [];
|
|
1265
|
-
const addedForeignLookups = new Map();
|
|
1266
|
-
const addedSpaceReferences = new Set();
|
|
1267
|
-
const { query, sort, cursor, limit, stopLimit, pipeline, uniqueLabel, groupId, } = req.body;
|
|
1268
|
-
try {
|
|
1269
|
-
if (Array.isArray(pipeline) && pipeline.length > 0) {
|
|
1270
|
-
pipeline.forEach((link) => {
|
|
1271
|
-
const { condition, referenceSpaceLabel, spaceReferenceId, spaceReferenceAs, referenceSort, referenceFirstItem, referenceLimit, } = link;
|
|
1272
|
-
if (spaceReferenceId) {
|
|
1273
|
-
const defaultReferenceAs = spaceReferenceAs || "linkedData";
|
|
1274
|
-
addedSpaceReferences.add(defaultReferenceAs);
|
|
1275
|
-
const lookupStage = {
|
|
1276
|
-
$lookup: {
|
|
1277
|
-
from: spaceReferenceId,
|
|
1278
|
-
let: {},
|
|
1279
|
-
pipeline: [],
|
|
1280
|
-
as: defaultReferenceAs,
|
|
1281
|
-
},
|
|
1282
|
-
};
|
|
1283
|
-
if (condition && condition.length > 0) {
|
|
1284
|
-
condition.forEach((cond) => {
|
|
1285
|
-
lookupStage.$lookup.let[`local_${cond.fromColumnId}`] =
|
|
1286
|
-
`$${cond.fromColumnId}`;
|
|
1287
|
-
});
|
|
1288
|
-
const matchStage = {
|
|
1289
|
-
$match: { $expr: { $and: [] } },
|
|
1290
|
-
};
|
|
1291
|
-
condition.forEach((cond) => {
|
|
1292
|
-
const conditionExpr = {};
|
|
1293
|
-
switch (cond.type) {
|
|
1294
|
-
case "=":
|
|
1295
|
-
conditionExpr.$eq = [
|
|
1296
|
-
`$${cond.toColumnId}`,
|
|
1297
|
-
`$$local_${cond.fromColumnId}`,
|
|
1298
|
-
];
|
|
1299
|
-
break;
|
|
1300
|
-
case "!=":
|
|
1301
|
-
conditionExpr.$ne = [
|
|
1302
|
-
`$${cond.toColumnId}`,
|
|
1303
|
-
`$$local_${cond.fromColumnId}`,
|
|
1304
|
-
];
|
|
1305
|
-
break;
|
|
1306
|
-
case ">":
|
|
1307
|
-
conditionExpr.$gt = [
|
|
1308
|
-
`$${cond.toColumnId}`,
|
|
1309
|
-
`$$local_${cond.fromColumnId}`,
|
|
1310
|
-
];
|
|
1311
|
-
break;
|
|
1312
|
-
case "<":
|
|
1313
|
-
conditionExpr.$lt = [
|
|
1314
|
-
`$${cond.toColumnId}`,
|
|
1315
|
-
`$$local_${cond.fromColumnId}`,
|
|
1316
|
-
];
|
|
1317
|
-
break;
|
|
1318
|
-
case "in":
|
|
1319
|
-
conditionExpr.$in = [
|
|
1320
|
-
`$${cond.toColumnId}`,
|
|
1321
|
-
`$$local_${cond.fromColumnId}`,
|
|
1322
|
-
];
|
|
1323
|
-
break;
|
|
1324
|
-
case "!in":
|
|
1325
|
-
conditionExpr.$nin = [
|
|
1326
|
-
`$${cond.toColumnId}`,
|
|
1327
|
-
`$$local_${cond.fromColumnId}`,
|
|
1328
|
-
];
|
|
1329
|
-
break;
|
|
1330
|
-
}
|
|
1331
|
-
if (Object.keys(conditionExpr).length > 0) {
|
|
1332
|
-
matchStage.$match.$expr.$and.push(conditionExpr);
|
|
1333
|
-
}
|
|
1334
|
-
});
|
|
1335
|
-
lookupStage.$lookup.pipeline.push(matchStage);
|
|
1336
|
-
}
|
|
1337
|
-
if (referenceSort && referenceSort.sortId) {
|
|
1338
|
-
const sortStage = {
|
|
1339
|
-
$sort: {
|
|
1340
|
-
[referenceSort.sortId]: referenceSort.type === "asc" ? 1 : -1,
|
|
1341
|
-
},
|
|
1342
|
-
};
|
|
1343
|
-
lookupStage.$lookup.pipeline.push(sortStage);
|
|
1344
|
-
}
|
|
1345
|
-
if (referenceLimit) {
|
|
1346
|
-
const limitStage = {
|
|
1347
|
-
$limit: referenceLimit,
|
|
1348
|
-
};
|
|
1349
|
-
lookupStage.$lookup.pipeline.push(limitStage);
|
|
1350
|
-
}
|
|
1351
|
-
pipelineList.push(lookupStage);
|
|
1352
|
-
if (referenceSpaceLabel && referenceSpaceLabel.length > 0) {
|
|
1353
|
-
const addFieldsStage = { $addFields: {} };
|
|
1354
|
-
if (referenceFirstItem) {
|
|
1355
|
-
pipelineList.push({
|
|
1356
|
-
$addFields: {
|
|
1357
|
-
[defaultReferenceAs]: {
|
|
1358
|
-
$first: {
|
|
1359
|
-
$ifNull: [`$${defaultReferenceAs}`, []],
|
|
1360
|
-
},
|
|
1361
|
-
},
|
|
1362
|
-
},
|
|
1363
|
-
});
|
|
1364
|
-
referenceSpaceLabel.forEach((field) => {
|
|
1365
|
-
addFieldsStage.$addFields[`${defaultReferenceAs}_${field}`] =
|
|
1366
|
-
`$${defaultReferenceAs}.${field}`;
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
else {
|
|
1370
|
-
referenceSpaceLabel.forEach((field) => {
|
|
1371
|
-
addFieldsStage.$addFields[`${defaultReferenceAs}_${field}`] =
|
|
1372
|
-
{
|
|
1373
|
-
$map: {
|
|
1374
|
-
input: `$${defaultReferenceAs}`,
|
|
1375
|
-
in: `$$this.${field}`,
|
|
1376
|
-
},
|
|
1377
|
-
};
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
pipelineList.push(addFieldsStage);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
if (query && query.length > 0) {
|
|
1386
|
-
query.forEach((q) => {
|
|
1387
|
-
if (q.foreign && Array.isArray(q.foreign)) {
|
|
1388
|
-
q.foreign.forEach((foreignLookup) => {
|
|
1389
|
-
const alias = foreignLookup.alias;
|
|
1390
|
-
if (!addedForeignLookups.has(alias)) {
|
|
1391
|
-
pipelineList.push({
|
|
1392
|
-
$lookup: {
|
|
1393
|
-
from: foreignLookup.collection,
|
|
1394
|
-
localField: foreignLookup.localField,
|
|
1395
|
-
foreignField: "_id",
|
|
1396
|
-
as: alias,
|
|
1397
|
-
},
|
|
1398
|
-
});
|
|
1399
|
-
addedForeignLookups.set(alias, true);
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
1405
|
-
const sortStage = { $sort: {} };
|
|
1406
|
-
if (sort) {
|
|
1407
|
-
const sortItems = Array.isArray(JSON.parse(JSON.stringify(sort)))
|
|
1408
|
-
? sort
|
|
1409
|
-
: [sort];
|
|
1410
|
-
sortItems.forEach((sortItem) => {
|
|
1411
|
-
if (sortItem.sortId) {
|
|
1412
|
-
sortStage.$sort[sortItem.sortId] = sortItem.type === "asc" ? 1 : -1;
|
|
1413
|
-
}
|
|
1414
|
-
});
|
|
1415
|
-
}
|
|
1416
|
-
const isSortBeforeFilter = sort === null || sort === void 0 ? void 0 : sort.sortBeforeFilter;
|
|
1417
|
-
// INFO: If data is sorted then only filter, group must be before filter as well
|
|
1418
|
-
if (isSortBeforeFilter) {
|
|
1419
|
-
if (Object.keys(sortStage.$sort).length > 0) {
|
|
1420
|
-
pipelineList.push(sortStage);
|
|
1421
|
-
}
|
|
1422
|
-
if (uniqueLabel) {
|
|
1423
|
-
pipelineList.push({
|
|
1424
|
-
$group: {
|
|
1425
|
-
_id: `$${uniqueLabel}`,
|
|
1426
|
-
doc: { $first: "$$ROOT" },
|
|
1427
|
-
},
|
|
1428
|
-
});
|
|
1429
|
-
pipelineList.push({
|
|
1430
|
-
$replaceRoot: { newRoot: "$doc" },
|
|
1431
|
-
});
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
if (query && query.length > 0) {
|
|
1435
|
-
const filter = handleParseQueryFilter(query);
|
|
1436
|
-
pipelineList.push({ $match: filter });
|
|
1437
|
-
}
|
|
1438
|
-
// INFO: Default for mongoDB: filter then only sort
|
|
1439
|
-
if (!isSortBeforeFilter) {
|
|
1440
|
-
if (Object.keys(sortStage.$sort).length > 0) {
|
|
1441
|
-
pipelineList.push(sortStage);
|
|
1442
|
-
}
|
|
1443
|
-
if (uniqueLabel) {
|
|
1444
|
-
pipelineList.push({
|
|
1445
|
-
$group: {
|
|
1446
|
-
_id: `$${uniqueLabel}`,
|
|
1447
|
-
doc: { $first: "$$ROOT" },
|
|
1448
|
-
},
|
|
1449
|
-
});
|
|
1450
|
-
pipelineList.push({
|
|
1451
|
-
$replaceRoot: { newRoot: "$doc" },
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
// INFO: Group by groupId if provided
|
|
1456
|
-
if (groupId && !uniqueLabel) {
|
|
1457
|
-
pipelineList.push({
|
|
1458
|
-
$group: {
|
|
1459
|
-
_id: `$${groupId}`,
|
|
1460
|
-
topItem: { $first: "$$ROOT" },
|
|
1461
|
-
children: { $push: "$$ROOT" },
|
|
1462
|
-
},
|
|
1463
|
-
});
|
|
1464
|
-
pipelineList.push({
|
|
1465
|
-
$replaceRoot: {
|
|
1466
|
-
newRoot: {
|
|
1467
|
-
$mergeObjects: [
|
|
1468
|
-
"$topItem",
|
|
1469
|
-
{
|
|
1470
|
-
children: {
|
|
1471
|
-
$cond: {
|
|
1472
|
-
if: { $gt: [{ $size: "$children" }, 0] },
|
|
1473
|
-
then: "$children",
|
|
1474
|
-
else: "$$REMOVE",
|
|
1475
|
-
},
|
|
1476
|
-
},
|
|
1477
|
-
},
|
|
1478
|
-
],
|
|
1479
|
-
},
|
|
1480
|
-
},
|
|
1481
|
-
});
|
|
1482
|
-
// INFO: Re-apply sort after group to maintain sort order
|
|
1483
|
-
if (Object.keys(sortStage.$sort).length > 0) {
|
|
1484
|
-
pipelineList.push(sortStage);
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
if (req.body.attributeIds && req.body.attributeIds.length > 0) {
|
|
1488
|
-
const projection = { _id: 1 };
|
|
1489
|
-
req.body.attributeIds.forEach((fieldId) => {
|
|
1490
|
-
projection[fieldId] = 1;
|
|
1491
|
-
});
|
|
1492
|
-
pipelineList.push({ $project: projection });
|
|
1493
|
-
}
|
|
1494
|
-
if (req.body.excludeAttributeIds &&
|
|
1495
|
-
req.body.excludeAttributeIds.length > 0) {
|
|
1496
|
-
pipelineList.push({
|
|
1497
|
-
$unset: req.body.excludeAttributeIds,
|
|
1498
|
-
});
|
|
1499
|
-
}
|
|
1500
|
-
if (cursor) {
|
|
1501
|
-
pipelineList.push({ $skip: Number.parseInt(cursor) });
|
|
1502
|
-
}
|
|
1503
|
-
if (!stopLimit) {
|
|
1504
|
-
pipelineList.push({ $limit: limit || 10 });
|
|
1505
|
-
}
|
|
1506
|
-
// INFO : Remove Link Search
|
|
1507
|
-
const foreignAliases = Array.from(addedForeignLookups.keys());
|
|
1508
|
-
if (foreignAliases.length > 0) {
|
|
1509
|
-
pipelineList.push({
|
|
1510
|
-
$unset: [...foreignAliases],
|
|
1511
|
-
});
|
|
1512
|
-
}
|
|
1513
|
-
const spaceReferenceFields = Array.from(addedSpaceReferences);
|
|
1514
|
-
if (spaceReferenceFields.length > 0) {
|
|
1515
|
-
pipelineList.push({
|
|
1516
|
-
$unset: [...spaceReferenceFields],
|
|
1517
|
-
});
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
catch (err) { }
|
|
1521
|
-
return pipelineList;
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
exports.MongoWrapper = MongoWrapper;
|
|
1
|
+
var __awaiter=this&&this.__awaiter||function(e,r,l,d){return new(l=l||Promise)(function(i,t){function s(e){try{o(d.next(e))}catch(e){t(e)}}function a(e){try{o(d.throw(e))}catch(e){t(e)}}function o(e){var t;e.done?i(e.value):((t=e.value)instanceof l?t:new l(function(e){e(t)})).then(s,a)}o((d=d.apply(e,r||[])).next())})},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.MongoWrapper=void 0;let dayjs_1=__importDefault(require("./dayjs")),uuid_1=require("uuid"),QueryModel_1=require("../model/QueryModel"),utils_1=require("./utils"),handleParseQueryFilter=(e,d)=>{let n={},u={};return e&&0<e.length&&e.map(i=>{let e,t,s,a=null!=(e=i.queryId)?e:"",o=(d&&(a=d+"."+a),i.value),r={},l=!!i.orQuery;switch(i.type){case"search":i.searchIds&&0<i.searchIds.length&&i.searchIds.map(e=>{l=!0,r[e]={$regex:""+(0,utils_1.handleSpecialWordsEscapeRegex)(o),$options:"i"}}),i.foreign&&0<i.foreign.length&&null!=(t=null==i?void 0:i.foreign)&&t.forEach(e=>{let t=e.alias;d&&(t=d+"."+t),e.searchFields&&0<e.searchFields.length&&e.searchFields.forEach(e=>{r[t+"."+e]={$regex:i.value.toString().replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),$options:"i"}})});break;case"=":r[a]=o;break;case"!=":r[a]={$ne:o};break;case">":r[a]={$gt:o};break;case"<":r[a]={$lt:o};break;case"><":Array.isArray(o)&&2<=o.length&&(r[a]={$gte:o[0],$lte:o[1]});break;case"in":r[a]={$in:o};break;case"!in":r[a]={$nin:o};break;case"exists":r[a]={$exists:o};break;case"elemMatch":r[a]={$elemMatch:o};break;case">size":r.$expr||(r.$expr={}),r.$expr.$gt=[{$size:"$"+a},o];break;case"<size":r.$expr||(r.$expr={}),r.$expr.$lt=[{$size:"$"+a},o]}i.orQueryGroupId&&("search"===i.type?null!=(s=null==i?void 0:i.searchIds)&&s.map(e=>{i.orQueryGroupId&&(u[null==i?void 0:i.orQueryGroupId]?u[null==i?void 0:i.orQueryGroupId].$and.push({[e]:r[e]}):u[null==i?void 0:i.orQueryGroupId]={$and:[{[e]:r[e]}]},delete r[e])}):void 0!==r[a]&&(u[i.orQueryGroupId]?u[i.orQueryGroupId].$and.push({[a]:r[a]}):u[i.orQueryGroupId]={$and:[{[a]:r[a]}]},delete r[a])),Object.keys(r).map(e=>{l?n.$or?n.$or.push({[e]:r[e]}):n.$or=[{[e]:r[e]}]:n[e]=r[e]})}),Object.keys(u).map(e=>{n.$or?n.$or.push(u[e]):n.$or=[u[e]]}),n};class MongoWrapper{constructor(e,t,i,s,a,o,r,l,d,n,u){this.mongoDB="",this.collection="",this.isProd=!1,this.config={baseConfig:[],opsConfig:{read:[],create:[],update:[],delete:[]}},this.tableId="",this.logId="",this.logCollectIds=[],this.modelChecker=e=>!1,this.parseModel=e=>(delete e._id,e.baseUpdatedAt=(0,dayjs_1.default)().toDate(),e),this.handleLogging=(r,l,t,d)=>__awaiter(this,void 0,void 0,function*(){if(this.logId)try{var e=t.body.bm_userId,i=t.body.bm_userRole,o=t.body.bm_userOrg;let s=[],a="create"===l?t.body.data:null==d?void 0:d.new;if(Object.keys(a).map(e=>{var t,i={newValue:a[e],columnId:e};"update"===l&&(i.oldValue=null==(t=null==d?void 0:d.old)?void 0:t[e],JSON.stringify(a[e])===JSON.stringify(null==(t=null==d?void 0:d.old)?void 0:t[e]))||"_id"===e||e.startsWith("base")||s.push(i)}),"update"!==l||0!==s.length){let t={_id:(0,uuid_1.v4)(),type:l,itemId:r,collectionId:this.collection,createdAt:(0,dayjs_1.default)().toDate(),values:s,userId:e,userRole:i,organisationId:o};("create"===l||"update"===l)&&0<this.logCollectIds.length&&this.logCollectIds.forEach(e=>{void 0!==a[e]&&(t[e]=a[e])}),yield this.mongoDB.db(this.tableId).collection(this.logId).insertOne(t),this.logWorkflow&&(yield this.logWorkflow(t))}}catch(e){}}),this.initBatchCreate=(c,h,y)=>__awaiter(this,void 0,void 0,function*(){var e;try{if(Array.isArray(c.body.data)){let t=!0;var a=!!c.body.upsert,o=(c.body.data.map(e=>{this.modelChecker(e)||(t=!1)}),t||h.status(400).json({err:"Invalid Model Structure"}),(0,QueryModel_1.checkBaseConfig)(this.config,c));let i=!0,s=[];if(yield Promise.all(c.body.data.map(e=>{(0,QueryModel_1.checkOpsConfig)(this.config,"update",c,e)||(i=!1),c.body.unique&&null!=e&&e[c.body.unique]&&s.push(e[c.body.unique])})),o&&i){var r=this.mongoDB.db(this.tableId).collection(this.collection);if(0<s.length){var l=yield(yield r.find({[c.body.unique]:{$in:s}})).toArray();if(0<l.length)return void h.status(400).json({err:`Unique:${l.map(e=>e[c.body.unique])} exists`})}let t=[];var d,n=c.body.data.map(e=>(t.push(e._id),Object.assign(Object.assign({},e),{baseUpdatedAt:(0,dayjs_1.default)().toDate()}))),u=(y&&(yield y(n)),a?(d=n.map(e=>({updateOne:{filter:{_id:e._id},update:{$set:e},upsert:!0}})),yield r.bulkWrite(d)):yield r.insertMany(n),{success:t});if(null!=(e=c.body)&&e.stopRes)return u;h.send(u)}else h.status(400).json({err:"Invalid Security Configuration"})}else h.status(400).json({err:"Invalid Fields"})}catch(e){h.status(400).json({err:e})}}),this.initCreate=(l,d,n)=>__awaiter(this,void 0,void 0,function*(){var e,t;try{if(this.modelChecker(l.body.data)){var i=(0,QueryModel_1.checkBaseConfig)(this.config,l),s=(0,QueryModel_1.checkOpsConfig)(this.config,"create",l,l.body.data);if(i&&s){var a=this.mongoDB.db(this.tableId).collection(this.collection);if(l.body.data.baseUpdatedAt=(0,dayjs_1.default)().toDate(),l.body.unique&&null!=(e=l.body.data)&&e[l.body.unique])if(yield a.findOne({[l.body.unique]:l.body.data[l.body.unique]}))return void d.status(400).json({err:`Unique:${l.body.data[l.body.unique]} exists`});n&&(yield n(l.body.data));var o=(yield a.insertOne(l.body.data)).insertedId.toString(),r=(yield this.handleLogging(o,"create",l),{success:!0});if(null!=(t=l.body)&&t.stopRes)return r;d.send(r)}else d.status(400).json({err:"Invalid Security Configuration"})}else d.status(400).json({err:"Invalid Model Structure"})}catch(e){d.status(400).json({err:e})}}),this.initGet=(d,n)=>__awaiter(this,void 0,void 0,function*(){var e;try{var t=d.body.id;if(t){var i,s=this.mongoDB.db(this.tableId).collection(this.collection),a=this.handleBuildPipeline({body:Object.assign(Object.assign({},d.body),{query:[{type:"=",queryId:"_id",value:t}]})}),[o]=yield s.aggregate(a).toArray(),r=(0,QueryModel_1.checkBaseConfig)(this.config,d),l=(0,QueryModel_1.checkOpsConfig)(this.config,"read",d,o);if(r&&l)return i={data:o},null!=(e=d.body)&&e.stopRes?i:void n.send(i);n.status(400).json({err:"Invalid Security Configuration"})}else n.status(400).json({err:"Invalid Fields"})}catch(e){n.status(400).json({err:e})}}),this.initBatchUpdate=($,f,b)=>__awaiter(this,void 0,void 0,function*(){var e,t,r;try{if(this.modelChecker($.body.data)&&$.body.query||$.body.unsetData){var l=$.body.unsetData,d=null!=(e=$.body.query)?e:[];let a=$.body.isOr?"$or":"$and",o={};var n=this.parseModel(null!=(t=$.body.data)?t:[]),u=(d&&0<d.length&&(o[a]=[],d.some(e=>"search"===e.type)&&(o.$or=[]),d.map(e=>{var t,i=null!=(t=e.queryId)?t:"";let s=e.value;switch(e.type){case"search":e.searchIds&&0<e.searchIds.length&&e.searchIds.map(e=>{o.$or.push({[e]:{$regex:(0,utils_1.handleSpecialWordsEscapeRegex)(s),$options:"i"}})});break;case"=":o[a].push({[i]:s});break;case"!=":o[a].push({[i]:{$ne:s}});break;case">":o[a].push({[i]:{$gt:s}});break;case"<":o[a].push({[i]:{$lt:s}});break;case"><":Array.isArray(s)&&2<=s.length&&(o[a]={[i]:{$gte:s[0],$lte:s[1]}});break;case"in":o[a].push({[i]:{$in:s}});break;case"!in":o[a].push({[i]:{$nin:s}});break;case"exists":o[a].push({$exists:s});break;case"elemMatch":o[a].push({[i]:{$elemMatch:s}})}})),(0,QueryModel_1.checkBaseConfig)(this.config,$));let i=!0;var c=this.mongoDB.db(this.tableId).collection(this.collection),h=yield(yield c.find(Object.assign({},o))).toArray();let s=[];if(yield Promise.all(h.map(e=>{$.body.sensitive&&!(0,dayjs_1.default)($.body.data.baseUpdatedAt).isAfter((0,dayjs_1.default)(e.baseUpdatedAt))&&f.status(400).json({err:"Refresh Sensitive Model"}),(0,QueryModel_1.checkOpsConfig)(this.config,"update",$,e)||(i=!1);var t=(0,utils_1.compareUpdatedFields)(e,$.body.data).workflowUpdateFields;s.push(Object.assign(Object.assign({},t),{_id:null==e?void 0:e._id}))})),u&&i){let t={};var y={},p=(l&&(l.forEach(e=>{t[e]=""}),y.$unset=Object.assign({},t)),n&&(y.$set=Object.assign({},n)),b&&(yield b(s)),yield c.updateMany(o,y),s.map(e=>e._id)),g={success:p};if(null!=(r=$.body)&&r.stopRes)return g;f.send(g)}else f.status(400).json({err:"Invalid Security Configuration"})}}catch(e){f.status(400).json({err:e})}}),this.initUpdate=(y,p,g)=>__awaiter(this,void 0,void 0,function*(){var e,s,a;try{var o=this.modelChecker(y.body.data)&&y.body.id;if(o){var r=!!y.body.upsert;let i={};var l=this.mongoDB.db(this.tableId).collection(this.collection),t=(r||(i=yield l.findOne({_id:o})),this.debug&&this.debug(y.body,i),(0,QueryModel_1.checkBaseConfig)(this.config,y)),d=(0,QueryModel_1.checkOpsConfig)(this.config,"update",y,i);if(t&&d){if(y.body.unique&&null!=(e=y.body.data)&&e[y.body.unique]){var n=yield l.findOne({[y.body.unique]:y.body.data[y.body.unique]});if(n&&y.body.id!==n._id)return void p.status(400).json({err:y.body.data[y.body.unique]+" exists"})}var u=(0,utils_1.compareUpdatedFields)(i,y.body.data).updatedFields,c={success:!0},h=(g&&(yield g(Object.assign(Object.assign({},u),{_id:o}))),this.parseModel(u));if(y.body.sensitive)if((0,dayjs_1.default)(y.body.data.baseUpdatedAt).isAfter((0,dayjs_1.default)(i.baseUpdatedAt))){if(yield l.updateOne({_id:o},{$set:Object.assign({},h)},{upsert:r}),null!=(s=y.body)&&s.stopRes)return c;p.send(c)}else p.status(400).json({err:"Refresh Sensitive Model"});else{if(yield l.updateOne({_id:o},{$set:Object.assign({},h)},{upsert:r}),null!=(a=y.body)&&a.stopRes)return c;p.send(c)}let t={};Object.keys(h).map(e=>{t[e]=i[e]}),yield this.handleLogging(o,"update",y,{old:t,new:h})}else p.status(400).json({err:"Invalid Security Configuration"})}else p.status(400).json({err:"Invalid Model Structure"})}catch(e){this.debug&&this.debug(null,null,e),p.status(400).json({err:e})}}),this.initBatchDelete=($,f,b)=>__awaiter(this,void 0,void 0,function*(){var e,t,i,s,a,o;try{if(!(Array.isArray($.body.id)&&0!==(null!=(t=null==(e=$.body.id)?void 0:e.length)?t:0)||Array.isArray($.body.query)&&0!==(null!=(s=null==(i=$.body.query)?void 0:i.length)?s:0)))throw"Invalid Batch Delete Config";if(Array.isArray($.body.id)){var r=this.mongoDB.db(this.tableId).collection(this.collection),l=yield r.find({_id:{$in:$.body.id}}),d=(0,QueryModel_1.checkBaseConfig)(this.config,$),n=yield l.toArray();let t=!0;if(0<n.length&&(yield Promise.all(n.map(e=>{(0,QueryModel_1.checkOpsConfig)(this.config,"delete",$,e)||(t=!1)}))),d&&t){b&&(yield b(n)),yield r.deleteMany({_id:{$in:$.body.id}});var u={success:$.body.id};if(null!=(a=$.body)&&a.stopRes)return u;f.send(u)}else f.status(400).json({err:"Invalid Security Configuration"})}else{var c=$.body.query;let a={};c&&0<c.length&&c.map(e=>{var t,i=null!=(t=e.queryId)?t:"";let s=e.value;switch(e.type){case"search":e.searchIds&&0<e.searchIds.length&&(a.$or=[],e.searchIds.map(e=>{a.$or.push({[e]:{$regex:(0,utils_1.handleSpecialWordsEscapeRegex)(s),$options:"i"}})}));break;case"=":a[i]=s;break;case"!=":a[i]={$ne:s};break;case">":a[i]={$gt:s};break;case"<":a[i]={$lt:s};break;case"><":Array.isArray(s)&&2<=s.length&&(a[i]={$gte:s[0],$lte:s[1]});break;case"in":a[i]={$in:s};break;case"!in":a[i]={$nin:s};break;case"exists":a[i]={$exists:s};break;case"elemMatch":a[i]={$elemMatch:s}}});var h=this.mongoDB.db(this.tableId).collection(this.collection),y=yield h.find(a).toArray(),p=(0,QueryModel_1.checkBaseConfig)(this.config,$);let t=!0,i=[];if(0<y.length&&y.map(e=>{i.push(e._id),(0,QueryModel_1.checkOpsConfig)(this.config,"delete",$,e)||(t=!1)}),b&&(yield b(y)),p&&t){yield h.deleteMany(a);var g={success:i};if(null!=(o=$.body)&&o.stopRes)return g;f.send(g)}else f.status(400).json({err:"Invalid Security Configuration"})}}catch(e){f.status(400).json({err:e})}}),this.initDelete=(l,d,n)=>__awaiter(this,void 0,void 0,function*(){var e;try{var t=l.body.id;if(t){var i=this.mongoDB.db(this.tableId).collection(this.collection),s=yield i.findOne({_id:t}),a=(0,QueryModel_1.checkBaseConfig)(this.config,l),o=(0,QueryModel_1.checkOpsConfig)(this.config,"delete",l,s);if(a&&o){n&&(yield n(s)),yield i.findOneAndDelete({_id:t}),yield this.handleLogging(s._id,"delete",l,{new:s});var r={success:!0};if(null!=(e=l.body)&&e.stopRes)return r;d.send(r)}else d.status(400).json({err:"Invalid Security Configuration"})}else d.status(400).json({err:"Invalid Fields"})}catch(e){d.status(400).json({err:e})}}),this.initList=(ae,oe)=>__awaiter(this,void 0,void 0,function*(){var e,t,i,s,r,l,n,u,c,h,a,y,p,g,$,f,b,v,m,_;try{var I=(0,QueryModel_1.checkBaseConfig)(this.config,ae);if(I){var j=ae.body.aggregate,k=null!=(e=ae.body.unionCollections)?e:[];let o=null!=(t=ae.body.query)?t:[],d;if(d=handleParseQueryFilter(o),k&&Array.isArray(k)&&0<k.length){if(j)return void oe.status(400).json({err:"Union operations cannot be combined with aggregate"});var O=null!=(i=ae.body.sort)?i:{date:-1},M=null!=(s=ae.body.limit)?s:50,C=null!=(l=null!=(r=ae.body.cursor)?r:ae.body.skip)?l:0;let a=[];if(k.forEach((e,t)=>{let i={$project:Object.assign({_id:1},e.projection)};var s;e.sourceLogic?i.$project.source="string"==typeof e.sourceLogic?{$literal:e.sourceLogic}:e.sourceLogic:i.$project.source={$literal:e.source},0===t?(o&&0<o.length&&a.push({$match:d}),e.query&&0<e.query.length&&(t=handleParseQueryFilter(e.query),a.push({$match:t})),e.addFields&&(a.push({$addFields:e.addFields}),Object.keys(e.addFields).forEach(e=>{i.$project[e]=1})),a.push(i)):(t=[],e.query&&0<e.query.length&&(s=handleParseQueryFilter(e.query),t.push({$match:s})),e.addFields&&(t.push({$addFields:e.addFields}),Object.keys(e.addFields).forEach(e=>{i.$project[e]=1})),t.push(i),s={$unionWith:{coll:e.collection,pipeline:t}},a.push(s))}),O){let t={$sort:{}};Array.isArray(O)?O.forEach(e=>{e.sortId&&(t.$sort[e.sortId]="asc"===e.type?1:-1)}):O.sortId&&O.type?t.$sort[O.sortId]="asc"===O.type?1:-1:t.$sort=O,a.push(t)}0<C&&a.push({$skip:C}),0<M&&a.push({$limit:M});var A,S=null!=(u=null==(n=k[0])?void 0:n.collection)?u:this.collection,D=this.mongoDB.db(this.tableId).collection(S),q=yield D.aggregate(a).toArray(),w=a.filter(e=>{e=Object.keys(e)[0];return"$skip"!==e&&"$limit"!==e}),E=(w.push({$count:"total"}),yield D.aggregate(w).toArray()),U=(null==(c=E[0])?void 0:c.total)||0;let t=!0;return(q.map(e=>{(0,QueryModel_1.checkOpsConfig)(this.config,"read",ae,e)||(t=!1)}),I&&t)?(A={data:q,count:U},null!=(h=ae.body)&&h.stopRes?A:void oe.send(A)):void oe.status(400).json({err:"Invalid Security Configuration"})}if(j){var Y,H=[],P=null!=(a=j.queryId)?a:"",L=null!=(y=j.dateId)?y:"baseUpdatedAt",F=j.timezone||"Asia/Kuala_Lumpur";for(Y of null!=(p=j.range)?p:[(0,dayjs_1.default)().tz(F).format("DD/MM/YYYY HH:mm:ss")]){Object.assign({},d);var W=Y.split("-"),[Q,z=(0,dayjs_1.default)().tz(F).format("DD/MM/YYYY HH:mm:ss")]=W,G=2===W.length,T=(0,dayjs_1.default)(Q,"DD/MM/YYYY HH:mm:ss").isValid(),N=(0,dayjs_1.default)(z,"DD/MM/YYYY HH:mm:ss").isValid(),V=dayjs_1.default.tz((0,dayjs_1.default)(Q,"DD/MM/YYYY HH:mm:ss").format("YYYY-MM-DDTHH:mm:ss"),F).utc().toDate(),J=dayjs_1.default.tz((0,dayjs_1.default)(z,"DD/MM/YYYY HH:mm:ss").format("YYYY-MM-DDTHH:mm:ss"),F).utc().toDate();if(!T||!N)return void oe.status(400).json({err:"Invalid Aggregate Range Configuration"});let o=[G?{$match:Object.assign(Object.assign({},d),{[L]:{$gte:V,$lte:J}})}:{$match:Object.assign(Object.assign({},d),{[L]:{$lte:V}})}],r=G?Y:"Begining until "+(0,dayjs_1.default)(Q,"DD/MM/YYYY HH:mm:ss").format("DD/MM/YYYY"),l=!1;if(j.unwind&&0<j.unwind.length&&j.unwind.map((e,t)=>{var i,s="model"+t;let a="";0<t&&(a="model"+(t-1)+".");t=handleParseQueryFilter(null!=(t=e.query)?t:[],s);null!=(i=e.unique)&&i.list&&o.push({$unwind:"$"+e.localField}),o.push({$lookup:{from:e.collectionId,localField:a+e.localField,foreignField:"_id",as:s}},{$unwind:"$"+s},{$match:t}),null!=(i=e.unique)&&i.type&&(l=!0,s="uniqueUnwindId",o.push({$group:{_id:r,uniqueUnwindId:{$addToSet:"$"+e.localField}}}),"count"===e.unique.type?o.push({$project:{value:{$size:"$"+s}}}):o.push({$project:{_id:0,value:"$"+s}}))}),!l){let e=r;switch(j.groupId&&(e="$"+j.groupId),j.type){case"avg":o.push({$group:{_id:e,value:{$avg:"$"+P}}});break;case"sum":o.push({$group:{_id:e,value:{$sum:"$"+P}}});break;case"count":o.push({$group:{_id:e,value:{$sum:1},ids:{$push:"$_id"}}})}}if(0===o.length)return void oe.status(400).json({err:"Invalid Aggregate Configuration"});var K=this.mongoDB.db(this.tableId).collection(this.collection);let e=0,t=[];var B=yield K.aggregate(o).toArray();j.groupId?e=B:(e=null!=($=null==(g=B[0])?void 0:g.value)?$:0,t=null!=(b=null==(f=B[0])?void 0:f.ids)?b:[]),H.push({_id:r,value:e,ids:t})}var X={data:H};if(null!=(v=ae.body)&&v.stopRes)return X;oe.send(X)}else{var R,Z=this.mongoDB.db(this.tableId).collection(this.collection),ee=this.handleBuildPipeline(ae),te=ee.filter(e=>{e=Object.keys(e)[0];return"$skip"!==e&&"$limit"!==e}),[x,ie]=(te.push({$count:"total"}),yield Promise.all([Z.aggregate(ee).toArray(),Z.aggregate(te).toArray()])),se=(null==(m=ie[0])?void 0:m.total)||0;let t=!0;if(0<x.length&&x.map(e=>{(0,QueryModel_1.checkOpsConfig)(this.config,"read",ae,e)||(t=!1)}),I&&t)return R={data:x,count:se},null!=(_=ae.body)&&_.stopRes?R:void oe.send(R);oe.status(400).json({err:"Invalid Security Configuration"})}}else oe.status(400).json({err:"Invalid Security Configuration"})}catch(e){oe.status(400).json({err:e.message})}}),this.init=()=>{var e=this.lib.express.Router();return e.post("/create",(e,t)=>{this.initCreate(e,t)}),e.post("/batchCreate",(e,t)=>{this.initBatchCreate(e,t)}),e.post("/get",(e,t)=>{this.initGet(e,t)}),e.post("/update",(e,t)=>{this.initUpdate(e,t)}),e.post("/batchUpdate",(e,t)=>{this.initBatchUpdate(e,t)}),e.post("/delete",(e,t)=>{this.initDelete(e,t)}),e.post("/batchDelete",(e,t)=>{this.initBatchDelete(e,t)}),e.post("/list",(e,t)=>{this.initList(e,t)}),e},this.mongoDB=e,this.collection=t,this.isProd=i,this.config=s,this.modelChecker=a,this.lib=o;e=this.isProd?"prod":"dev";this.tableId=r?r+"-"+e:e,this.logId=null!=l?l:"",this.logWorkflow=d,this.logCollectIds=null!=n?n:[],this.debug=u}handleBuildPipeline(e){let n=[],i=new Map,u=new Set;var{query:s,sort:a,cursor:o,limit:r,stopLimit:l,pipeline:d,uniqueLabel:c,groupId:h}=e.body;try{Array.isArray(d)&&0<d.length&&d.forEach(e=>{var{condition:e,referenceSpaceLabel:s,spaceReferenceId:a,spaceReferenceAs:o,referenceSort:r,referenceFirstItem:l,referenceLimit:d}=e;if(a){let i=o||"linkedData",t=(u.add(i),{$lookup:{from:a,let:{},pipeline:[],as:i}});if(e&&0<e.length){e.forEach(e=>{t.$lookup.let["local_"+e.fromColumnId]="$"+e.fromColumnId});let i={$match:{$expr:{$and:[]}}};e.forEach(e=>{var t={};switch(e.type){case"=":t.$eq=["$"+e.toColumnId,"$$local_"+e.fromColumnId];break;case"!=":t.$ne=["$"+e.toColumnId,"$$local_"+e.fromColumnId];break;case">":t.$gt=["$"+e.toColumnId,"$$local_"+e.fromColumnId];break;case"<":t.$lt=["$"+e.toColumnId,"$$local_"+e.fromColumnId];break;case"in":t.$in=["$"+e.toColumnId,"$$local_"+e.fromColumnId];break;case"!in":t.$nin=["$"+e.toColumnId,"$$local_"+e.fromColumnId]}0<Object.keys(t).length&&i.$match.$expr.$and.push(t)}),t.$lookup.pipeline.push(i)}if(r&&r.sortId&&(o={$sort:{[r.sortId]:"asc"===r.type?1:-1}},t.$lookup.pipeline.push(o)),d&&t.$lookup.pipeline.push({$limit:d}),n.push(t),s&&0<s.length){let t={$addFields:{}};l?(n.push({$addFields:{[i]:{$first:{$ifNull:["$"+i,[]]}}}}),s.forEach(e=>{t.$addFields[i+"_"+e]=`$${i}.`+e})):s.forEach(e=>{t.$addFields[i+"_"+e]={$map:{input:"$"+i,in:"$$this."+e}}}),n.push(t)}}}),s&&0<s.length&&s.forEach(e=>{e.foreign&&Array.isArray(e.foreign)&&e.foreign.forEach(e=>{var t=e.alias;i.has(t)||(n.push({$lookup:{from:e.collection,localField:e.localField,foreignField:"_id",as:t}}),i.set(t,!0))})});let t={$sort:{}};a&&(Array.isArray(JSON.parse(JSON.stringify(a)))?a:[a]).forEach(e=>{e.sortId&&(t.$sort[e.sortId]="asc"===e.type?1:-1)});var y,p=null==a?void 0:a.sortBeforeFilter;if(p&&(0<Object.keys(t.$sort).length&&n.push(t),c)&&(n.push({$group:{_id:"$"+c,doc:{$first:"$$ROOT"}}}),n.push({$replaceRoot:{newRoot:"$doc"}})),s&&0<s.length&&(y=handleParseQueryFilter(s),n.push({$match:y})),p||(0<Object.keys(t.$sort).length&&n.push(t),c&&(n.push({$group:{_id:"$"+c,doc:{$first:"$$ROOT"}}}),n.push({$replaceRoot:{newRoot:"$doc"}}))),h&&!c&&(n.push({$group:{_id:"$"+h,topItem:{$first:"$$ROOT"},children:{$push:"$$ROOT"}}}),n.push({$replaceRoot:{newRoot:{$mergeObjects:["$topItem",{children:{$cond:{if:{$gt:[{$size:"$children"},0]},then:"$children",else:"$$REMOVE"}}}]}}}),0<Object.keys(t.$sort).length)&&n.push(t),e.body.attributeIds&&0<e.body.attributeIds.length){let t={_id:1};e.body.attributeIds.forEach(e=>{t[e]=1}),n.push({$project:t})}e.body.excludeAttributeIds&&0<e.body.excludeAttributeIds.length&&n.push({$unset:e.body.excludeAttributeIds}),o&&n.push({$skip:Number.parseInt(o)}),l||n.push({$limit:r||10});var g=Array.from(i.keys()),$=(0<g.length&&n.push({$unset:[...g]}),Array.from(u));0<$.length&&n.push({$unset:[...$]})}catch(e){}return n}}exports.MongoWrapper=MongoWrapper;
|