mvc-common-toolkit 1.43.10 → 1.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/dist/src/constants.d.ts +59 -0
  2. package/dist/src/constants.js +69 -0
  3. package/dist/src/constants.js.map +1 -0
  4. package/dist/src/gateways/alibaba-cloud-gateway.d.ts +30 -0
  5. package/dist/src/gateways/alibaba-cloud-gateway.js +120 -0
  6. package/dist/src/gateways/alibaba-cloud-gateway.js.map +1 -0
  7. package/dist/src/gateways/http-audit-gateway.d.ts +20 -0
  8. package/dist/src/gateways/http-audit-gateway.js +76 -0
  9. package/dist/src/gateways/http-audit-gateway.js.map +1 -0
  10. package/dist/src/gateways/index.d.ts +5 -0
  11. package/dist/src/gateways/index.js +22 -0
  12. package/dist/src/gateways/index.js.map +1 -0
  13. package/dist/src/gateways/internal-auth-gateway.d.ts +8 -0
  14. package/dist/src/gateways/internal-auth-gateway.js +40 -0
  15. package/dist/src/gateways/internal-auth-gateway.js.map +1 -0
  16. package/dist/src/gateways/stdout-audit-gateway.d.ts +7 -0
  17. package/dist/src/gateways/stdout-audit-gateway.js +25 -0
  18. package/dist/src/gateways/stdout-audit-gateway.js.map +1 -0
  19. package/dist/src/gateways/webhook-audit-gateway.d.ts +14 -0
  20. package/dist/src/gateways/webhook-audit-gateway.js +27 -0
  21. package/dist/src/gateways/webhook-audit-gateway.js.map +1 -0
  22. package/dist/src/interfaces.d.ts +218 -0
  23. package/dist/src/interfaces.js +3 -0
  24. package/dist/src/interfaces.js.map +1 -0
  25. package/dist/src/models/audit-log.d.ts +77 -0
  26. package/dist/src/models/audit-log.js +92 -0
  27. package/dist/src/models/audit-log.js.map +1 -0
  28. package/dist/src/models/index.d.ts +1 -0
  29. package/dist/src/models/index.js +18 -0
  30. package/dist/src/models/index.js.map +1 -0
  31. package/dist/src/pkg/array-helper.d.ts +1 -0
  32. package/dist/src/pkg/array-helper.js +12 -0
  33. package/dist/src/pkg/array-helper.js.map +1 -0
  34. package/dist/src/pkg/bcrypt-helper.d.ts +2 -0
  35. package/dist/src/pkg/bcrypt-helper.js +36 -0
  36. package/dist/src/pkg/bcrypt-helper.js.map +1 -0
  37. package/dist/src/pkg/crypto-helper.d.ts +2 -0
  38. package/dist/src/pkg/crypto-helper.js +16 -0
  39. package/dist/src/pkg/crypto-helper.js.map +1 -0
  40. package/dist/src/pkg/encryption-helper.d.ts +18 -0
  41. package/dist/src/pkg/encryption-helper.js +89 -0
  42. package/dist/src/pkg/encryption-helper.js.map +1 -0
  43. package/dist/src/pkg/encryption-helper.spec.d.ts +1 -0
  44. package/dist/src/pkg/encryption-helper.spec.js +238 -0
  45. package/dist/src/pkg/encryption-helper.spec.js.map +1 -0
  46. package/dist/src/pkg/filter-helper.d.ts +2 -0
  47. package/dist/src/pkg/filter-helper.js +102 -0
  48. package/dist/src/pkg/filter-helper.js.map +1 -0
  49. package/dist/src/pkg/filter-helper.spec.d.ts +1 -0
  50. package/dist/src/pkg/filter-helper.spec.js +94 -0
  51. package/dist/src/pkg/filter-helper.spec.js.map +1 -0
  52. package/dist/src/pkg/geoip-helper.d.ts +2 -0
  53. package/dist/src/pkg/geoip-helper.js +32 -0
  54. package/dist/src/pkg/geoip-helper.js.map +1 -0
  55. package/dist/src/pkg/hash-helper.d.ts +1 -0
  56. package/dist/src/pkg/hash-helper.js +37 -0
  57. package/dist/src/pkg/hash-helper.js.map +1 -0
  58. package/dist/src/pkg/http-request-utils.d.ts +4 -0
  59. package/dist/src/pkg/http-request-utils.js +55 -0
  60. package/dist/src/pkg/http-request-utils.js.map +1 -0
  61. package/dist/src/pkg/index.d.ts +19 -0
  62. package/dist/src/pkg/index.js +46 -0
  63. package/dist/src/pkg/index.js.map +1 -0
  64. package/dist/src/pkg/key-helper.d.ts +2 -0
  65. package/dist/src/pkg/key-helper.js +20 -0
  66. package/dist/src/pkg/key-helper.js.map +1 -0
  67. package/dist/src/pkg/logger.d.ts +9 -0
  68. package/dist/src/pkg/logger.js +23 -0
  69. package/dist/src/pkg/logger.js.map +1 -0
  70. package/dist/src/pkg/object-helper.d.ts +2 -0
  71. package/dist/src/pkg/object-helper.js +37 -0
  72. package/dist/src/pkg/object-helper.js.map +1 -0
  73. package/dist/src/pkg/paginated-cache-registry.d.ts +8 -0
  74. package/dist/src/pkg/paginated-cache-registry.js +23 -0
  75. package/dist/src/pkg/paginated-cache-registry.js.map +1 -0
  76. package/dist/src/pkg/query-helper.d.ts +3 -0
  77. package/dist/src/pkg/query-helper.js +60 -0
  78. package/dist/src/pkg/query-helper.js.map +1 -0
  79. package/dist/src/pkg/referral-tree-utils.d.ts +33 -0
  80. package/dist/src/pkg/referral-tree-utils.js +71 -0
  81. package/dist/src/pkg/referral-tree-utils.js.map +1 -0
  82. package/dist/src/pkg/scripts/index.d.ts +1 -0
  83. package/dist/src/pkg/scripts/index.js +28 -0
  84. package/dist/src/pkg/scripts/index.js.map +1 -0
  85. package/dist/src/pkg/scripts/lua.d.ts +10 -0
  86. package/dist/src/pkg/scripts/lua.js +109 -0
  87. package/dist/src/pkg/scripts/lua.js.map +1 -0
  88. package/dist/src/pkg/sort-helper.d.ts +3 -0
  89. package/dist/src/pkg/sort-helper.js +18 -0
  90. package/dist/src/pkg/sort-helper.js.map +1 -0
  91. package/dist/src/pkg/string-utils.d.ts +10 -0
  92. package/dist/src/pkg/string-utils.js +79 -0
  93. package/dist/src/pkg/string-utils.js.map +1 -0
  94. package/dist/src/pkg/task-helper.d.ts +2 -0
  95. package/dist/src/pkg/task-helper.js +30 -0
  96. package/dist/src/pkg/task-helper.js.map +1 -0
  97. package/dist/src/pkg/trading-pair-helper.d.ts +9 -0
  98. package/dist/src/pkg/trading-pair-helper.js +44 -0
  99. package/dist/src/pkg/trading-pair-helper.js.map +1 -0
  100. package/dist/src/pkg/trading-pair-helper.spec.d.ts +1 -0
  101. package/dist/src/pkg/trading-pair-helper.spec.js +132 -0
  102. package/dist/src/pkg/trading-pair-helper.spec.js.map +1 -0
  103. package/dist/src/pkg/workflow/delayed-task-registry.d.ts +10 -0
  104. package/dist/src/pkg/workflow/delayed-task-registry.js +67 -0
  105. package/dist/src/pkg/workflow/delayed-task-registry.js.map +1 -0
  106. package/dist/src/pkg/workflow/delayed-task.d.ts +18 -0
  107. package/dist/src/pkg/workflow/delayed-task.js +95 -0
  108. package/dist/src/pkg/workflow/delayed-task.js.map +1 -0
  109. package/dist/src/pkg/workflow/index.d.ts +5 -0
  110. package/dist/src/pkg/workflow/index.js +22 -0
  111. package/dist/src/pkg/workflow/index.js.map +1 -0
  112. package/dist/src/pkg/workflow/processing-milestone.d.ts +18 -0
  113. package/dist/src/pkg/workflow/processing-milestone.js +39 -0
  114. package/dist/src/pkg/workflow/processing-milestone.js.map +1 -0
  115. package/dist/src/pkg/workflow/retry-task.d.ts +24 -0
  116. package/dist/src/pkg/workflow/retry-task.js +89 -0
  117. package/dist/src/pkg/workflow/retry-task.js.map +1 -0
  118. package/dist/src/pkg/workflow/retry-task.spec.d.ts +1 -0
  119. package/dist/src/pkg/workflow/retry-task.spec.js +145 -0
  120. package/dist/src/pkg/workflow/retry-task.spec.js.map +1 -0
  121. package/dist/src/pkg/workflow/sync-taskqueue.d.ts +32 -0
  122. package/dist/src/pkg/workflow/sync-taskqueue.js +108 -0
  123. package/dist/src/pkg/workflow/sync-taskqueue.js.map +1 -0
  124. package/dist/src/pkg/worksheet.utils.d.ts +27 -0
  125. package/dist/src/pkg/worksheet.utils.js +116 -0
  126. package/dist/src/pkg/worksheet.utils.js.map +1 -0
  127. package/dist/src/services/audit-service.d.ts +7 -0
  128. package/dist/src/services/audit-service.js +32 -0
  129. package/dist/src/services/audit-service.js.map +1 -0
  130. package/dist/src/services/excel.service.d.ts +25 -0
  131. package/dist/src/services/excel.service.js +95 -0
  132. package/dist/src/services/excel.service.js.map +1 -0
  133. package/dist/src/services/http-service.d.ts +7 -0
  134. package/dist/src/services/http-service.js +67 -0
  135. package/dist/src/services/http-service.js.map +1 -0
  136. package/dist/src/services/index.d.ts +8 -0
  137. package/dist/src/services/index.js +25 -0
  138. package/dist/src/services/index.js.map +1 -0
  139. package/dist/src/services/kafka-service.d.ts +15 -0
  140. package/dist/src/services/kafka-service.js +68 -0
  141. package/dist/src/services/kafka-service.js.map +1 -0
  142. package/dist/src/services/mailer-service.d.ts +15 -0
  143. package/dist/src/services/mailer-service.js +44 -0
  144. package/dist/src/services/mailer-service.js.map +1 -0
  145. package/dist/src/services/paginated-cache.d.ts +16 -0
  146. package/dist/src/services/paginated-cache.js +115 -0
  147. package/dist/src/services/paginated-cache.js.map +1 -0
  148. package/dist/src/services/paginated-cache.spec.d.ts +1 -0
  149. package/dist/src/services/paginated-cache.spec.js +284 -0
  150. package/dist/src/services/paginated-cache.spec.js.map +1 -0
  151. package/dist/src/services/redis-service.d.ts +33 -0
  152. package/dist/src/services/redis-service.js +230 -0
  153. package/dist/src/services/redis-service.js.map +1 -0
  154. package/dist/src/services/security-service.d.ts +11 -0
  155. package/dist/src/services/security-service.js +68 -0
  156. package/dist/src/services/security-service.js.map +1 -0
  157. package/dist/tsconfig.tsbuildinfo +1 -1
  158. package/package.json +1 -1
  159. package/src/constants.ts +66 -0
  160. package/src/gateways/alibaba-cloud-gateway.ts +127 -0
  161. package/src/gateways/http-audit-gateway.ts +104 -0
  162. package/src/gateways/index.ts +5 -0
  163. package/src/gateways/internal-auth-gateway.ts +42 -0
  164. package/src/gateways/stdout-audit-gateway.ts +23 -0
  165. package/src/gateways/webhook-audit-gateway.ts +33 -0
  166. package/src/interfaces.ts +304 -0
  167. package/src/models/audit-log.ts +126 -0
  168. package/src/models/index.ts +1 -0
  169. package/src/pkg/array-helper.ts +7 -0
  170. package/src/pkg/bcrypt-helper.ts +9 -0
  171. package/src/pkg/crypto-helper.ts +18 -0
  172. package/src/pkg/encryption-helper.spec.ts +423 -0
  173. package/src/pkg/encryption-helper.ts +155 -0
  174. package/src/pkg/filter-helper.spec.ts +105 -0
  175. package/src/pkg/filter-helper.ts +139 -0
  176. package/src/pkg/geoip-helper.ts +5 -0
  177. package/src/pkg/hash-helper.ts +12 -0
  178. package/src/pkg/http-request-utils.ts +75 -0
  179. package/src/pkg/index.ts +19 -0
  180. package/src/pkg/key-helper.ts +20 -0
  181. package/src/pkg/logger.ts +23 -0
  182. package/src/pkg/object-helper.ts +42 -0
  183. package/src/pkg/paginated-cache-registry.ts +25 -0
  184. package/src/pkg/query-helper.ts +79 -0
  185. package/src/pkg/referral-tree-utils.ts +165 -0
  186. package/src/pkg/scripts/index.ts +1 -0
  187. package/src/pkg/scripts/lua.ts +112 -0
  188. package/src/pkg/sort-helper.ts +19 -0
  189. package/src/pkg/string-utils.ts +104 -0
  190. package/src/pkg/task-helper.ts +25 -0
  191. package/src/pkg/trading-pair-helper.spec.ts +146 -0
  192. package/src/pkg/trading-pair-helper.ts +78 -0
  193. package/src/pkg/workflow/delayed-task-registry.ts +54 -0
  194. package/src/pkg/workflow/delayed-task.ts +106 -0
  195. package/src/pkg/workflow/index.ts +5 -0
  196. package/src/pkg/workflow/processing-milestone.ts +54 -0
  197. package/src/pkg/workflow/retry-task.spec.ts +194 -0
  198. package/src/pkg/workflow/retry-task.ts +119 -0
  199. package/src/pkg/workflow/sync-taskqueue.ts +118 -0
  200. package/src/pkg/worksheet.utils.ts +178 -0
  201. package/src/services/audit-service.ts +22 -0
  202. package/src/services/excel.service.ts +103 -0
  203. package/src/services/http-service.ts +71 -0
  204. package/src/services/index.ts +8 -0
  205. package/src/services/kafka-service.ts +81 -0
  206. package/src/services/mailer-service.ts +43 -0
  207. package/src/services/paginated-cache.spec.ts +519 -0
  208. package/src/services/paginated-cache.ts +122 -0
  209. package/src/services/redis-service.ts +238 -0
  210. package/src/services/security-service.ts +80 -0
