@heliyos/heliyos-api-core 1.0.67 → 1.0.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.
- package/dist/email/index.js +5 -2
- package/dist/middleware.js +54 -9
- package/package.json +1 -1
- package/src/email/index.ts +6 -2
package/dist/email/index.js
CHANGED
|
@@ -52,12 +52,12 @@ const markdownToHtml = (text) => {
|
|
|
52
52
|
// Bold: **text** or __text__
|
|
53
53
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
54
54
|
.replace(/__(.*?)__/g, "<strong>$1</strong>")
|
|
55
|
-
// Italics: *text*
|
|
55
|
+
// Italics: *text* (intentionally avoid _text_ to keep URLs/query keys intact)
|
|
56
56
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
57
|
-
.replace(/_(.*?)_/g, "<em>$1</em>")
|
|
58
57
|
// Newlines to <br>
|
|
59
58
|
.replace(/\n/g, "<br>");
|
|
60
59
|
};
|
|
60
|
+
const URL_LIKE_PATTERN = /^(https?:\/\/|mailto:|tel:)\S+$/i;
|
|
61
61
|
/**
|
|
62
62
|
* Recursively process object values to convert markdown to HTML
|
|
63
63
|
*/
|
|
@@ -65,6 +65,9 @@ const processMarkdownData = (data) => {
|
|
|
65
65
|
if (!data)
|
|
66
66
|
return data;
|
|
67
67
|
if (typeof data === "string") {
|
|
68
|
+
if (URL_LIKE_PATTERN.test(data.trim())) {
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
68
71
|
return markdownToHtml(data);
|
|
69
72
|
}
|
|
70
73
|
if (Array.isArray(data)) {
|
package/dist/middleware.js
CHANGED
|
@@ -19,6 +19,55 @@ const serve_static_1 = __importDefault(require("serve-static"));
|
|
|
19
19
|
const authentication_1 = require("./authentication");
|
|
20
20
|
const allowedOrigin_1 = require("./allowedOrigin");
|
|
21
21
|
const customError_1 = require("./@types/globals/customError");
|
|
22
|
+
const genericErrorMessage = "Something went wrong";
|
|
23
|
+
const defaultErrorStatusCode = 500;
|
|
24
|
+
const nonProductionEnvironments = new Set(["development", "local", "test"]);
|
|
25
|
+
const sensitiveErrorMessagePatterns = [
|
|
26
|
+
/https?:\/\//i,
|
|
27
|
+
/\bapi\.[a-z0-9.-]+\b/i,
|
|
28
|
+
/\btraceback\b/i,
|
|
29
|
+
/\bstack trace\b/i,
|
|
30
|
+
/\b(httpx|requests|axios)\b/i,
|
|
31
|
+
/\bparallel(?:\.ai)?\b/i,
|
|
32
|
+
];
|
|
33
|
+
const isProductionEnvironment = () => {
|
|
34
|
+
const nodeEnv = (process.env.NODE_ENV || "").toLowerCase();
|
|
35
|
+
return !nonProductionEnvironments.has(nodeEnv);
|
|
36
|
+
};
|
|
37
|
+
const toStatusCode = (status) => Number.isFinite(Number(status))
|
|
38
|
+
? Number(status)
|
|
39
|
+
: defaultErrorStatusCode;
|
|
40
|
+
const isSensitiveErrorMessage = (message) => {
|
|
41
|
+
if (!message) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (message.length > 220 || message.includes("\n") || message.includes("\r")) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return sensitiveErrorMessagePatterns.some((pattern) => pattern.test(message));
|
|
48
|
+
};
|
|
49
|
+
const sanitizeErrorMessage = (message, statusCode) => {
|
|
50
|
+
if (!isProductionEnvironment()) {
|
|
51
|
+
return message || genericErrorMessage;
|
|
52
|
+
}
|
|
53
|
+
const normalizedMessage = (message || "").trim();
|
|
54
|
+
if (!normalizedMessage) {
|
|
55
|
+
return genericErrorMessage;
|
|
56
|
+
}
|
|
57
|
+
if (statusCode >= 500 && isSensitiveErrorMessage(normalizedMessage)) {
|
|
58
|
+
return genericErrorMessage;
|
|
59
|
+
}
|
|
60
|
+
if (statusCode < 500 && isSensitiveErrorMessage(normalizedMessage)) {
|
|
61
|
+
return genericErrorMessage;
|
|
62
|
+
}
|
|
63
|
+
return normalizedMessage;
|
|
64
|
+
};
|
|
65
|
+
const sanitizeErrorDescription = (description) => {
|
|
66
|
+
if (isProductionEnvironment()) {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
return description;
|
|
70
|
+
};
|
|
22
71
|
/**
|
|
23
72
|
* Function to handle invalid routes
|
|
24
73
|
* @param _
|
|
@@ -134,10 +183,10 @@ const apply_cors = (req, res, next) => {
|
|
|
134
183
|
*/
|
|
135
184
|
const handle_errors = (error, _, res, __) => {
|
|
136
185
|
const { message, description, stack, status } = error;
|
|
137
|
-
const
|
|
186
|
+
const statusCode = toStatusCode(status);
|
|
138
187
|
const response = {
|
|
139
|
-
message,
|
|
140
|
-
description,
|
|
188
|
+
message: sanitizeErrorMessage(message, statusCode),
|
|
189
|
+
description: sanitizeErrorDescription(description),
|
|
141
190
|
};
|
|
142
191
|
// Log original error
|
|
143
192
|
console.error("=== Begin Error ===\n---\n" +
|
|
@@ -153,14 +202,10 @@ const handle_errors = (error, _, res, __) => {
|
|
|
153
202
|
"Stack: " +
|
|
154
203
|
stack +
|
|
155
204
|
"\n---\n=== End Error ===");
|
|
156
|
-
if (!errorStatus) {
|
|
157
|
-
response.message = "Internal server error";
|
|
158
|
-
}
|
|
159
205
|
// Provide stack track in env development and local
|
|
160
|
-
if (
|
|
161
|
-
process.env.NODE_ENV === "local") {
|
|
206
|
+
if (!isProductionEnvironment()) {
|
|
162
207
|
response.error = Object.assign({ stack }, error);
|
|
163
208
|
}
|
|
164
209
|
// Send status and response
|
|
165
|
-
return res.status(
|
|
210
|
+
return res.status(statusCode).json(response);
|
|
166
211
|
};
|
package/package.json
CHANGED
package/src/email/index.ts
CHANGED
|
@@ -25,13 +25,14 @@ const markdownToHtml = (text: string): string => {
|
|
|
25
25
|
// Bold: **text** or __text__
|
|
26
26
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
27
27
|
.replace(/__(.*?)__/g, "<strong>$1</strong>")
|
|
28
|
-
// Italics: *text*
|
|
28
|
+
// Italics: *text* (intentionally avoid _text_ to keep URLs/query keys intact)
|
|
29
29
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
30
|
-
.replace(/_(.*?)_/g, "<em>$1</em>")
|
|
31
30
|
// Newlines to <br>
|
|
32
31
|
.replace(/\n/g, "<br>");
|
|
33
32
|
};
|
|
34
33
|
|
|
34
|
+
const URL_LIKE_PATTERN = /^(https?:\/\/|mailto:|tel:)\S+$/i;
|
|
35
|
+
|
|
35
36
|
/**
|
|
36
37
|
* Recursively process object values to convert markdown to HTML
|
|
37
38
|
*/
|
|
@@ -39,6 +40,9 @@ const processMarkdownData = (data: any): any => {
|
|
|
39
40
|
if (!data) return data;
|
|
40
41
|
|
|
41
42
|
if (typeof data === "string") {
|
|
43
|
+
if (URL_LIKE_PATTERN.test(data.trim())) {
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
42
46
|
return markdownToHtml(data);
|
|
43
47
|
}
|
|
44
48
|
|