blixify-server 0.1.67 → 0.1.69

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.
@@ -0,0 +1,9 @@
1
+ export declare class CryptoMiddleware {
2
+ secretKey: string;
3
+ forceDecryption: boolean;
4
+ constructor(secretKey: string, forceDecryption: boolean);
5
+ handleEncryption: (data: any) => any;
6
+ handleDecryption: (data: string) => any;
7
+ init(): (req: any, res: any, next?: any) => Promise<any>;
8
+ }
9
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/apis/crypto.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,SAAS,SAAM;IACf,eAAe,UAAS;gBAEZ,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO;IAKvD,gBAAgB,SAAU,GAAG,SAS3B;IAEF,gBAAgB,SAAU,MAAM,SAO9B;IAEF,IAAI,UAG4C,GAAG,OAAO,GAAG,SAAS,GAAG;CAW1E"}
@@ -0,0 +1,56 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.CryptoMiddleware = void 0;
13
+ const CryptoJS = require("crypto-js");
14
+ class CryptoMiddleware {
15
+ constructor(secretKey, forceDecryption) {
16
+ this.secretKey = "";
17
+ this.forceDecryption = false;
18
+ this.handleEncryption = (data) => {
19
+ try {
20
+ // Encrypt the data
21
+ const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), this.secretKey).toString();
22
+ return encrypted;
23
+ }
24
+ catch (err) { }
25
+ };
26
+ this.handleDecryption = (data) => {
27
+ try {
28
+ // Decrypt the data
29
+ const bytes = CryptoJS.AES.decrypt(data, this.secretKey);
30
+ const decrypted = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
31
+ return decrypted;
32
+ }
33
+ catch (err) { }
34
+ };
35
+ this.secretKey = secretKey;
36
+ this.forceDecryption = forceDecryption;
37
+ }
38
+ init() {
39
+ // eslint-disable-next-line
40
+ const wrapper = this;
41
+ const cryptoMiddleware = function (req, res, next) {
42
+ var _a;
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ if (wrapper.forceDecryption && !req.body.sign)
45
+ return res.status(400).json({ error: "Missing signature for signing" });
46
+ if ((_a = req.body) === null || _a === void 0 ? void 0 : _a.sign)
47
+ req.body = wrapper.handleDecryption(req.body.sign);
48
+ if (next) {
49
+ next();
50
+ }
51
+ });
52
+ };
53
+ return cryptoMiddleware;
54
+ }
55
+ }
56
+ exports.CryptoMiddleware = CryptoMiddleware;
@@ -1 +1 @@
1
- {"version":3,"file":"mongoWrapper.d.ts","sourceRoot":"","sources":["../../src/apis/mongoWrapper.ts"],"names":[],"mappings":"AAQA,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAmGD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,EAAE,GAAG,CAAM;IAClB,UAAU,SAAM;IAChB,MAAM,UAAS;IACf,MAAM,EAAE,cAAc,CAQpB;IACF,GAAG,EAAE,UAAU,CAAC;IAChB,OAAO,SAAM;IACb,KAAK,EAAE,GAAG,CAAC;IAEX,YAAY,QAAS,GAAG,aAEtB;gBAGA,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,EACrD,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI;IAa3D,UAAU,SAAU,GAAG,SAIrB;IAEF,eAAe,QACR,GAAG,OACH,GAAG,yBACc,GAAG,EAAE,KAAK,QAAQ,GAAG,CAAC;;mBAyE5C;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAgDtC;IAEF,OAAO,QAAe,GAAG,OAAO,GAAG;;mBAgCjC;IAEF,eAAe,QACR,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAmJtC;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAwFtC;IAEF,eAAe,QACR,GAAG,OACH,GAAG,yBACc,GAAG,EAAE,KAAK,QAAQ,GAAG,CAAC;;mBA6H5C;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAqCtC;IAEF,QAAQ,QAAe,GAAG,OAAO,GAAG;;;;;mBA6PlC;IAEF,IAAI,YA+EF;CACH"}
1
+ {"version":3,"file":"mongoWrapper.d.ts","sourceRoot":"","sources":["../../src/apis/mongoWrapper.ts"],"names":[],"mappings":"AAQA,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAmGD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,EAAE,GAAG,CAAM;IAClB,UAAU,SAAM;IAChB,MAAM,UAAS;IACf,MAAM,EAAE,cAAc,CAQpB;IACF,GAAG,EAAE,UAAU,CAAC;IAChB,OAAO,SAAM;IACb,KAAK,EAAE,GAAG,CAAC;IAEX,YAAY,QAAS,GAAG,aAEtB;gBAGA,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,EACrD,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI;IAa3D,UAAU,SAAU,GAAG,SAIrB;IAEF,eAAe,QACR,GAAG,OACH,GAAG,yBACc,GAAG,EAAE,KAAK,QAAQ,GAAG,CAAC;;mBAyE5C;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAgDtC;IAEF,OAAO,QAAe,GAAG,OAAO,GAAG;;mBAgCjC;IAEF,eAAe,QACR,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAmJtC;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAwFtC;IAEF,eAAe,QACR,GAAG,OACH,GAAG,yBACc,GAAG,EAAE,KAAK,QAAQ,GAAG,CAAC;;mBA6H5C;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAqCtC;IAEF,QAAQ,QAAe,GAAG,OAAO,GAAG;;;;;mBAmQlC;IAEF,IAAI,YA+EF;CACH"}
@@ -641,7 +641,7 @@ class MongoWrapper {
641
641
  }