@@ -0,0 +1,155 @@
1
+ import {
2
+ randomBytes,
3
+ pbkdf2Sync,
4
+ createCipheriv,
5
+ createDecipheriv,
6
+ } from "crypto";
7
+
8
+ const PBKDF2_ITERATIONS = 310_000; // adjust upward over time
9
+ const KEY_LEN = 32; // 256-bit AES key
10
+ const IV_LEN = 12; // standard for GCM
11
+ const SALT_LEN = 16; // at least 16 bytes
12
+
13
+ interface EncryptedPayload {
14
+ iv: string; // hex
15
+ salt: string; // hex
16
+ ciphertext: string;
17
+ tag: string; // auth tag (hex)
18
+ }
19
+
20
+ interface EncryptedPayload2FA {
21
+ iv: string;
22
+ saltUser: string;
23
+ saltServer: string;
24
+ ciphertext: string;
25
+ tag: string;
26
+ }
27
+
28
+ /**
29
+ * Encrypt a UTF-8 string using password-based AES-256-GCM
30
+ */
31
+ export function encrypt(text: string, password: string): EncryptedPayload {
32
+ const salt = randomBytes(SALT_LEN);
33
+ const key = pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, KEY_LEN, "sha256");
34
+
35
+ const iv = randomBytes(IV_LEN);
36
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
37
+
38
+ const ciphertext = Buffer.concat([
39
+ cipher.update(text, "utf8"),
40
+ cipher.final(),
41
+ ]);
42
+ const tag = cipher.getAuthTag();
43
+
44
+ return {
45
+ iv: iv.toString("hex"),
46
+ salt: salt.toString("hex"),
47
+ ciphertext: ciphertext.toString("hex"),
48
+ tag: tag.toString("hex"),
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Decrypt payload produced by `encrypt`
54
+ */
55
+ export function decrypt(payload: EncryptedPayload, password: string): string {
56
+ const { iv, salt, ciphertext, tag } = payload;
57
+
58
+ const key = pbkdf2Sync(
59
+ Buffer.from(password),
60
+ Buffer.from(salt, "hex"),
61
+ PBKDF2_ITERATIONS,
62
+ KEY_LEN,
63
+ "sha256"
64
+ );
65
+
66
+ const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "hex"));
67
+ decipher.setAuthTag(Buffer.from(tag, "hex"));
68
+
69
+ const plaintext = Buffer.concat([
70
+ decipher.update(Buffer.from(ciphertext, "hex")),
71
+ decipher.final(),
72
+ ]);
73
+
74
+ return plaintext.toString("utf8");
75
+ }
76
+
77
+ function deriveKey(password: string, salt: Buffer): Buffer {
78
+ return pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, KEY_LEN, "sha256");
79
+ }
80
+
81
+ export function encryptWithTwoFactors(
82
+ plaintext: string,
83
+ userPassword: string,
84
+ serverSecret: string
85
+ ): EncryptedPayload2FA {
86
+ const saltUser = randomBytes(SALT_LEN);
87
+ const saltServer = randomBytes(SALT_LEN);
88
+
89
+ const userKey = deriveKey(userPassword, saltUser);
90
+ const serverKey = deriveKey(serverSecret, saltServer);
91
+
92
+ // Final AES key: XOR of both keys
93
+ const finalKey = Buffer.alloc(KEY_LEN);
94
+ for (let i = 0; i < KEY_LEN; i++) {
95
+ finalKey[i] = userKey[i] ^ serverKey[i];
96
+ }
97
+
98
+ const iv = randomBytes(IV_LEN);
99
+ const cipher = createCipheriv("aes-256-gcm", finalKey, iv);
100
+
101
+ const ciphertext = Buffer.concat([
102
+ cipher.update(plaintext, "utf8"),
103
+ cipher.final(),
104
+ ]);
105
+ const tag = cipher.getAuthTag();
106
+
107
+ // Cleanup sensitive buffers
108
+ userKey.fill(0);
109
+ serverKey.fill(0);
110
+ finalKey.fill(0);
111
+
112
+ return {
113
+ iv: iv.toString("hex"),
114
+ saltUser: saltUser.toString("hex"),
115
+ saltServer: saltServer.toString("hex"),
116
+ ciphertext: ciphertext.toString("hex"),
117
+ tag: tag.toString("hex"),
118
+ };
119
+ }
120
+
121
+ export function decryptWithTwoFactors(
122
+ payload: EncryptedPayload2FA,
123
+ userPassword: string,
124
+ serverSecret: string
125
+ ): string {
126
+ const userKey = deriveKey(userPassword, Buffer.from(payload.saltUser, "hex"));
127
+ const serverKey = deriveKey(
128
+ serverSecret,
129
+ Buffer.from(payload.saltServer, "hex")
130
+ );
131
+
132
+ const finalKey = Buffer.alloc(KEY_LEN);
133
+ for (let i = 0; i < KEY_LEN; i++) {
134
+ finalKey[i] = userKey[i] ^ serverKey[i];
135
+ }
136
+
137
+ const decipher = createDecipheriv(
138
+ "aes-256-gcm",
139
+ finalKey,
140
+ Buffer.from(payload.iv, "hex")
141
+ );
142
+ decipher.setAuthTag(Buffer.from(payload.tag, "hex"));
143
+
144
+ const plaintext = Buffer.concat([
145
+ decipher.update(Buffer.from(payload.ciphertext, "hex")),
146
+ decipher.final(),
147
+ ]);
148
+
149
+ // Cleanup sensitive buffers
150
+ userKey.fill(0);
151
+ serverKey.fill(0);
152
+ finalKey.fill(0);
153
+
154
+ return plaintext.toString("utf8");
155
+ }
@@ -0,0 +1,105 @@
1
+ import { expect } from "chai";
2
+
3
+ import { FILTER_OPERATOR } from "../constants";
4
+ import { IFilter } from "../interfaces";
5
+ import { toSimpleMongooseFilter } from "./filter-helper";
6
+
7
+ describe("filter helper", () => {
8
+ describe("simple mongoose filter", () => {
9
+ it("should parse simple equal filters correctly", () => {
10
+ const filters: IFilter[] = [
11
+ {
12
+ field: "name",
13
+ operator: FILTER_OPERATOR.EQUAL,
14
+ value: "andy",
15
+ },
16
+ {
17
+ field: "email",
18
+ operator: FILTER_OPERATOR.EQUAL,
19
+ value: "andy@gmail.com",
20
+ },
21
+ ];
22
+
23
+ const parsedFilter = toSimpleMongooseFilter(filters);
24
+
25
+ expect(parsedFilter.name).to.be.equal("andy");
26
+ expect(parsedFilter.email).to.be.equal("andy@gmail.com");
27
+ });
28
+
29
+ it("should parse more complex filters correctly", () => {
30
+ const filters: IFilter[] = [
31
+ {
32
+ field: "name",
33
+ operator: FILTER_OPERATOR.INS_STARTS_WITH,
34
+ value: "andy",
35
+ },
36
+ {
37
+ field: "email",
38
+ operator: FILTER_OPERATOR.INS_ENDS_WITH,
39
+ value: "andy@gmail.com",
40
+ },
41
+ {
42
+ field: "age",
43
+ operator: FILTER_OPERATOR.IN,
44
+ value: [20, 30, 40],
45
+ },
46
+ ];
47
+
48
+ const parsedFilter = toSimpleMongooseFilter(filters);
49
+
50
+ expect(parsedFilter.name).to.be.deep.equal({
51
+ $regex: "^andy.*$",
52
+ $options: "i",
53
+ });
54
+
55
+ expect(parsedFilter.email).to.be.deep.equal({
56
+ $regex: ".*andy@gmail.com$",
57
+ $options: "i",
58
+ });
59
+
60
+ expect(parsedFilter.age).to.be.deep.equal([20, 30, 40]);
61
+ });
62
+
63
+ it("should parse OR operator correctly", () => {
64
+ const filters: IFilter[] = [
65
+ {
66
+ field: null,
67
+ operator: FILTER_OPERATOR.OR,
68
+ value: [
69
+ {
70
+ field: "name",
71
+ operator: FILTER_OPERATOR.EQUAL,
72
+ value: "andy",
73
+ },
74
+ {
75
+ field: "name",
76
+ operator: FILTER_OPERATOR.EQUAL,
77
+ value: "devstic",
78
+ },
79
+ ] as IFilter[],
80
+ },
81
+ {
82
+ field: "email",
83
+ operator: FILTER_OPERATOR.INS_LIKE,
84
+ value: "andy@gmail.com",
85
+ },
86
+ ];
87
+
88
+ const parsedFilter = toSimpleMongooseFilter(filters);
89
+
90
+ expect(parsedFilter.$or).to.be.deep.equal([
91
+ {
92
+ name: "andy",
93
+ },
94
+ {
95
+ name: "devstic",
96
+ },
97
+ ]);
98
+
99
+ expect(parsedFilter.email).to.be.deep.equal({
100
+ $regex: ".*andy@gmail.com.*",
101
+ $options: "i",
102
+ });
103
+ });
104
+ });
105
+ });
@@ -0,0 +1,139 @@
1
+ import { FILTER_OPERATOR } from "../constants";
2
+ import { IFilter } from "../interfaces";
3
+
4
+ export const toSimpleMongooseFilter = (
5
+ filters: IFilter[]
6
+ ): Record<string, any> => {
7
+ return filters.reduce((agg, current) => {
8
+ switch (current.operator) {
9
+ case FILTER_OPERATOR.EQUAL:
10
+ agg[current.field] = current.value;
11
+
12
+ break;
13
+ case FILTER_OPERATOR.NOT_EQUAL:
14
+ agg[current.field] = {
15
+ $ne: current.value,
16
+ };
17
+
18
+ break;
19
+
20
+ case FILTER_OPERATOR.NOT:
21
+ agg[current.field] = {
22
+ $ne: current.value,
23
+ };
24
+
25
+ break;
26
+
27
+ case FILTER_OPERATOR.LIKE:
28
+ agg[current.field] = {
29
+ $regex: `.*${current.value}.*`,
30
+ };
31
+
32
+ break;
33
+
34
+ case FILTER_OPERATOR.INS_LIKE:
35
+ agg[current.field] = {
36
+ $regex: `.*${current.value}.*`,
37
+ $options: "i",
38
+ };
39
+
40
+ break;
41
+
42
+ case FILTER_OPERATOR.STARTS_WITH:
43
+ agg[current.field] = {
44
+ $regex: `^${current.value}.*$`,
45
+ };
46
+
47
+ break;
48
+ case FILTER_OPERATOR.ENDS_WITH:
49
+ agg[current.field] = {
50
+ $regex: `.*${current.value}$`,
51
+ };
52
+
53
+ break;
54
+ case FILTER_OPERATOR.INS_STARTS_WITH:
55
+ agg[current.field] = {
56
+ $regex: `^${current.value}.*$`,
57
+ $options: "i",
58
+ };
59
+
60
+ break;
61
+ case FILTER_OPERATOR.INS_ENDS_WITH:
62
+ agg[current.field] = {
63
+ $regex: `.*${current.value}$`,
64
+ $options: "i",
65
+ };
66
+
67
+ break;
68
+ case FILTER_OPERATOR.GREATER_THAN:
69
+ agg[current.field] = {
70
+ $gt: current.value,
71
+ };
72
+
73
+ break;
74
+
75
+ case FILTER_OPERATOR.GREATER_THAN_OR_EQUAL:
76
+ agg[current.field] = {
77
+ $gte: current.value,
78
+ };
79
+
80
+ break;
81
+
82
+ case FILTER_OPERATOR.LESS_THAN:
83
+ agg[current.field] = {
84
+ $lt: current.value,
85
+ };
86
+
87
+ break;
88
+
89
+ case FILTER_OPERATOR.LESS_THAN_OR_EQUAL:
90
+ agg[current.field] = {
91
+ $lte: current.value,
92
+ };
93
+
94
+ break;
95
+
96
+ case FILTER_OPERATOR.IN:
97
+ agg[current.field] = current.value;
98
+
99
+ break;
100
+
101
+ case FILTER_OPERATOR.NOT_IN:
102
+ agg[current.field] = {
103
+ $nin: current.value,
104
+ };
105
+
106
+ break;
107
+
108
+ case FILTER_OPERATOR.OR:
109
+ const parsedOr =
110
+ current.value?.map((filterCondition: IFilter) =>
111
+ toSimpleMongooseFilter([filterCondition])
112
+ ) || [];
113
+
114
+ if (!parsedOr.length) {
115
+ break;
116
+ }
117
+
118
+ agg.$or = parsedOr;
119
+
120
+ break;
121
+
122
+ case FILTER_OPERATOR.NOR:
123
+ const parsedNor =
124
+ current.value?.map((filterCondition: IFilter) =>
125
+ toSimpleMongooseFilter([filterCondition])
126
+ ) || [];
127
+
128
+ if (!parsedNor.length) {
129
+ break;
130
+ }
131
+
132
+ agg.$nor = parsedNor;
133
+
134
+ break;
135
+ }
136
+
137
+ return agg;
138
+ }, {} as Record<string, any>);
139
+ };
@@ -0,0 +1,5 @@
1
+ import * as geoip from "geoip-country";
2
+
3
+ export function lookupIp(address: string): geoip.Lookup {
4
+ return geoip.lookup(address);
5
+ }
@@ -0,0 +1,12 @@
1
+ import * as crypto from "crypto";
2
+
3
+ import jsonS = require("fast-json-stable-stringify");
4
+
5
+ export const generateHashFromJSON = (data: Record<string, any>): string => {
6
+ if (!data || typeof data !== "object") {
7
+ throw new Error("Input must be a non-null object");
8
+ }
9
+
10
+ const jsonString = jsonS(data);
11
+ return crypto.createHash("sha256").update(jsonString).digest("hex");
12
+ };
@@ -0,0 +1,75 @@
1
+ export function constructUrlQueryString(
2
+ url: string,
3
+ queryStringData: any,
4
+ options?: { encodeUrl?: boolean }
5
+ ): string {
6
+ if (!queryStringData) {
7
+ return url;
8
+ }
9
+
10
+ const encoder = options?.encodeUrl
11
+ ? encodeURIComponent
12
+ : (value: any) => value;
13
+
14
+ const rawQueryString = [];
15
+ for (const props in queryStringData) {
16
+ const propValue = queryStringData[props];
17
+ if (propValue === undefined || propValue === null) {
18
+ continue;
19
+ }
20
+
21
+ if (typeof propValue === "object") {
22
+ rawQueryString.push(`${props}=${encoder(JSON.stringify(propValue))}`);
23
+ } else {
24
+ rawQueryString.push(`${props}=${encoder(propValue)}`);
25
+ }
26
+ }
27
+
28
+ return `${url}?${rawQueryString.join("&")}`;
29
+ }
30
+
31
+ const MASK_FIELDS = ["password", "secret"];
32
+
33
+ export function maskSensitiveData(
34
+ data: any,
35
+ maskFields: string[] = MASK_FIELDS
36
+ ): Record<string, any> {
37
+ // It is a string, number, or whatever. We don't process
38
+ if (typeof data !== "object") {
39
+ return data;
40
+ }
41
+
42
+ // Data is an object
43
+ if (!Array.isArray(data)) {
44
+ const maskedData = Object.assign({}, data || {});
45
+ const keys = Object.keys(data);
46
+
47
+ keys.forEach((key) => {
48
+ let value = data[key];
49
+
50
+ if (!value) {
51
+ return;
52
+ }
53
+
54
+ if (typeof value === "object") {
55
+ value = maskSensitiveData(value, maskFields);
56
+
57
+ maskedData[key] = value;
58
+
59
+ return;
60
+ }
61
+
62
+ // Key is not sensitive
63
+ if (!maskFields.includes(key)) {
64
+ return;
65
+ }
66
+
67
+ maskedData[key] = "***";
68
+ });
69
+
70
+ return maskedData;
71
+ }
72
+
73
+ // Data is an array
74
+ return data.map((i) => maskSensitiveData(i, maskFields));
75
+ }
@@ -0,0 +1,19 @@
1
+ export * as bcryptHelper from "./bcrypt-helper";
2
+ export * as httpRequestUtils from "./http-request-utils";
3
+ export * as objectHelper from "./object-helper";
4
+ export * as queryHelper from "./query-helper";
5
+ export * as stringUtils from "./string-utils";
6
+ export * as worksheetUtils from "./worksheet.utils";
7
+ export * as cryptoHelpers from "./crypto-helper";
8
+ export * as sortHelpers from "./sort-helper";
9
+ export * as filterHelpers from "./filter-helper";
10
+ export * as loggers from "./logger";
11
+ export * as workflows from "./workflow";
12
+ export * as geoipHelpers from "./geoip-helper";
13
+ export * as arrayHelpers from "./array-helper";
14
+ export * as referralTreeHelpers from "./referral-tree-utils";
15
+ export * as timeoutHelper from "./task-helper";
16
+ export * as cacheHelper from "./paginated-cache-registry";
17
+ export * as encryptionHelper from "./encryption-helper";
18
+ export * as scripts from "./scripts";
19
+ export * as tradingPairHelper from "./trading-pair-helper";
@@ -0,0 +1,20 @@
1
+ const versionPlaceholder = '_version';
2
+
3
+ // Helper functions for versioned cache keys
4
+ export const getVersionedCacheKey = (key: string, version: number) => {
5
+ if (key.includes(versionPlaceholder)) {
6
+ return key.replace(versionPlaceholder, version.toString());
7
+ }
8
+
9
+ return `${key}:version:${version}`;
10
+ };
11
+
12
+ export const getVersionCacheKeyForKey = (key: string) => {
13
+ if (key.includes(versionPlaceholder)) {
14
+ const indexOfPlaceholder = key.indexOf(versionPlaceholder);
15
+
16
+ return key.substring(0, indexOfPlaceholder);
17
+ }
18
+
19
+ return `${key}:version`;
20
+ };
@@ -0,0 +1,23 @@
1
+ import pino from "pino";
2
+
3
+ import { Logger } from "../interfaces";
4
+
5
+ export class PinoLogger implements Logger {
6
+ protected _logger: pino.Logger;
7
+
8
+ constructor() {
9
+ this._logger = pino();
10
+ }
11
+
12
+ public info(message: string, ...args: any[]): void {
13
+ return this._logger.info(message, ...args);
14
+ }
15
+
16
+ public error(message: string, ...args: any[]): void {
17
+ return this._logger.error(message, ...args);
18
+ }
19
+
20
+ public warn(message: string, ...args: any[]): void {
21
+ return this._logger.warn(message, ...args);
22
+ }
23
+ }
@@ -0,0 +1,42 @@
1
+ export function removeUndefinedProps(data: any): any {
2
+ const allKeys = Object.keys(data);
3
+
4
+ return allKeys.reduce((aggregated, current) => {
5
+ if (data[current] !== undefined) {
6
+ aggregated[current] = data[current];
7
+ }
8
+
9
+ return aggregated;
10
+ }, {});
11
+ }
12
+
13
+ export const tryParseStringIntoCorrectData = (data: string): any => {
14
+ if (!data?.length) {
15
+ return;
16
+ }
17
+
18
+ try {
19
+ // Parse boolean
20
+ if (data === "true") {
21
+ return true;
22
+ }
23
+
24
+ if (data === "false") {
25
+ return false;
26
+ }
27
+
28
+ // Parse number
29
+ const dataAsNumber = Number(data);
30
+
31
+ if (!Number.isNaN(dataAsNumber)) {
32
+ return dataAsNumber;
33
+ }
34
+
35
+ // Parse object
36
+ const parsedObject = JSON.parse(data);
37
+
38
+ return parsedObject;
39
+ } catch (error) {
40
+ return data;
41
+ }
42
+ };
@@ -0,0 +1,25 @@
1
+ import { CacheService, IPaginatedDataCache } from "../interfaces";
2
+ import { PaginatedDataCache } from "../services/paginated-cache";
3
+
4
+ export class PaginatedCacheRegistry {
5
+ protected _registry = new Map<string, IPaginatedDataCache>();
6
+
7
+ constructor(protected cacheService: CacheService) {}
8
+
9
+ public has(dataName: string): boolean {
10
+ return this._registry.has(dataName);
11
+ }
12
+
13
+ public getOrCreatePaginatedCache<T = any>(
14
+ dataName: string
15
+ ): IPaginatedDataCache<T> {
16
+ if (this._registry.has(dataName)) {
17
+ return this._registry.get(dataName);
18
+ }
19
+
20
+ const service = new PaginatedDataCache(dataName, this.cacheService);
21
+ this._registry.set(dataName, service);
22
+
23
+ return service;
24
+ }
25
+ }
@@ -0,0 +1,79 @@
1
+ import { FILTER_OPERATOR } from "../constants";
2
+ import { IFilter, ISort } from "../interfaces";
3
+
4
+ /**
5
+ * Parses a sort data such as "-price name date" into an array of generic sort data
6
+ * @param data the sort string
7
+ * @returns ISort[]
8
+ */
9
+ export function parseSort(data: string): ISort[] {
10
+ if (!data) {
11
+ return [];
12
+ }
13
+
14
+ const sortConditions: ISort[] = data.split(" ").map((item) => {
15
+ if (item[0] === "-") {
16
+ return {
17
+ columnName: item.slice(1, item.length - 1),
18
+ direction: "DESC",
19
+ };
20
+ }
21
+
22
+ return {
23
+ columnName: item,
24
+ direction: "ASC",
25
+ };
26
+ });
27
+
28
+ return sortConditions;
29
+ }
30
+
31
+ /**
32
+ * Parses filter expression for a field name
33
+ * @param field The fieldname in query string ?email=
34
+ * @param filterData The filter expression. Ex: eq:123 lt:100 gt:400
35
+ * @returns IFilter
36
+ */
37
+ export function parseFilter(field: string, filterData: string): IFilter {
38
+ if (!filterData) {
39
+ throw new Error("missing filter data");
40
+ }
41
+
42
+ const splittedData = filterData.split(":");
43
+ if (splittedData.length === 1) {
44
+ return {
45
+ field,
46
+ operator: FILTER_OPERATOR.EQUAL,
47
+ value: splittedData[0],
48
+ };
49
+ }
50
+
51
+ if (splittedData.length === 2) {
52
+ const [operator, value] = splittedData;
53
+
54
+ if (!Object.keys(FILTER_OPERATOR).includes(operator)) {
55
+ throw new Error(`invalid filter operator ${operator}`);
56
+ }
57
+
58
+ if (operator === FILTER_OPERATOR.OR || operator === FILTER_OPERATOR.AND) {
59
+ throw new Error("operator $or and $and are only for internal use");
60
+ }
61
+
62
+ if (
63
+ operator === FILTER_OPERATOR.IN ||
64
+ operator === FILTER_OPERATOR.NOT_IN
65
+ ) {
66
+ return {
67
+ field,
68
+ operator: operator as FILTER_OPERATOR,
69
+ value: value.split(","),
70
+ };
71
+ }
72
+
73
+ return {
74
+ field,
75
+ operator: operator as FILTER_OPERATOR,
76
+ value,
77
+ };
78
+ }
79
+ }