@blazedpath/commons 0.0.4

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 (224) hide show
  1. package/README.md +3 -0
  2. package/blz-base/health/index.js +215 -0
  3. package/blz-base/index.js +1466 -0
  4. package/blz-cache/LruCache.js +44 -0
  5. package/blz-cache/index.js +29 -0
  6. package/blz-config/index.js +434 -0
  7. package/blz-core/index.js +364 -0
  8. package/blz-cryptography/index.js +54 -0
  9. package/blz-datetimes/index.js +356 -0
  10. package/blz-file/example.dat +2545 -0
  11. package/blz-file/fileService.js +205 -0
  12. package/blz-file/index.js +94 -0
  13. package/blz-file/index.test.js +31 -0
  14. package/blz-file/lab.js +33 -0
  15. package/blz-hazelcast/index.js +189 -0
  16. package/blz-hazelcast/lib/credentials.js +25 -0
  17. package/blz-hazelcast/lib/credentialsFactory.js +12 -0
  18. package/blz-hazelcast/lib/hazelcastCache.js +234 -0
  19. package/blz-iterable/index.js +446 -0
  20. package/blz-json-schema/index.js +11 -0
  21. package/blz-jwt/index.js +121 -0
  22. package/blz-kafka/index.js +522 -0
  23. package/blz-math/index.js +131 -0
  24. package/blz-mongodb/index.js +326 -0
  25. package/blz-rds/__test__/scape.test.js +58 -0
  26. package/blz-rds/blz-rds-executor.js +578 -0
  27. package/blz-rds/blz-rds-helper.js +310 -0
  28. package/blz-rds/commands/core/add.js +13 -0
  29. package/blz-rds/commands/core/and.js +18 -0
  30. package/blz-rds/commands/core/asc.js +10 -0
  31. package/blz-rds/commands/core/avg.js +10 -0
  32. package/blz-rds/commands/core/column-ref.js +8 -0
  33. package/blz-rds/commands/core/count-distinct.js +10 -0
  34. package/blz-rds/commands/core/count.js +10 -0
  35. package/blz-rds/commands/core/decimal.js +8 -0
  36. package/blz-rds/commands/core/desc.js +10 -0
  37. package/blz-rds/commands/core/distinct.js +10 -0
  38. package/blz-rds/commands/core/divide.js +11 -0
  39. package/blz-rds/commands/core/embedded-exists.js +17 -0
  40. package/blz-rds/commands/core/embedded-select.js +17 -0
  41. package/blz-rds/commands/core/equals.js +9 -0
  42. package/blz-rds/commands/core/false.js +8 -0
  43. package/blz-rds/commands/core/greater-or-equal.js +9 -0
  44. package/blz-rds/commands/core/greater.js +9 -0
  45. package/blz-rds/commands/core/in.js +9 -0
  46. package/blz-rds/commands/core/integer.js +8 -0
  47. package/blz-rds/commands/core/is-not-null.js +11 -0
  48. package/blz-rds/commands/core/is-null-or-value.js +10 -0
  49. package/blz-rds/commands/core/is-null.js +11 -0
  50. package/blz-rds/commands/core/less-or-equal.js +9 -0
  51. package/blz-rds/commands/core/less-unary.js +12 -0
  52. package/blz-rds/commands/core/less.js +9 -0
  53. package/blz-rds/commands/core/like.js +12 -0
  54. package/blz-rds/commands/core/max.js +10 -0
  55. package/blz-rds/commands/core/min.js +10 -0
  56. package/blz-rds/commands/core/multiply.js +13 -0
  57. package/blz-rds/commands/core/not-equals.js +9 -0
  58. package/blz-rds/commands/core/not-in.js +9 -0
  59. package/blz-rds/commands/core/not.js +13 -0
  60. package/blz-rds/commands/core/null.js +8 -0
  61. package/blz-rds/commands/core/nvl.js +11 -0
  62. package/blz-rds/commands/core/or.js +13 -0
  63. package/blz-rds/commands/core/parameter.js +34 -0
  64. package/blz-rds/commands/core/remainder.js +16 -0
  65. package/blz-rds/commands/core/string.js +8 -0
  66. package/blz-rds/commands/core/subtract.js +13 -0
  67. package/blz-rds/commands/core/sum.js +10 -0
  68. package/blz-rds/commands/core/true.js +8 -0
  69. package/blz-rds/commands/core/tuple.js +13 -0
  70. package/blz-rds/commands/datetimes/add-days.js +11 -0
  71. package/blz-rds/commands/datetimes/add-hours.js +11 -0
  72. package/blz-rds/commands/datetimes/add-milliseconds.js +11 -0
  73. package/blz-rds/commands/datetimes/add-minutes.js +11 -0
  74. package/blz-rds/commands/datetimes/add-months.js +11 -0
  75. package/blz-rds/commands/datetimes/add-seconds.js +11 -0
  76. package/blz-rds/commands/datetimes/add-years.js +11 -0
  77. package/blz-rds/commands/datetimes/date-diff.js +11 -0
  78. package/blz-rds/commands/datetimes/date.js +12 -0
  79. package/blz-rds/commands/datetimes/datetime-diff.js +11 -0
  80. package/blz-rds/commands/datetimes/datetime.js +15 -0
  81. package/blz-rds/commands/datetimes/day.js +10 -0
  82. package/blz-rds/commands/datetimes/hour.js +10 -0
  83. package/blz-rds/commands/datetimes/millisecond.js +10 -0
  84. package/blz-rds/commands/datetimes/minute.js +10 -0
  85. package/blz-rds/commands/datetimes/month-text.js +10 -0
  86. package/blz-rds/commands/datetimes/month.js +10 -0
  87. package/blz-rds/commands/datetimes/now.js +9 -0
  88. package/blz-rds/commands/datetimes/second.js +10 -0
  89. package/blz-rds/commands/datetimes/subtract-days.js +11 -0
  90. package/blz-rds/commands/datetimes/subtract-hours.js +11 -0
  91. package/blz-rds/commands/datetimes/subtract-milliseconds.js +11 -0
  92. package/blz-rds/commands/datetimes/subtract-minutes.js +11 -0
  93. package/blz-rds/commands/datetimes/subtract-seconds.js +11 -0
  94. package/blz-rds/commands/datetimes/time-diff.js +11 -0
  95. package/blz-rds/commands/datetimes/time.js +13 -0
  96. package/blz-rds/commands/datetimes/today.js +9 -0
  97. package/blz-rds/commands/datetimes/week-day-text.js +10 -0
  98. package/blz-rds/commands/datetimes/week-day.js +10 -0
  99. package/blz-rds/commands/datetimes/week.js +10 -0
  100. package/blz-rds/commands/datetimes/year.js +10 -0
  101. package/blz-rds/commands/math/abs.js +10 -0
  102. package/blz-rds/commands/math/acos.js +10 -0
  103. package/blz-rds/commands/math/asin.js +10 -0
  104. package/blz-rds/commands/math/atan.js +10 -0
  105. package/blz-rds/commands/math/atan2.js +11 -0
  106. package/blz-rds/commands/math/ceil.js +10 -0
  107. package/blz-rds/commands/math/cos.js +10 -0
  108. package/blz-rds/commands/math/cosh.js +10 -0
  109. package/blz-rds/commands/math/exp.js +10 -0
  110. package/blz-rds/commands/math/floor.js +10 -0
  111. package/blz-rds/commands/math/log.js +18 -0
  112. package/blz-rds/commands/math/log10.js +10 -0
  113. package/blz-rds/commands/math/pow.js +11 -0
  114. package/blz-rds/commands/math/random.js +9 -0
  115. package/blz-rds/commands/math/round.js +18 -0
  116. package/blz-rds/commands/math/sign.js +10 -0
  117. package/blz-rds/commands/math/sin.js +10 -0
  118. package/blz-rds/commands/math/sinh.js +10 -0
  119. package/blz-rds/commands/math/sqrt.js +10 -0
  120. package/blz-rds/commands/math/tan.js +10 -0
  121. package/blz-rds/commands/math/tanh.js +10 -0
  122. package/blz-rds/commands/math/trunc.js +18 -0
  123. package/blz-rds/commands/strings/concat.js +20 -0
  124. package/blz-rds/commands/strings/contains.js +12 -0
  125. package/blz-rds/commands/strings/ends-with.js +12 -0
  126. package/blz-rds/commands/strings/index-of.js +11 -0
  127. package/blz-rds/commands/strings/is-null-or-empty.js +11 -0
  128. package/blz-rds/commands/strings/is-null-or-white-space.js +11 -0
  129. package/blz-rds/commands/strings/join.js +22 -0
  130. package/blz-rds/commands/strings/last-index-of.js +11 -0
  131. package/blz-rds/commands/strings/length.js +10 -0
  132. package/blz-rds/commands/strings/pad-left.js +20 -0
  133. package/blz-rds/commands/strings/pad-right.js +20 -0
  134. package/blz-rds/commands/strings/replace.js +12 -0
  135. package/blz-rds/commands/strings/starts-with.js +12 -0
  136. package/blz-rds/commands/strings/substring.js +12 -0
  137. package/blz-rds/commands/strings/to-lower.js +10 -0
  138. package/blz-rds/commands/strings/to-upper.js +10 -0
  139. package/blz-rds/commands/strings/trim-end.js +10 -0
  140. package/blz-rds/commands/strings/trim-start.js +10 -0
  141. package/blz-rds/commands/strings/trim.js +10 -0
  142. package/blz-rds/index.js +744 -0
  143. package/blz-rds-mysql/base.js +857 -0
  144. package/blz-rds-mysql/connection-manager.js +129 -0
  145. package/blz-rds-mysql/execute-bulk-insert.js +35 -0
  146. package/blz-rds-mysql/execute-bulk-merge.js +45 -0
  147. package/blz-rds-mysql/execute-non-query.js +34 -0
  148. package/blz-rds-mysql/execute-query.js +50 -0
  149. package/blz-rds-mysql/index.js +41 -0
  150. package/blz-rds-mysql/stored-procedure.js +207 -0
  151. package/blz-rds-mysql/syntaxis.json +114 -0
  152. package/blz-rds-mysqlx/base.js +846 -0
  153. package/blz-rds-mysqlx/connection-manager.js +141 -0
  154. package/blz-rds-mysqlx/execute-bulk-insert.js +35 -0
  155. package/blz-rds-mysqlx/execute-bulk-merge.js +45 -0
  156. package/blz-rds-mysqlx/execute-non-query.js +29 -0
  157. package/blz-rds-mysqlx/execute-query.js +39 -0
  158. package/blz-rds-mysqlx/index.js +41 -0
  159. package/blz-rds-mysqlx/stored-procedure.js +179 -0
  160. package/blz-rds-mysqlx/syntaxis.json +105 -0
  161. package/blz-rds-oracle/index.js +540 -0
  162. package/blz-rds-oracle/syntaxis.json +112 -0
  163. package/blz-rds-postgres/base.js +861 -0
  164. package/blz-rds-postgres/connection-manager.js +225 -0
  165. package/blz-rds-postgres/execute-bulk-insert.js +81 -0
  166. package/blz-rds-postgres/execute-bulk-merge.js +93 -0
  167. package/blz-rds-postgres/execute-non-query.js +23 -0
  168. package/blz-rds-postgres/execute-query.js +37 -0
  169. package/blz-rds-postgres/index.js +41 -0
  170. package/blz-rds-postgres/result-set.js +51 -0
  171. package/blz-rds-postgres/stored-procedure.js +116 -0
  172. package/blz-rds-postgres/syntaxis.json +114 -0
  173. package/blz-redis/index.js +217 -0
  174. package/blz-redis/lib/redisCache.js +265 -0
  175. package/blz-regex/index.js +25 -0
  176. package/blz-security/.eslintrc.js +15 -0
  177. package/blz-security/__test__/AuthorizationKpn.yaml +1043 -0
  178. package/blz-security/__test__/FinancingSetting.yaml +177 -0
  179. package/blz-security/__test__/KpnConfigPortal.yaml +330 -0
  180. package/blz-security/__test__/OrderManagement.yaml +5190 -0
  181. package/blz-security/__test__/Security.yaml +128 -0
  182. package/blz-security/__test__/autorization.test.js +105 -0
  183. package/blz-security/__test__/orderManagement.test.js +26 -0
  184. package/blz-security/__test__/secureUrl.test.js +79 -0
  185. package/blz-security/__test__/solveMergeRule.test.js +109 -0
  186. package/blz-security/__test__/sqlInjectionGuard.test.js +203 -0
  187. package/blz-security/__test__/xssGuard.test.js +204 -0
  188. package/blz-security/authorizationService.js +536 -0
  189. package/blz-security/config/global.js +8 -0
  190. package/blz-security/config/welcome +8 -0
  191. package/blz-security/doc/README.md +75 -0
  192. package/blz-security/filescanner/index.js +46 -0
  193. package/blz-security/helpers/consts.js +229 -0
  194. package/blz-security/helpers/utils.js +267 -0
  195. package/blz-security/implementations/cache.js +90 -0
  196. package/blz-security/implementations/oidc.js +404 -0
  197. package/blz-security/implementations/pkceCacheStore.js +23 -0
  198. package/blz-security/implementations/saml.js +10 -0
  199. package/blz-security/implementations/uma.js +63 -0
  200. package/blz-security/implementations/webAuthn.js +9 -0
  201. package/blz-security/implementations/wstg.js +72 -0
  202. package/blz-security/index.js +77 -0
  203. package/blz-security/lab/index.js +27 -0
  204. package/blz-security/middleware/HapiServerAzureAd.js +641 -0
  205. package/blz-security/middleware/HapiServerKeycloak.js +840 -0
  206. package/blz-security/middleware/HapiServerSimToken.js +247 -0
  207. package/blz-security/middleware/hapi.js +515 -0
  208. package/blz-security/middleware/hapiServer.js +974 -0
  209. package/blz-security/navigationMemoryRepository.js +15 -0
  210. package/blz-security/navigationMongoDbRepository.js +73 -0
  211. package/blz-security/secureUrlService.js +47 -0
  212. package/blz-security/securityService.js +409 -0
  213. package/blz-security/sqlInjectionGuard.js +162 -0
  214. package/blz-security/templates/forbidden.html +0 -0
  215. package/blz-security/templates/session-iframe-azure-ad.html +7 -0
  216. package/blz-security/templates/session-iframe.html +73 -0
  217. package/blz-security/templates/unauthorized.html +1 -0
  218. package/blz-security/xssGuard.js +87 -0
  219. package/blz-strings/index.js +167 -0
  220. package/blz-uuid/index.js +7 -0
  221. package/blz-yaml/index.js +19 -0
  222. package/index.js +84 -0
  223. package/package.json +97 -0
  224. package/process-managers/index.js +422 -0