642
642
  });
643
643
  this.initList = (req, res) => __awaiter(this, void 0, void 0, function* () {
644
- var _p, _q, _r, _s, _t, _u, _v, _w, _x;
644
+ var _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
645
645
  try {
646
646
  //INFO : Security Checker
647
647
  const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
@@ -772,6 +772,7 @@ class MongoWrapper {
772
772
  $group: {
773
773
  _id: groupId,
774
774
  value: { $sum: 1 },
775
+ ids: { $push: "$_id" },
775
776
  },
776
777
  });
777
778
  break;
@@ -787,21 +788,25 @@ class MongoWrapper {
787
788
  .db(this.tableId)
788
789
  .collection(this.collection);
789
790
  let value = 0;
791
+ let ids = [];
790
792
  const mongoQuery = mongoCollection.aggregate(aggregationPipeline);
791
793
  const result = yield mongoQuery.toArray();
792
794
  if (aggregate.groupId)
793
795
  value = result;
794
- else
796
+ else {
795
797
  value = (_u = (_t = result[0]) === null || _t === void 0 ? void 0 : _t.value) !== null && _u !== void 0 ? _u : 0;
798
+ ids = (_w = (_v = result[0]) === null || _v === void 0 ? void 0 : _v.ids) !== null && _w !== void 0 ? _w : [];
799
+ }
796
800
  dataList.push({
797
801
  _id: id,
798
802
  value,
803
+ ids,
799
804
  });
800
805
  }
801
806
  const resBody = {
802
807
  data: dataList,
803
808
  };
804
- if ((_v = req.body) === null || _v === void 0 ? void 0 : _v.stopRes)
809
+ if ((_x = req.body) === null || _x === void 0 ? void 0 : _x.stopRes)
805
810
  return resBody;
806
811
  res.send(resBody);
807
812
  }
@@ -817,7 +822,7 @@ class MongoWrapper {
817
822
  }
818
823
  //INFO : Step 3 - Limit
819
824
  if (!req.body.stopLimit) {
820
- mongoQuery = mongoQuery.limit((_w = req.body.limit) !== null && _w !== void 0 ? _w : 10);
825
+ mongoQuery = mongoQuery.limit((_y = req.body.limit) !== null && _y !== void 0 ? _y : 10);
821
826
  }
822
827
  //INFO : Step 4 - Sort
823
828
  if (req.body.sort) {
@@ -845,7 +850,7 @@ class MongoWrapper {
845
850
  data: dataList,
846
851
  count,
847
852
  };
848
- if ((_x = req.body) === null || _x === void 0 ? void 0 : _x.stopRes)
853
+ if ((_z = req.body) === null || _z === void 0 ? void 0 : _z.stopRes)
849
854
  return resBody;
850
855
  res.send(resBody);
851
856
  }
@@ -0,0 +1,35 @@
1
+ import SecurityConfig from "../model/SecurityConfig";
2
+ export interface WrapperLib {
3
+ express?: any;
4
+ }
5
+ /**
6
+ * @Wrapper
7
+ * collection - PostgreSQL Collection
8
+ *
9
+ */
10
+ export declare class PostgreSQLWrapper {
11
+ pgDB: any;
12
+ collection: string;
13
+ isProd: boolean;
14
+ config: SecurityConfig;
15
+ lib: WrapperLib;
16
+ debug: any;
17
+ modelChecker: (obj: any) => boolean;
18
+ constructor(pgDB: any, collection: string, isProd: boolean, config: SecurityConfig, modelChecker: (obj: any, ignore?: boolean) => boolean, lib: WrapperLib, debug?: (reqBody: any, curBody: any, errMsg: any) => void);
19
+ buildUpdateQuery(pgData: any): string;
20
+ initCreate: (req: any, res: any, workflow?: ((data: any) => Promise<any>) | undefined) => Promise<{
21
+ success: boolean;
22
+ } | undefined>;
23
+ initGet: (req: any, res: any) => Promise<{
24
+ data: null;
25
+ } | undefined>;
26
+ initUpdate: (req: any, res: any, workflow?: ((data: any) => Promise<any>) | undefined) => Promise<{
27
+ success: boolean;
28
+ } | undefined>;
29
+ initDelete: (req: any, res: any, workflow?: ((data: any) => Promise<any>) | undefined) => Promise<{
30
+ success: boolean;
31
+ } | undefined>;
32
+ initList: (req: any, res: any) => Promise<void>;
33
+ init: () => any;
34
+ }
35
+ //# sourceMappingURL=postgresqlWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresqlWrapper.d.ts","sourceRoot":"","sources":["../../src/apis/postgresqlWrapper.ts"],"names":[],"mappings":"AAQA,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,IAAI,EAAE,GAAG,CAAM;IACf,UAAU,SAAM;IAChB,MAAM,UAAS;IACf,MAAM,EAAE,cAAc,CAQpB;IACF,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,GAAG,CAAC;IAEX,YAAY,QAAS,GAAG,aAEtB;gBAGA,IAAI,EAAE,GAAG,EACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,EACrD,GAAG,EAAE,UAAU,EACf,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI;IAoB3D,gBAAgB,CAAC,MAAM,EAAE,GAAG;IAM5B,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAuDtC;IAEF,OAAO,QAAe,GAAG,OAAO,GAAG;;mBAiCjC;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAgFtC;IAEF,UAAU,QACH,GAAG,OACH,GAAG,qBACU,GAAG,KAAK,QAAQ,GAAG,CAAC;;mBAmCtC;IAEF,QAAQ,QAAe,GAAG,OAAO,GAAG,mBAgPlC;IAEF,IAAI,YA+EF;CACH"}
@@ -0,0 +1,513 @@
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.PostgreSQLWrapper = void 0;
16
+ const moment_timezone_1 = __importDefault(require("moment-timezone"));
17
+ const QueryModel_1 = require("../model/QueryModel");
18
+ const utils_1 = require("./utils");
19
+ /**
20
+ * @Wrapper
21
+ * collection - PostgreSQL Collection
22
+ *
23
+ */
24
+ class PostgreSQLWrapper {
25
+ constructor(pgDB, collection, isProd, config, modelChecker, lib, debug) {
26
+ this.pgDB = "";
27
+ this.collection = "";
28
+ this.isProd = false;
29
+ this.config = {
30
+ baseConfig: [],
31
+ opsConfig: {
32
+ read: [],
33
+ create: [],
34
+ update: [],
35
+ delete: [],
36
+ },
37
+ };
38
+ // eslint-disable-next-line
39
+ this.modelChecker = (obj) => {
40
+ return false;
41
+ };
42
+ this.initCreate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
43
+ var _a, _b;
44
+ try {
45
+ const valid = this.modelChecker(req.body.data);
46
+ if (valid) {
47
+ //INFO : Security Checker
48
+ const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
49
+ const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "create", req, req.body.data);
50
+ if (!validBaseConfig || !validOpsConfig) {
51
+ res.status(400).json({ err: "Invalid Security Configuration" });
52
+ return;
53
+ }
54
+ // req.body.data["baseUpdatedAt"] = moment().toDate();
55
+ if (req.body.unique && ((_a = req.body.data) === null || _a === void 0 ? void 0 : _a[req.body.unique])) {
56
+ const uniqueField = req.body.unique;
57
+ const uniqueValue = req.body.data[uniqueField];
58
+ const { rowCount } = yield this.pgDB.query(`SELECT * FROM ${this.collection} WHERE ${uniqueField} = $1 LIMIT 1`, [uniqueValue]);
59
+ if (rowCount > 0) {
60
+ res
61
+ .status(400)
62
+ .json({ err: `Unique:${req.body.data[req.body.unique]} exists` });
63
+ return;
64
+ }
65
+ }
66
+ if (workflow)
67
+ yield workflow(req.body.data);
68
+ const columns = Object.keys(req.body.data).join(", ");
69
+ const values = Object.values(req.body.data);
70
+ const placeholders = values
71
+ .map((_, index) => `$${index + 1}`)
72
+ .join(", ");
73
+ yield this.pgDB.query(`INSERT INTO ${this.collection} (${columns}) VALUES (${placeholders})`, values);
74
+ const resBody = { success: true };
75
+ if ((_b = req.body) === null || _b === void 0 ? void 0 : _b.stopRes)
76
+ return resBody;
77
+ res.send(resBody);
78
+ }
79
+ else {
80
+ res.status(400).json({ err: "Invalid Model Structure" });
81
+ }
82
+ }
83
+ catch (err) {
84
+ res.status(400).json({ err: err });
85
+ }
86
+ });
87
+ this.initGet = (req, res) => __awaiter(this, void 0, void 0, function* () {
88
+ var _c;
89
+ try {
90
+ const valid = req.body.id;
91
+ if (valid) {
92
+ //INFO : Security Checker
93
+ const pgResult = yield this.pgDB.query(`SELECT * FROM ${this.collection} WHERE id = $1 LIMIT 1`, [valid]);
94
+ const resBody = { data: null };
95
+ if (pgResult.rowCount > 0) {
96
+ const pgData = pgResult.rows[0];
97
+ const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
98
+ const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "read", req, pgData);
99
+ if (!validBaseConfig || !validOpsConfig) {
100
+ res.status(400).json({ err: "Invalid Security Configuration" });
101
+ return;
102
+ }
103
+ resBody["data"] = pgData;
104
+ }
105
+ if ((_c = req.body) === null || _c === void 0 ? void 0 : _c.stopRes)
106
+ return resBody;
107
+ res.send(resBody);
108
+ }
109
+ else {
110
+ res.status(400).json({ err: "Invalid Fields" });
111
+ }
112
+ }
113
+ catch (err) {
114
+ res.status(400).json({ err: err });
115
+ }
116
+ });
117
+ this.initUpdate = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
118
+ var _d, _e, _f;
119
+ try {
120
+ const valid = this.modelChecker(req.body.data) && req.body.id;
121
+ if (valid) {
122
+ const pgResult = yield this.pgDB.query(`SELECT * FROM ${this.collection} WHERE id = $1`, [valid]);
123
+ if (pgResult.rowCount > 0) {
124
+ const pgData = pgResult.rows[0];
125
+ if (this.debug)
126
+ this.debug(req.body, pgData);
127
+ const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
128
+ const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "update", req, pgData);
129
+ if (!validBaseConfig || !validOpsConfig) {
130
+ res.status(400).json({ err: "Invalid Security Configuration" });
131
+ return;
132
+ }
133
+ if (req.body.unique && ((_d = req.body.data) === null || _d === void 0 ? void 0 : _d[req.body.unique])) {
134
+ const uniqueField = req.body.unique;
135
+ const uniqueValue = req.body.data[uniqueField];
136
+ const { rowCount } = yield this.pgDB.query(`SELECT * FROM ${this.collection} WHERE ${uniqueField} = $1 LIMIT 1`, [uniqueValue]);
137
+ if (rowCount > 0) {
138
+ res.status(400).json({
139
+ err: `Unique:${req.body.data[req.body.unique]} exists`,
140
+ });
141
+ return;
142
+ }
143
+ }
144
+ const { updatedFields } = (0, utils_1.compareUpdatedFields)(pgData, req.body.data);
145
+ const resBody = { success: true };
146
+ if (workflow)
147
+ yield workflow(updatedFields);
148
+ // const data = this.parseModel(updatedFields);
149
+ //INFO : Security Checker
150
+ const updateQuery = this.buildUpdateQuery(updatedFields);
151
+ const sqlQuery = `UPDATE ${this.collection} SET ${updateQuery} WHERE id = $${Object.keys(updatedFields).length + 1}`;
152
+ const values = [...Object.values(updatedFields), valid];
153
+ if (req.body.sensitive) {
154
+ if ((0, moment_timezone_1.default)(req.body.data.baseUpdatedAt).isAfter((0, moment_timezone_1.default)(pgData.baseUpdatedAt))) {
155
+ yield this.pgDB.query(sqlQuery, values);
156
+ if ((_e = req.body) === null || _e === void 0 ? void 0 : _e.stopRes)
157
+ return resBody;
158
+ res.send(resBody);
159
+ }
160
+ else {
161
+ res.status(400).json({ err: "Refresh Sensitive Model" });
162
+ }
163
+ }
164
+ else {
165
+ yield this.pgDB.query(sqlQuery, values);
166
+ if ((_f = req.body) === null || _f === void 0 ? void 0 : _f.stopRes)
167
+ return resBody;
168
+ res.send(resBody);
169
+ }
170
+ }
171
+ else
172
+ throw "No Data Found";
173
+ }
174
+ else {
175
+ throw "Invalid Model Structure";
176
+ }
177
+ }
178
+ catch (err) {
179
+ if (this.debug)
180
+ this.debug(null, null, err);
181
+ res.status(400).json({ err: err });
182
+ }
183
+ });
184
+ this.initDelete = (req, res, workflow) => __awaiter(this, void 0, void 0, function* () {
185
+ var _g;
186
+ try {
187
+ const valid = req.body.id;
188
+ if (valid) {
189
+ const pgResult = yield this.pgDB.query(`SELECT * FROM ${this.collection} WHERE id = $1 LIMIT 1`, [valid]);
190
+ if (pgResult.rowCount > 0) {
191
+ const pgData = pgResult.rows[0];
192
+ const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
193
+ const validOpsConfig = (0, QueryModel_1.checkOpsConfig)(this.config, "read", req, pgData);
194
+ if (!validBaseConfig || !validOpsConfig) {
195
+ res.status(400).json({ err: "Invalid Security Configuration" });
196
+ return;
197
+ }
198
+ if (workflow)
199
+ yield workflow(pgData);
200
+ yield this.pgDB.query(`DELETE FROM ${this.collection} WHERE id = $1`, [valid]);
201
+ const resBody = { success: true };
202
+ if ((_g = req.body) === null || _g === void 0 ? void 0 : _g.stopRes)
203
+ return resBody;
204
+ res.send(resBody);
205
+ }
206
+ else
207
+ throw "No Data Found";
208
+ }
209
+ else
210
+ throw "Invalid Fields";
211
+ }
212
+ catch (err) {
213
+ res.status(400).json({ err: err });
214
+ }
215
+ });
216
+ this.initList = (req, res) => __awaiter(this, void 0, void 0, function* () {
217
+ var _h, _j, _k, _l, _m;
218
+ try {
219
+ //INFO : Security Checker
220
+ const validBaseConfig = (0, QueryModel_1.checkBaseConfig)(this.config, req);
221
+ if (validBaseConfig) {
222
+ const aggregate = req.body.aggregate;
223
+ const queryList = (_h = req.body.query) !== null && _h !== void 0 ? _h : [];
224
+ if (aggregate) {
225
+ const queryId = (_j = aggregate.queryId) !== null && _j !== void 0 ? _j : "";
226
+ const dateId = (_k = aggregate.dateId) !== null && _k !== void 0 ? _k : "baseUpdatedAt";
227
+ const dateRanges = (_l = aggregate.range) !== null && _l !== void 0 ? _l : [];
228
+ const dataList = [];
229
+ for (const dateRange of dateRanges) {
230
+ //INFO : Step 1 - Query
231
+ let query = `SELECT * FROM ${this.collection}`;
232
+ const whereClauses = [];
233
+ if (queryList && queryList.length > 0) {
234
+ queryList.map((eachQuery) => {
235
+ var _a;
236
+ const queryId = (_a = eachQuery.queryId) !== null && _a !== void 0 ? _a : "";
237
+ const value = eachQuery.value;
238
+ switch (eachQuery.type) {
239
+ case "=":
240
+ whereClauses.push(`${queryId} = ${value}`);
241
+ break;
242
+ case "!=":
243
+ whereClauses.push(`${queryId} != ${value}`);
244
+ break;
245
+ case ">":
246
+ whereClauses.push(`${queryId} > ${value}`);
247
+ break;
248
+ case "<":
249
+ whereClauses.push(`${queryId} < ${value}`);
250
+ break;
251
+ case "><":
252
+ if (Array.isArray(value) && value.length >= 2) {
253
+ whereClauses.push(`${queryId} BETWEEN ${value[0]} AND ${value[1]}`);
254
+ }
255
+ break;
256
+ case "in":
257
+ whereClauses.push(`${queryId} IN (${value
258
+ .map((eachValue) => `'${eachValue}'`)
259
+ .join(", ")})`);
260
+ break;
261
+ default:
262
+ break;
263
+ }
264
+ });
265
+ }
266
+ const date = dateRange.split("-");
267
+ const [startDate, endDate = (0, moment_timezone_1.default)().format("DD/MM/YYYY HH:mm:ss"),] = date;
268
+ const isDuration = date.length === 2;
269
+ const isValidStartDate = (0, moment_timezone_1.default)(startDate, "DD/MM/YYYY").isValid();
270
+ const isValidEndDate = (0, moment_timezone_1.default)(endDate, "DD/MM/YYYY").isValid();
271
+ const startMoment = (0, moment_timezone_1.default)(startDate, "DD/MM/YYYY HH:mm:ss").tz("Asia/Kuala_lumpur");
272
+ const endMoment = (0, moment_timezone_1.default)(endDate, "DD/MM/YYYY HH:mm:ss").tz("Asia/Kuala_lumpur");
273
+ const isoStartDate = startMoment.toDate();
274
+ const queryStartDate = startMoment.toISOString();
275
+ const queryEndDate = endMoment.toISOString();
276
+ if (!isValidStartDate || !isValidEndDate) {
277
+ res
278
+ .status(400)
279
+ .json({ err: "Invalid Aggregate Range Configuration" });
280
+ return;
281
+ }
282
+ const id = isDuration
283
+ ? dateRange
284
+ : `Begining until ${(0, moment_timezone_1.default)(isoStartDate).format("DD/MM/YYYY")}`;
285
+ if (isDuration) {
286
+ whereClauses.push(`${dateId} BETWEEN '${queryStartDate}' AND '${queryEndDate}'`);
287
+ }
288
+ else {
289
+ whereClauses.push(`${dateId} < '${queryStartDate}'`);
290
+ }
291
+ const allWhereClauses = `${whereClauses.length > 0
292
+ ? "WHERE " + whereClauses.join(" AND ")
293
+ : ""}`;
294
+ let value = 0;
295
+ switch (aggregate.type) {
296
+ case "count":
297
+ query = `SELECT COUNT(*) as count FROM ${this.collection} ${allWhereClauses}`;
298
+ const countResult = yield this.pgDB.query(query);
299
+ value = parseInt(countResult.rows[0].count, 10);
300
+ break;
301
+ case "sum":
302
+ query = `SELECT SUM(${queryId}) as sum FROM ${this.collection} ${allWhereClauses}`;
303
+ const sumResult = yield this.pgDB.query(query);
304
+ value = parseFloat(sumResult.rows[0].sum);
305
+ break;
306
+ case "avg":
307
+ query = `SELECT AVG(${queryId}) as avg FROM ${this.collection} ${allWhereClauses}`;
308
+ const avgResult = yield this.pgDB.query(query);
309
+ value = parseFloat(avgResult.rows[0].avg);
310
+ break;
311
+ case "value":
312
+ query = `SELECT * FROM ${this.collection} ${allWhereClauses} ORDER BY ${dateId} DESC LIMIT 1`;
313
+ const valueResult = yield this.pgDB.query(query);
314
+ if (valueResult.rows.length > 0)
315
+ value = valueResult.rows[0][queryId];
316
+ break;
317
+ default:
318
+ break;
319
+ }
320
+ dataList.push({
321
+ _id: id,
322
+ value: value,
323
+ });
324
+ }
325
+ res.send({
326
+ data: dataList,
327
+ });
328
+ }
329
+ else {
330
+ //INFO : Step 1 - Query
331
+ let query = `SELECT * FROM ${this.collection}`;
332
+ const whereClauses = [];
333
+ if (queryList && queryList.length > 0) {
334
+ queryList.map((eachQuery) => {
335
+ var _a;
336
+ const queryId = (_a = eachQuery.queryId) !== null && _a !== void 0 ? _a : "";
337
+ const value = eachQuery.value;
338
+ switch (eachQuery.type) {
339
+ case "search":
340
+ if (eachQuery.searchIds && eachQuery.searchIds.length > 0) {
341
+ whereClauses.push(`${eachQuery.searchIds[0]} ILIKE '${value}%'`);
342
+ }
343
+ break;
344
+ case "=":
345
+ whereClauses.push(`${queryId} = '${value}'`);
346
+ break;
347
+ case "!=":
348
+ whereClauses.push(`${queryId} != '${value}'`);
349
+ break;
350
+ case ">":
351
+ whereClauses.push(`${queryId} > '${value}'`);
352
+ break;
353
+ case "<":
354
+ whereClauses.push(`${queryId} < '${value}'`);
355
+ break;
356
+ case "><":
357
+ if (Array.isArray(value) && value.length >= 2) {
358
+ whereClauses.push(`${queryId} BETWEEN '${value[0]}' AND '${value[1]}'`);
359
+ }
360
+ break;
361
+ case "in":
362
+ whereClauses.push(`${queryId} IN (${value
363
+ .map((eachValue) => `'${eachValue}'`)
364
+ .join(", ")})`);
365
+ break;
366
+ default:
367
+ break;
368
+ }
369
+ });
370
+ }
371
+ const allWhereClauses = `${whereClauses.length > 0 ? "WHERE " + whereClauses.join(" AND ") : ""}`;
372
+ query += ` ${allWhereClauses}`;
373
+ //INFO : Step 2 - Sort
374
+ if (req.body.sort) {
375
+ const sortReq = req.body.sort;
376
+ query += ` ORDER BY ${sortReq.sortId} ${sortReq.type === "asc" ? "ASC" : "DESC"}`;
377
+ }
378
+ //INFO : Step 3 - Pagination
379
+ if (req.body.cursor) {
380
+ query += ` OFFSET ${req.body.cursor}`;
381
+ }
382
+ //INFO : Step 4 - Limit
383
+ if (!req.body.stopLimit) {
384
+ const limit = (_m = req.body.limit) !== null && _m !== void 0 ? _m : 10;
385
+ query += ` LIMIT ${limit}`;
386
+ }
387
+ const { rows, rowCount } = yield this.pgDB.query(query);
388
+ //INFO : Security Checker
389
+ let validOpsConfig = true;
390
+ const dataList = [];
391
+ if (rows) {
392
+ rows.forEach((eachData) => {
393
+ dataList.push(eachData);
394
+ if (!(0, QueryModel_1.checkOpsConfig)(this.config, "read", req, eachData)) {
395
+ validOpsConfig = false;
396
+ }
397
+ });
398
+ }
399
+ if (!validBaseConfig || !validOpsConfig) {
400
+ res.status(400).json({ err: "Invalid Security Configuration" });
401
+ return;
402
+ }
403
+ res.send({
404
+ data: dataList,
405
+ count: rowCount,
406
+ });
407
+ }
408
+ }
409
+ else {
410
+ res.status(400).json({ err: "Invalid Security Configuration" });
411
+ }
412
+ }
413
+ catch (err) {
414
+ if (err.message)
415
+ res.status(400).json({ err: err.message });
416
+ else
417
+ res.status(400).json({ err: err });
418
+ }
419
+ });
420
+ this.init = () => {
421
+ const router = this.lib.express.Router();
422
+ /**
423
+ * @Input :
424
+ * data - Model
425
+ * unique - string (Optional)
426
+ */
427
+ router.post("/create", (req, res) => {
428
+ this.initCreate(req, res);
429
+ });
430
+ /**
431
+ * @Input :
432
+ * data - Model
433
+ * unique - string (Optional)
434
+ */
435
+ // router.post("/batchCreate", (req: any, res: any) => {
436
+ // this.initBatchCreate(req, res);
437
+ // });
438
+ /**
439
+ * @Input :
440
+ * id - string
441
+ */
442
+ router.post("/get", (req, res) => {
443
+ this.initGet(req, res);
444
+ });
445
+ /**
446
+ * @Input :
447
+ * data - Model
448
+ * id - string
449
+ * unique - string (Optional)
450
+ */
451
+ router.post("/update", (req, res) => {
452
+ this.initUpdate(req, res);
453
+ });
454
+ /**
455
+ * @Input :
456
+ * data - Model
457
+ * query - Query[]
458
+ * unsetData - string[] (Unset Attribute Id) (Optional)
459
+ * isOr - boolean (Optional)
460
+ */
461
+ // router.post("/batchUpdate", (req: any, res: any) => {
462
+ // this.initBatchUpdate(req, res);
463
+ // });
464
+ /**
465
+ * @Input :
466
+ * id - string
467
+ */
468
+ router.post("/delete", (req, res) => {
469
+ this.initDelete(req, res);
470
+ });
471
+ /**
472
+ * @Input :
473
+ * id - string[]
474
+ */
475
+ // router.post("/batchDelete", (req: any, res: any) => {
476
+ // this.initBatchDelete(req, res);
477
+ // });
478
+ /**
479
+ * @Input
480
+ * query - Query interface (Optional)
481
+ * cursor - any (Optional)
482
+ * limit - number (Optional)
483
+ * sort - Sort interface (Optional)
484
+ * stopLimit - boolean to retreive all data (Optional)
485
+ */
486
+ router.post("/list", (req, res) => {
487
+ this.initList(req, res);
488
+ });
489
+ return router;
490
+ };
491
+ this.pgDB = pgDB;
492
+ this.collection = collection;
493
+ this.isProd = isProd;
494
+ this.config = config;
495
+ this.modelChecker = modelChecker;
496
+ this.lib = lib;
497
+ this.debug = debug;
498
+ }
499
+ //TODO: Parse Model
500
+ //TODO: Batch Create & Update
501
+ //TODO: Change table schema dynanically
502
+ // parseModel = (data: any) => {
503
+ // delete data["_id"];
504
+ // data["baseUpdatedAt"] = moment().toDate();
505
+ // return data;
506
+ // };
507
+ buildUpdateQuery(pgData) {
508
+ return Object.keys(pgData)
509
+ .map((key, index) => `${key} = $${index + 1}`)
510
+ .join(", ");
511
+ }
512
+ }
513
+ exports.PostgreSQLWrapper = PostgreSQLWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blixify-server",
3
- "version": "0.1.67",
3
+ "version": "0.1.69",
4
4
  "license": "MIT",
5
5
  "main": "dist/apis/index.js",
6
6
  "private": false,
@@ -21,6 +21,7 @@
21
21
  "build": "yarn run lint && tsc --build \"./tsconfig.json\"",
22
22
  "deploy": "yarn run lint && tsc --build \"./buildtsconfig.json\"",
23
23
  "lint": "eslint . --max-warnings=0",
24
+ "start:postgres": "cd dist && node postgresServer.js",
24
25
  "start:mongo": "cd dist && node mongoServer.js",
25
26
  "start:fb": "cd dist && node firebaseServer.js",
26
27
  "start:aws": "cd dist && node awsServer.js",
@@ -37,9 +38,11 @@
37
38
  "dependencies": {
38
39
  "@types/uuid": "^9.0.7",
39
40
  "axios": "^1.4.0",
41
+ "crypto-js": "^4.2.0",
40
42
  "mime": "^3.0.0",
41
43
  "moment": "^2.29.4",
42
44
  "moment-timezone": "^0.5.43",
45
+ "pg": "^8.12.0",
43
46
  "uuid": "^9.0.1"
44
47
  },
45
48
  "devDependencies": {