@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.
@@ -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* or _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)) {
@@ -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 errorStatus = status || "500";
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 (process.env.NODE_ENV === "development" ||
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(parseInt(errorStatus, 10)).json(response);
210
+ return res.status(statusCode).json(response);
166
211
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heliyos/heliyos-api-core",
3
- "version": "1.0.67",
3
+ "version": "1.0.69",
4
4
  "description": "Heliyos's core api functions and middlewares. Its a private package hosted on npm.",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -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* or _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