@@ -0,0 +1,578 @@
1
+ const toString = Object.prototype.toString;
2
+ const { z } = require('zod');
3
+ const logger = require('pino')();
4
+ class SqlInjectionGuard {
5
+ constructor(logger = console) {
6
+ this.logger = logger;
7
+ this._initialized = false;
8
+ }
9
+
10
+ _initialize() {
11
+ if (this._initialized) return;
12
+ this._initialized = true;
13
+ const allowedPatternsEnv = process.env.blz_securityApiSanitizeAllowedSqlInputPatterns;
14
+ const paramPatternsEnv = process.env.blz_securityApiSanitizeDangerousParamPatterns;
15
+ const sqlPatternsEnv = process.env.blz_securityApiSanitizeDangerousSqlPatterns;
16
+ this.onlyLog = process.env.blz_securityApiSanitizeOnlyLog === 'true';
17
+ const parseRegexArray = (input) => {
18
+ try {
19
+ if (input == undefined || input == null) return null
20
+ const rawList = JSON.parse(input); // must be an array of strings type ["--", "\\bselect\\b.+\\bfrom\\b"]
21
+ return rawList.map(pattern => new RegExp(pattern, 'i'));
22
+ } catch {
23
+ return null;
24
+ }
25
+ };
26
+ this.dangerousParamPatterns =
27
+ parseRegexArray(paramPatternsEnv) || [
28
+ /--/i,
29
+ /\/\*/i,
30
+ /\*\//i,
31
+ /\bor\b\s+\w+\s*=/i,
32
+ /\bor\b\s+.*?=.*?/i,
33
+ /\bor\b\s+'.*?'\s*=\s*'.*?'/i,
34
+ /\bor\b\s+\w+\s*like/i,
35
+ /\band\b\s+\w+\s*=/i,
36
+ /\band\b\s+\w+\s*like/i,
37
+ /\bselect\b[\s\S]+?\bfrom\b/i,
38
+ /\bunion\s+select\b/i,
39
+ /\bdrop\s+table\b/i,
40
+ /\binsert\s+into\b/i,
41
+ /\bupdate\b\s+\w+\s+\bset\b[\s\S]*?=/i,
42
+ /\bdelete\s+from\b/i,
43
+ /\bpg_sleep\s*\(/i,
44
+ /\bdbms_lock\.sleep\s*\(/i,
45
+ /\bexec\s*\(/i,
46
+ /\bexecute\s*\(/i
47
+ ];
48
+ this.dangerousSqlPatterns =
49
+ parseRegexArray(sqlPatternsEnv) || [
50
+ /;\s*drop\b/i,
51
+ /;\s*truncate\b/i,
52
+ /\bpg_sleep\s*\(/i,
53
+ /\bdbms_lock\.sleep\s*\(/i,
54
+ /\bexec(ute)?\s*(\(|\s)/i,
55
+ /\binformation_schema\b/i,
56
+ /\bpg_catalog\b/i,
57
+ ];
58
+ this.allowedInputPatterns =
59
+ parseRegexArray(allowedPatternsEnv) || [
60
+ new RegExp('^[^<>]*<$', 'i'),
61
+ new RegExp('^>[^<>]*$', 'i')
62
+ ];
63
+ // Define a schema for each param object
64
+ this.paramSchema = z.object({
65
+ name: z.string(),
66
+ value: z.any(), // value can be string, number, etc.
67
+ });
68
+ // Schema for the full list
69
+ this.paramsSchema = z.array(this.paramSchema);
70
+ }
71
+
72
+ isAllowedByWhitelist(value) {
73
+ return this.allowedInputPatterns.some(pattern => pattern.test(value));
74
+ }
75
+
76
+ validateParamValue(name, value) {
77
+ this. _initialize()
78
+ if (typeof value !== 'string') return;
79
+ const trimmed = value.trim();
80
+ if (this.isAllowedByWhitelist(trimmed)) return
81
+ // Always check for dangerous SQL injection patterns
82
+ for (const pattern of this.dangerousParamPatterns) {
83
+ if (pattern.test(trimmed)) {
84
+ const message = `Potential SQL injection in parameter "${name}": ${value}`;
85
+ if (this.onlyLog) {
86
+ this.logger?.warn?.(`[SQLInjectionGuard] ${message}`);
87
+ } else {
88
+ const err = new Error('Potential SQL injection');
89
+ err.code = 'SQLInjection';
90
+ err.data = message;
91
+ throw err;
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ validateParamList(params) {
98
+ this. _initialize()
99
+ this.paramsSchema.parse(params); // Validate structure with Zod
100
+ for (const param of params) {
101
+ this.validateParamValue(param.name, param.value);
102
+ }
103
+ return params;
104
+ }
105
+
106
+ validateRawSql(sql) {
107
+ this. _initialize()
108
+ if (typeof sql !== 'string') return false;
109
+ for (const pattern of this.dangerousSqlPatterns) {
110
+ if (pattern.test(sql.toLowerCase())) {
111
+ const message = `Potential SQL injection in "${sql}" pattern:${pattern}`;
112
+ if (this.onlyLog) {
113
+ this.logger.warn(`[SQLInjectionGuard] ${message}`);
114
+ } else {
115
+ const err = new Error('Potential SQL injection');
116
+ err.code = 'SQLInjection';
117
+ err.data = message;
118
+ throw err;
119
+ }
120
+ }
121
+ }
122
+ return sql
123
+ }
124
+
125
+ validateObject(obj) {
126
+ this. _initialize()
127
+ const checkValue = (value) => {
128
+ if (typeof value === 'string') {
129
+ const trimmed = value.trim();
130
+ if (!this.isAllowedByWhitelist(trimmed)) {
131
+ for (const pattern of this.dangerousParamPatterns) {
132
+ if (pattern.test(trimmed)) {
133
+ const message = `Value "${value}" violates SQL injection policy.`;
134
+ if (this.onlyLog) {
135
+ this.logger.warn(`[SQLInjectionGuard] ${message}`);
136
+ } else {
137
+ const err = new Error('Potential SQL injection');
138
+ err.code = 'BadRequest';
139
+ err.data = message;
140
+ throw err;
141
+ }
142
+ }
143
+ }
144
+ }
145
+ } else if (Array.isArray(value)) {
146
+ for (const item of value) checkValue(item);
147
+ } else if (typeof value === 'object' && value !== null) {
148
+ for (const key in value) {
149
+ if (Object.hasOwn(value, key)) {
150
+ checkValue(value[key]);
151
+ }
152
+ }
153
+ }
154
+ };
155
+
156
+ checkValue(obj);
157
+ return obj;
158
+ }
159
+ }
160
+ // Instantiate guard once (e.g., globally or per module)
161
+ const guard = new SqlInjectionGuard(logger);
162
+
163
+ let adjustTypes = function (row, types) {
164
+ if (types) {
165
+ for (let i = 0; i < types.length; i++) {
166
+ if (i < row.length) {
167
+ let type = types[i];
168
+ switch (type) {
169
+ case 'string':
170
+ row[i] = convertToString(row[i]);
171
+ break;
172
+ case 'integer':
173
+ row[i] = convertToInteger(row[i]);
174
+ break;
175
+ case 'decimal':
176
+ row[i] = convertToDecimal(row[i]);
177
+ break;
178
+ case 'boolean':
179
+ row[i] = convertToBoolean(row[i]);
180
+ break;
181
+ case 'datetime':
182
+ row[i] = convertToDatetime(row[i]);
183
+ break;
184
+ case 'date':
185
+ row[i] = convertToDate(row[i]);
186
+ break;
187
+ case 'time':
188
+ row[i] = convertToTime(row[i]);
189
+ break;
190
+ case 'binary':
191
+ row[i] = convertToBinary(row[i]);
192
+ break;
193
+ }
194
+ }
195
+ }
196
+ }
197
+ };
198
+ let convertToString = function (value) {
199
+ if (value === null)
200
+ return null;
201
+ let valueType = toString.call(value);
202
+ if (valueType === '[object String]')
203
+ return value;
204
+ if (valueType === '[object Number]')
205
+ return value.toString();
206
+ if (valueType === '[object Boolean]')
207
+ return value ? 'true' : 'false';
208
+ if (valueType === '[object Date]')
209
+ return value.toJSON();
210
+ throw errorInvalidConversion(value, 'string');
211
+ };
212
+ let convertToInteger = function (value) {
213
+ if (value === null)
214
+ return null;
215
+ let valueType = toString.call(value);
216
+ if (valueType === '[object String]' && !isNaN(value))
217
+ return Math.round(Number(value));
218
+ if (valueType === '[object Number]')
219
+ return Math.round(value);
220
+ if (valueType === '[object Boolean]')
221
+ return value ? 1 : 0;
222
+ throw errorInvalidConversion(value, 'integer');
223
+ };
224
+ let convertToDecimal = function (value) {
225
+ if (value === null)
226
+ return null;
227
+ let valueType = toString.call(value);
228
+ if (valueType === '[object String]' && !isNaN(value))
229
+ return Number(value);
230
+ if (valueType === '[object Number]')
231
+ return value;
232
+ if (valueType === '[object Boolean]')
233
+ return value ? 1 : 0;
234
+ throw errorInvalidConversion(value, 'decimal');
235
+ };
236
+ let convertToBoolean = function (value) {
237
+ if (value === null)
238
+ return null;
239
+ let valueType = toString.call(value);
240
+ if (valueType === '[object String]') {
241
+ if (value === '1' || value.toUpperCase() === 'T' || value.toUpperCase() === 'TRUE' || value.toUpperCase() === 'Y' || value.toUpperCase() === 'YES')
242
+ return true;
243
+ if (value === '0' || value.toUpperCase() === 'F' || value.toUpperCase() === 'FALSE' || value.toUpperCase() === 'N' || value.toUpperCase() === 'NO')
244
+ return false;
245
+ }
246
+ if (valueType === '[object Number]') {
247
+ if (value === 1)
248
+ return true;
249
+ if (value === 0)
250
+ return false;
251
+ }
252
+ if (valueType === '[object Boolean]')
253
+ return value;
254
+ throw errorInvalidConversion(value, 'boolean');
255
+ };
256
+ let convertToDatetime = function (value) {
257
+ if (value === null)
258
+ return null;
259
+ let valueType = toString.call(value);
260
+ if (valueType === '[object String]') {
261
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
262
+ if (matchDatetime)
263
+ return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
264
+ else {
265
+ const probableDate = new Date(value);
266
+ if (probableDate.toString() !== 'Invalid Date') {
267
+ return probableDate;
268
+ }
269
+ }
270
+ }
271
+ if (valueType === '[object Date]') {
272
+ return value;
273
+ }
274
+ if (valueType === "[object Number]") {
275
+ return new Date(value);
276
+ }
277
+ throw errorInvalidConversion(value, 'datetime');
278
+ };
279
+ let convertToDate = function (value) {
280
+ if (value === null)
281
+ return null;
282
+ let valueType = toString.call(value);
283
+ if (valueType === '[object String]') {
284
+ let matchDate = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(value);
285
+ if (matchDate)
286
+ //TODO: revisar por qu esta asumiendo que es una fecha UTC cuando deberia ser local
287
+ return new Date(Date.UTC(Number(matchDate[1]), Number(matchDate[2]) - 1, Number(matchDate[3]), 0, 0, 0, 0));
288
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
289
+ if (matchDatetime)
290
+ return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), 0, 0, 0, 0));
291
+ else {
292
+ const probableDate = new Date(value);
293
+ if (probableDate.toString() !== 'Invalid Date') {
294
+ //TODO: revisar por qu esta asumiendo que es una fecha UTC cuando deberia ser local
295
+ return new Date(Date.UTC(probableDate.getUTCFullYear(), probableDate.getUTCMonth(), probableDate.getUTCDate(), 0, 0, 0, 0));
296
+ }
297
+ }
298
+ }
299
+ if (valueType === "[object Number]") {
300
+ value = new Date(value);
301
+ }
302
+ if (valueType === '[object Date]') {
303
+ return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), 0, 0, 0, 0));
304
+ }
305
+ throw errorInvalidConversion(value, 'date');
306
+ };
307
+ let convertToTime = function (value) {
308
+ if (value === null)
309
+ return null;
310
+ let valueType = toString.call(value);
311
+ if (valueType === '[object String]') {
312
+ let matchTime = /^\+?(\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?$/.exec(value);
313
+ if (matchTime) {
314
+ return new Date(Date.UTC(1970, 0, 1, Number(matchTime[1]), Number(matchTime[2]), Number(matchTime[3]), convertMilliseconds(matchTime[4])));
315
+ }
316
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
317
+ if (matchDatetime) {
318
+ return new Date(Date.UTC(1970, 0, 1, Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
319
+ }
320
+ }
321
+ if (valueType === '[object Date]') {
322
+ return new Date(Date.UTC(1970, 0, 1, value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds()));
323
+ }
324
+ throw errorInvalidConversion(value, 'time');
325
+ };
326
+ let convertToBinary = function (value) {
327
+ if (value == null)
328
+ return null;
329
+ if (value && value.type === 'Buffer')
330
+ return Buffer.from(value);
331
+ if (Buffer.isBuffer(value))
332
+ return value;
333
+ if (Array.isArray(value))
334
+ return Buffer.from(value);
335
+ throw errorInvalidConversion(value, 'binary');
336
+ };
337
+ let convertMilliseconds = function (strMilliseconds) {
338
+ if (strMilliseconds) {
339
+ if (strMilliseconds.length < 3)
340
+ strMilliseconds = strMilliseconds.padEnd(3, '0');
341
+ if (strMilliseconds.length > 3)
342
+ strMilliseconds = strMilliseconds.substr(0, 3);
343
+ return Number(strMilliseconds);
344
+ }
345
+ else
346
+ return 0;
347
+ };
348
+ let errorInvalidConversion = function (value, targetType) {
349
+ let err = new Error();
350
+ err.code = 'InvalidConversion';
351
+ err.data = { value: value, targetType: targetType };
352
+ return err;
353
+ };
354
+
355
+ function getTransactionsContext(callContext) {
356
+ if (!callContext.rdsTransactionContext) {
357
+ callContext.rdsTransactionContext = [];
358
+ }
359
+ return callContext.rdsTransactionContext;
360
+ }
361
+ /**
362
+ * @param {*} callContext
363
+ * @param {*} connection
364
+ * @return { rdsConnection: RdsConnection, mustBeClosed: boolean }
365
+ */
366
+ let getRdsConnection = async function (callContext, connection) {
367
+ /**
368
+ * 1-. Debido a que cada petición tiene su propia pila de conexiones para la
369
+ * transacción, la obtenemos para ver cúal es la conexión que debe devolver.
370
+ */
371
+ let transactionsStack = getTransactionsContext(callContext);
372
+ /**
373
+ * 2-. Si la pila se encuentra vacía, indica que no estamos en un entorno de
374
+ * transacción, por lo tanto, devolvemos una conexión nueva.
375
+ */
376
+ if (transactionsStack.length === 0) {
377
+ let rdsConnection = new RdsConnection(await connection.provider.createRdsConnection(connection), connection.provider);
378
+ return { rdsConnection, mustBeClosed: true };
379
+ } else {
380
+ /**
381
+ * 3-. Si la pila no se encuentra vacía, significa que estamos en un contexto en donde
382
+ * se manejan transacciones, la transaccion que debe utilizarla conexion es la última
383
+ *
384
+ * De esta transaccion, debemos obtener la conexion asociada al nombre de conexión. Si
385
+ * esta no existe, debemos generar una conexion nueva.
386
+ */
387
+ let connectionName = connection.name;
388
+ var transactionBrick = transactionsStack[transactionsStack.length - 1];
389
+
390
+ if (!transactionBrick.connection) {
391
+ let rdsConnection = new RdsConnection(await connection.provider.createRdsConnection(connection), connection.provider);
392
+ return { rdsConnection, mustBeClosed: true };
393
+ }
394
+ let rdsConnection = transactionBrick.connection[connectionName];
395
+ if (!rdsConnection) {
396
+ /**
397
+ * Sino, tenemos que crear una nueva conexión y asociarla con el bloque de transacción para poder
398
+ * registrarla y devolverla de ahora en mas. Además, se inicializa la conexión para indicar el tipo
399
+ * de propagación que va a tener la transacción
400
+ */
401
+ rdsConnection = new RdsConnection(await connection.provider.createRdsConnection(connection), connection.provider);
402
+ transactionBrick.connection[connectionName] = rdsConnection;
403
+ await rdsConnection.beginTransaction();
404
+ }
405
+ /**
406
+ * Si el bloque de transacción tiene asociada una conexión, devolvemos la misma, acompañada con
407
+ * el tipo de transacción que estamos llevando adelante.
408
+ */
409
+ return { rdsConnection, mustBeClosed: false };
410
+ }
411
+ };
412
+ /**
413
+ * @param {*} nativeConnection
414
+ * @param {*} provider
415
+ * @constructor
416
+ */
417
+ function RdsConnection(nativeConnection, provider) {
418
+ let transactionRequest = false;
419
+ return {
420
+ async beginTransaction() {
421
+ transactionRequest = true;
422
+ return await provider.beginTransaction(nativeConnection);
423
+ },
424
+ async close() {
425
+ transactionRequest = false;
426
+ return await provider.close(nativeConnection);
427
+ },
428
+ async commitTransaction() {
429
+ transactionRequest = false;
430
+ return await provider.commitTransaction(nativeConnection);
431
+ },
432
+ get connection() {
433
+ return nativeConnection;
434
+ },
435
+ get isTransactionRequest() {
436
+ return transactionRequest;
437
+ },
438
+ async rollbackTransaction() {
439
+ transactionRequest = false;
440
+ return await provider.rollbackTransaction(nativeConnection);
441
+ }
442
+ }
443
+ }
444
+
445
+ let _relationalDatabaseQueryId;
446
+
447
+ module.exports = {
448
+ execute: async function (callContext, connection, sql, parameters, options, types, fnSelection) {
449
+ let traceId = null;
450
+ let traceStartTime = null;
451
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true') {
452
+ if (typeof _relationalDatabaseQueryId === 'undefined')
453
+ _relationalDatabaseQueryId = 1;
454
+ else
455
+ _relationalDatabaseQueryId++;
456
+ traceId = _relationalDatabaseQueryId;
457
+ traceStartTime = Date.now();
458
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + sql + ' | PARAMETERS: ' + JSON.stringify(parameters));
459
+ }
460
+ let resultSet = null, rdsConnection = null, mustBeClosed = null;
461
+ try {
462
+ if (process.env.blz_securityApiSanitizeSqlInjection) {
463
+ sql = guard.validateRawSql(sql)
464
+ parameters = guard.validateParamList(parameters);
465
+ }
466
+ ({ rdsConnection, mustBeClosed } = await getRdsConnection(callContext, connection));
467
+ if (options) {
468
+ options.isTransactionRequest = rdsConnection.isTransactionRequest;
469
+ } else {
470
+ options = {
471
+ isTransactionRequest: rdsConnection.isTransactionRequest
472
+ };
473
+ }
474
+ let preResult = await connection.provider.executeSql(rdsConnection.connection, sql, parameters, options);
475
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true')
476
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + (Date.now() - traceStartTime) + ' milliseconds');
477
+ let result = { data: null };
478
+ if (preResult.data) {
479
+ if (options.queryOne) {
480
+ let row = preResult.data.length > 0 ? preResult.data[0] : null;
481
+ if (row) {
482
+ adjustTypes(row, types);
483
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true')
484
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + JSON.stringify(row));
485
+ result.data = await fnSelection(row);
486
+ }
487
+ else {
488
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true')
489
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | No records found');
490
+ result.data = null;
491
+ }
492
+ }
493
+ else {
494
+ result.data = [];
495
+ let rowIndex = 0;
496
+ for (let i = 0; i < preResult.data.length; i++) {
497
+ let row = preResult.data[i];
498
+ adjustTypes(row, types);
499
+ rowIndex++;
500
+ if (rowIndex <= 10 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
501
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + JSON.stringify(row));
502
+ result.data.push(await fnSelection(row));
503
+ }
504
+ if (rowIndex === 0 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
505
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | No records found');
506
+ if (rowIndex > 10 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
507
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | More records found');
508
+ }
509
+ }
510
+ else if (preResult.resultSet) {
511
+ resultSet = preResult.resultSet;
512
+ if (options.queryOne) {
513
+ let row = await resultSet.getRow();
514
+ if (row) {
515
+ adjustTypes(row, types);
516
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true')
517
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + JSON.stringify(row));
518
+ result.data = await fnSelection(row);
519
+ }
520
+ else {
521
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true')
522
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | No records found');
523
+ result.data = null;
524
+ }
525
+ }
526
+ else {
527
+ result.data = [];
528
+ let rowIndex = 0;
529
+ let row = await resultSet.getRow();
530
+ if (row)
531
+ adjustTypes(row, types);
532
+ while (row) {
533
+ rowIndex++;
534
+ if (rowIndex <= 10 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
535
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | ' + JSON.stringify(row));
536
+ result.data.push(await fnSelection(row));
537
+ row = await resultSet.getRow();
538
+ if (row)
539
+ adjustTypes(row, types);
540
+ }
541
+ if (rowIndex === 0 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
542
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | No records found');
543
+ if (rowIndex > 10 && (process.env.blz_traceAll === 'true' || process.env.blz_traceRelationalDatabaseQueries === 'true'))
544
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'RELATIONAL DATABASE QUERY (' + traceId + ') | ' + connection.name + ' | More records found');
545
+ }
546
+ }
547
+ if (preResult.rowsAffected)
548
+ result.rowsAffected = preResult.rowsAffected;
549
+ if (preResult.id)
550
+ result.id = preResult.id;
551
+ if (preResult.ids)
552
+ result.ids = preResult.ids;
553
+ if (preResult.outParameters)
554
+ result.outParameters = preResult.outParameters;
555
+ if (resultSet && resultSet.close)
556
+ await resultSet.close();
557
+ if (mustBeClosed)
558
+ await connection.provider.close(rdsConnection.connection);
559
+ return result;
560
+ }
561
+ catch (err) {
562
+ if (resultSet && resultSet.close)
563
+ await resultSet.close();
564
+ if (mustBeClosed)
565
+ await connection.provider.close(rdsConnection.connection);
566
+ let rdsError = new Error();
567
+ rdsError.code = 'RdsError';
568
+ rdsError.message = 'Error executing sql ' + sql;
569
+ rdsError.data = { connectionName: connection.name, sql: sql, parameters: parameters };
570
+ rdsError.innerError = err;
571
+ throw rdsError;
572
+ }
573
+ },
574
+ checkConnection: async function (connection) {
575
+ ({ rdsConnection, mustBeClosed } = await getRdsConnection({}, connection));
576
+ let rdsConnection = new RdsConnection(await connection.provider.createRdsConnection(connection), connection.provider);
577
+ }
578
+ };