@arkyn/server 3.0.8 → 3.0.10
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/http/api/_logRequest.d.ts.map +1 -1
- package/dist/http/badResponses/_badResponse.d.ts +7 -0
- package/dist/http/badResponses/_badResponse.d.ts.map +1 -1
- package/dist/http/badResponses/unprocessableEntity.d.ts.map +1 -1
- package/dist/index.js +239 -165
- package/dist/index.js.map +1 -1
- package/dist/modules/http/api/_logRequest.js +34 -31
- package/dist/modules/http/api/_logRequest.js.map +1 -1
- package/dist/modules/http/badResponses/_badResponse.js +3 -1
- package/dist/modules/http/badResponses/_badResponse.js.map +1 -1
- package/dist/modules/http/badResponses/unprocessableEntity.js +15 -5
- package/dist/modules/http/badResponses/unprocessableEntity.js.map +1 -1
- package/dist/modules/services/apiService.js +35 -23
- package/dist/modules/services/apiService.js.map +1 -1
- package/dist/modules/services/logService.js +29 -11
- package/dist/modules/services/logService.js.map +1 -1
- package/dist/modules/utilities/decodeRequestBody.js +13 -8
- package/dist/modules/utilities/decodeRequestBody.js.map +1 -1
- package/dist/modules/utilities/sensitiveDataKeys.js +31 -0
- package/dist/modules/utilities/sensitiveDataKeys.js.map +1 -0
- package/dist/modules/validations/validateEmail.js +21 -16
- package/dist/modules/validations/validateEmail.js.map +1 -1
- package/dist/services/apiService.d.ts +12 -0
- package/dist/services/apiService.d.ts.map +1 -1
- package/dist/services/logService.d.ts +15 -2
- package/dist/services/logService.d.ts.map +1 -1
- package/dist/utilities/decodeRequestBody.d.ts +7 -2
- package/dist/utilities/decodeRequestBody.d.ts.map +1 -1
- package/dist/utilities/sensitiveDataKeys.d.ts +22 -0
- package/dist/utilities/sensitiveDataKeys.d.ts.map +1 -0
- package/dist/validations/validateEmail.d.ts +10 -1
- package/dist/validations/validateEmail.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
import { flushDebugLogs as e } from "../../utilities/flushDebugLogs.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { SENSITIVE_DATA_KEYS as t } from "../../utilities/sensitiveDataKeys.js";
|
|
3
|
+
import { LogService as n } from "../../services/logService.js";
|
|
4
|
+
import { formatJsonObject as r, parseSensitiveData as i } from "@arkyn/shared";
|
|
4
5
|
//#region src/http/api/_logRequest.ts
|
|
5
|
-
async function
|
|
6
|
-
let
|
|
7
|
-
if (!
|
|
8
|
-
let { userToken:
|
|
6
|
+
async function a(a) {
|
|
7
|
+
let o = n.getConfig();
|
|
8
|
+
if (!o) return;
|
|
9
|
+
let { userToken: s, apiUrl: c, trafficSourceId: l } = o;
|
|
10
|
+
if (!c) return;
|
|
11
|
+
let { elapsedTime: u, method: d, queryParams: f, requestBody: p, requestHeaders: m, responseBody: h, responseHeaders: g, status: _, rawUrl: v } = a;
|
|
9
12
|
if (process.env.NODE_ENV !== "development") try {
|
|
10
|
-
let
|
|
11
|
-
|
|
12
|
-
let
|
|
13
|
-
domainUrl: `${
|
|
14
|
-
pathnameUrl:
|
|
15
|
-
trafficSourceId:
|
|
16
|
-
status:
|
|
17
|
-
protocol:
|
|
18
|
-
method:
|
|
13
|
+
let n = new URL(v), a = "https";
|
|
14
|
+
n.protocol === "http:" && (a = "http");
|
|
15
|
+
let o = JSON.stringify({
|
|
16
|
+
domainUrl: `${n.protocol}//${n.host}`,
|
|
17
|
+
pathnameUrl: n.pathname,
|
|
18
|
+
trafficSourceId: l,
|
|
19
|
+
status: _,
|
|
20
|
+
protocol: a,
|
|
21
|
+
method: d.toLowerCase(),
|
|
19
22
|
trafficUserId: null,
|
|
20
|
-
elapsedTime:
|
|
21
|
-
requestHeaders: JSON.stringify(
|
|
22
|
-
requestBody: JSON.stringify(
|
|
23
|
-
queryParams: JSON.stringify(
|
|
24
|
-
responseHeaders: JSON.stringify(
|
|
25
|
-
responseBody: JSON.stringify(
|
|
26
|
-
}),
|
|
23
|
+
elapsedTime: u,
|
|
24
|
+
requestHeaders: i(JSON.stringify(m), [...t]),
|
|
25
|
+
requestBody: i(JSON.stringify(p), [...t]),
|
|
26
|
+
queryParams: JSON.stringify(f),
|
|
27
|
+
responseHeaders: i(JSON.stringify(g), [...t]),
|
|
28
|
+
responseBody: i(JSON.stringify(h), [...t])
|
|
29
|
+
}), y = {
|
|
27
30
|
"Content-Type": "application/json",
|
|
28
|
-
Authorization: `Bearer ${
|
|
29
|
-
},
|
|
31
|
+
Authorization: `Bearer ${s}`
|
|
32
|
+
}, b = await fetch(c, {
|
|
30
33
|
method: "POST",
|
|
31
|
-
body:
|
|
32
|
-
headers:
|
|
34
|
+
body: o,
|
|
35
|
+
headers: y
|
|
33
36
|
});
|
|
34
|
-
if (!
|
|
35
|
-
let t = await
|
|
37
|
+
if (!b.ok) {
|
|
38
|
+
let t = await b.text(), n = b.status, i = b.statusText, a = await b.json().catch(() => null);
|
|
36
39
|
e({
|
|
37
40
|
name: "LogError",
|
|
38
41
|
scheme: "red",
|
|
39
42
|
debugs: [
|
|
40
43
|
"Failed to log request.",
|
|
41
|
-
`Status: ${
|
|
44
|
+
`Status: ${n} ${i}.`,
|
|
42
45
|
`Status text: ${t}.`,
|
|
43
|
-
`JSON Response: ${a ?
|
|
46
|
+
`JSON Response: ${a ? r(a, 0) : "No JSON response"}`
|
|
44
47
|
]
|
|
45
48
|
});
|
|
46
49
|
}
|
|
@@ -53,6 +56,6 @@ async function r(r) {
|
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
//#endregion
|
|
56
|
-
export {
|
|
59
|
+
export { a as logRequest };
|
|
57
60
|
|
|
58
61
|
//# sourceMappingURL=_logRequest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_logRequest.js","names":[],"sources":["../../../../src/http/api/_logRequest.ts"],"sourcesContent":["import { formatJsonObject } from \"@arkyn/shared\";\nimport { flushDebugLogs } from \"../..\";\nimport { LogService } from \"../../services/logService\";\n\ntype ConfigProps = {\n\trawUrl: string;\n\tstatus: number;\n\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n\ttoken: string | null;\n\telapsedTime: number;\n\trequestHeaders: Record<string, string>;\n\trequestBody: Record<string, string>;\n\tqueryParams: Record<string, string>;\n\tresponseHeaders: Record<string, string>;\n\tresponseBody: Record<string, string>;\n};\n\n/**\n * Sends a request to the inbox flow API with the provided configuration.\n *\n * - This function retrieves the inbox flow configuration using `LogService.getConfig()`.\n * - If the configuration is not available, the function will return early without performing any action.\n * - In a development environment (`NODE_ENV === \"development\"`), the function will also return early.\n * - The request is sent as a POST request to the inbox API URL with the provided configuration details.\n * - If an error occurs during the request, it will be logged using the `httpDebug` service.\n *\n * @param {ConfigProps} config - The configuration object for the request.\n * @param {string} config.rawUrl - The raw URL of the request.\n * @param {number} config.status - The HTTP status code associated with the request.\n * @param {\"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\"} config.method - The HTTP method used for the request. Can be \"POST\", \"GET\", \"PUT\", \"DELETE\", or \"PATCH\".\n * @param {string | null} config.token - The authentication token for the request.\n * @param {number} config.elapsedTime - The elapsed time for the request in milliseconds.\n * @param {Record<string, string>} config.requestHeaders - The headers sent with the request.\n * @param {Record<string, string>} config.requestBody - The body of the request, if applicable.\n * @param {Record<string, string>} config.queryParams - The query parameters for the request.\n * @param {Record<string, string>} config.responseHeaders - The headers received in the response.\n * @param {Record<string, string>} config.responseBody - The body of the response received.\n *\n * @remarks\n *\n * @returns {Promise<void>} A promise that resolves when the request is complete.\n *\n * @example\n * ```typescript\n * const config = {\n * rawUrl: \"https://example.com/api/data\",\n * status: 200,\n * method: \"GET\",\n * token: \"auth-token-123\",\n * elapsedTime: 150,\n * requestHeaders: { \"Accept\": \"application/json\", \"Authorization\": \"Bearer token123\" },\n * requestBody: {},\n * queryParams: { \"page\": \"1\", \"limit\": \"10\" },\n * responseHeaders: { \"Content-Type\": \"application/json\" },\n * responseBody: { \"data\": \"example response\" }\n * };\n *\n * await logRequest(config);\n * ```\n */\n\nasync function logRequest(config: ConfigProps): Promise<void> {\n\tconst arkynService = LogService.getConfig();\n\tif (!arkynService) return;\n\n\tconst { userToken, apiUrl, trafficSourceId } = arkynService;\n\n\tconst {\n\t\telapsedTime,\n\t\tmethod,\n\t\tqueryParams,\n\t\trequestBody,\n\t\trequestHeaders,\n\t\tresponseBody,\n\t\tresponseHeaders,\n\t\tstatus,\n\t\trawUrl,\n\t} = config;\n\n\tif (process.env.NODE_ENV === \"development\") return;\n\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\n\t\tlet protocol: \"http\" | \"https\" = \"https\";\n\t\tif (url.protocol === \"http:\") protocol = \"http\";\n\n\t\tconst body = JSON.stringify({\n\t\t\tdomainUrl: `${url.protocol}//${url.host}`,\n\t\t\tpathnameUrl: url.pathname,\n\t\t\ttrafficSourceId: trafficSourceId,\n\t\t\tstatus,\n\t\t\tprotocol,\n\t\t\tmethod: method.toLowerCase(),\n\t\t\ttrafficUserId: null,\n\t\t\telapsedTime,\n\t\t\trequestHeaders: JSON.stringify(requestHeaders),\n\t\t\trequestBody: JSON.stringify(requestBody),\n\t\t\tqueryParams: JSON.stringify(queryParams),\n\t\t\tresponseHeaders: JSON.stringify(responseHeaders),\n\t\t\tresponseBody: JSON.stringify(responseBody),\n\t\t});\n\n\t\tconst headers = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAuthorization: `Bearer ${userToken}`,\n\t\t};\n\n\t\tconst fetchResponse = await fetch(apiUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\theaders,\n\t\t});\n\n\t\tif (!fetchResponse.ok) {\n\t\t\tconst errorText = await fetchResponse.text();\n\t\t\tconst errorStatus = fetchResponse.status;\n\t\t\tconst errorStatusText = fetchResponse.statusText;\n\t\t\tconst jsonResponse = await fetchResponse.json().catch(() => null);\n\n\t\t\tflushDebugLogs({\n\t\t\t\tname: \"LogError\",\n\t\t\t\tscheme: \"red\",\n\t\t\t\tdebugs: [\n\t\t\t\t\t`Failed to log request.`,\n\t\t\t\t\t`Status: ${errorStatus} ${errorStatusText}.`,\n\t\t\t\t\t`Status text: ${errorText}.`,\n\t\t\t\t\t`JSON Response: ${jsonResponse ? formatJsonObject(jsonResponse, 0) : \"No JSON response\"}`,\n\t\t\t\t],\n\t\t\t});\n\t\t}\n\t} catch (err) {\n\t\tflushDebugLogs({\n\t\t\tdebugs: [`Error sending request: ${err}`],\n\t\t\tname: \"LogError\",\n\t\t\tscheme: \"red\",\n\t\t});\n\t}\n}\n\nexport { logRequest };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_logRequest.js","names":[],"sources":["../../../../src/http/api/_logRequest.ts"],"sourcesContent":["import { formatJsonObject, parseSensitiveData } from \"@arkyn/shared\";\nimport { flushDebugLogs } from \"../..\";\nimport { LogService } from \"../../services/logService\";\nimport { SENSITIVE_DATA_KEYS } from \"../../utilities/sensitiveDataKeys\";\n\ntype ConfigProps = {\n\trawUrl: string;\n\tstatus: number;\n\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n\ttoken: string | null;\n\telapsedTime: number;\n\trequestHeaders: Record<string, string>;\n\trequestBody: Record<string, string>;\n\tqueryParams: Record<string, string>;\n\tresponseHeaders: Record<string, string>;\n\tresponseBody: Record<string, string>;\n};\n\n/**\n * Sends a request to the inbox flow API with the provided configuration.\n *\n * - This function retrieves the inbox flow configuration using `LogService.getConfig()`.\n * - If the configuration is not available, the function will return early without performing any action.\n * - In a development environment (`NODE_ENV === \"development\"`), the function will also return early.\n * - The request is sent as a POST request to the inbox API URL with the provided configuration details.\n * - If an error occurs during the request, it will be logged using the `httpDebug` service.\n *\n * @param {ConfigProps} config - The configuration object for the request.\n * @param {string} config.rawUrl - The raw URL of the request.\n * @param {number} config.status - The HTTP status code associated with the request.\n * @param {\"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\"} config.method - The HTTP method used for the request. Can be \"POST\", \"GET\", \"PUT\", \"DELETE\", or \"PATCH\".\n * @param {string | null} config.token - The authentication token for the request.\n * @param {number} config.elapsedTime - The elapsed time for the request in milliseconds.\n * @param {Record<string, string>} config.requestHeaders - The headers sent with the request.\n * @param {Record<string, string>} config.requestBody - The body of the request, if applicable.\n * @param {Record<string, string>} config.queryParams - The query parameters for the request.\n * @param {Record<string, string>} config.responseHeaders - The headers received in the response.\n * @param {Record<string, string>} config.responseBody - The body of the response received.\n *\n * @remarks\n *\n * @returns {Promise<void>} A promise that resolves when the request is complete.\n *\n * @example\n * ```typescript\n * const config = {\n * rawUrl: \"https://example.com/api/data\",\n * status: 200,\n * method: \"GET\",\n * token: \"auth-token-123\",\n * elapsedTime: 150,\n * requestHeaders: { \"Accept\": \"application/json\", \"Authorization\": \"Bearer token123\" },\n * requestBody: {},\n * queryParams: { \"page\": \"1\", \"limit\": \"10\" },\n * responseHeaders: { \"Content-Type\": \"application/json\" },\n * responseBody: { \"data\": \"example response\" }\n * };\n *\n * await logRequest(config);\n * ```\n */\n\nasync function logRequest(config: ConfigProps): Promise<void> {\n\tconst arkynService = LogService.getConfig();\n\tif (!arkynService) return;\n\n\tconst { userToken, apiUrl, trafficSourceId } = arkynService;\n\n\t// No endpoint was configured (missing, invalid, or rejected as insecure by\n\t// `LogService.setConfig`) — never fall back to a hardcoded/default destination.\n\tif (!apiUrl) return;\n\n\tconst {\n\t\telapsedTime,\n\t\tmethod,\n\t\tqueryParams,\n\t\trequestBody,\n\t\trequestHeaders,\n\t\tresponseBody,\n\t\tresponseHeaders,\n\t\tstatus,\n\t\trawUrl,\n\t} = config;\n\n\tif (process.env.NODE_ENV === \"development\") return;\n\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\n\t\tlet protocol: \"http\" | \"https\" = \"https\";\n\t\tif (url.protocol === \"http:\") protocol = \"http\";\n\n\t\tconst body = JSON.stringify({\n\t\t\tdomainUrl: `${url.protocol}//${url.host}`,\n\t\t\tpathnameUrl: url.pathname,\n\t\t\ttrafficSourceId: trafficSourceId,\n\t\t\tstatus,\n\t\t\tprotocol,\n\t\t\tmethod: method.toLowerCase(),\n\t\t\ttrafficUserId: null,\n\t\t\telapsedTime,\n\t\t\t// Sensitive fields (Authorization/Cookie headers, password/token/secret\n\t\t\t// body fields, etc.) are masked before this payload ever leaves the\n\t\t\t// process — see `SENSITIVE_DATA_KEYS`.\n\t\t\trequestHeaders: parseSensitiveData(JSON.stringify(requestHeaders), [\n\t\t\t\t...SENSITIVE_DATA_KEYS,\n\t\t\t]),\n\t\t\trequestBody: parseSensitiveData(JSON.stringify(requestBody), [\n\t\t\t\t...SENSITIVE_DATA_KEYS,\n\t\t\t]),\n\t\t\tqueryParams: JSON.stringify(queryParams),\n\t\t\tresponseHeaders: parseSensitiveData(JSON.stringify(responseHeaders), [\n\t\t\t\t...SENSITIVE_DATA_KEYS,\n\t\t\t]),\n\t\t\tresponseBody: parseSensitiveData(JSON.stringify(responseBody), [\n\t\t\t\t...SENSITIVE_DATA_KEYS,\n\t\t\t]),\n\t\t});\n\n\t\tconst headers = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAuthorization: `Bearer ${userToken}`,\n\t\t};\n\n\t\tconst fetchResponse = await fetch(apiUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\theaders,\n\t\t});\n\n\t\tif (!fetchResponse.ok) {\n\t\t\tconst errorText = await fetchResponse.text();\n\t\t\tconst errorStatus = fetchResponse.status;\n\t\t\tconst errorStatusText = fetchResponse.statusText;\n\t\t\tconst jsonResponse = await fetchResponse.json().catch(() => null);\n\n\t\t\tflushDebugLogs({\n\t\t\t\tname: \"LogError\",\n\t\t\t\tscheme: \"red\",\n\t\t\t\tdebugs: [\n\t\t\t\t\t`Failed to log request.`,\n\t\t\t\t\t`Status: ${errorStatus} ${errorStatusText}.`,\n\t\t\t\t\t`Status text: ${errorText}.`,\n\t\t\t\t\t`JSON Response: ${jsonResponse ? formatJsonObject(jsonResponse, 0) : \"No JSON response\"}`,\n\t\t\t\t],\n\t\t\t});\n\t\t}\n\t} catch (err) {\n\t\tflushDebugLogs({\n\t\t\tdebugs: [`Error sending request: ${err}`],\n\t\t\tname: \"LogError\",\n\t\t\tscheme: \"red\",\n\t\t});\n\t}\n}\n\nexport { logRequest };\n"],"mappings":";;;;;AA8DA,eAAe,EAAW,GAAoC;CAC7D,IAAM,IAAe,EAAW,UAAU;CAC1C,IAAI,CAAC,GAAc;CAEnB,IAAM,EAAE,cAAW,WAAQ,uBAAoB;CAI/C,IAAI,CAAC,GAAQ;CAEb,IAAM,EACL,gBACA,WACA,gBACA,gBACA,mBACA,iBACA,oBACA,WACA,cACG;CAEJ,YAAA,IAAA,aAA6B,eAE7B,IAAI;EACH,IAAM,IAAM,IAAI,IAAI,CAAM,GAEtB,IAA6B;EACjC,AAAI,EAAI,aAAa,YAAS,IAAW;EAEzC,IAAM,IAAO,KAAK,UAAU;GAC3B,WAAW,GAAG,EAAI,SAAS,IAAI,EAAI;GACnC,aAAa,EAAI;GACA;GACjB;GACA;GACA,QAAQ,EAAO,YAAY;GAC3B,eAAe;GACf;GAIA,gBAAgB,EAAmB,KAAK,UAAU,CAAc,GAAG,CAClE,GAAG,CACJ,CAAC;GACD,aAAa,EAAmB,KAAK,UAAU,CAAW,GAAG,CAC5D,GAAG,CACJ,CAAC;GACD,aAAa,KAAK,UAAU,CAAW;GACvC,iBAAiB,EAAmB,KAAK,UAAU,CAAe,GAAG,CACpE,GAAG,CACJ,CAAC;GACD,cAAc,EAAmB,KAAK,UAAU,CAAY,GAAG,CAC9D,GAAG,CACJ,CAAC;EACF,CAAC,GAEK,IAAU;GACf,gBAAgB;GAChB,eAAe,UAAU;EAC1B,GAEM,IAAgB,MAAM,MAAM,GAAQ;GACzC,QAAQ;GACR;GACA;EACD,CAAC;EAED,IAAI,CAAC,EAAc,IAAI;GACtB,IAAM,IAAY,MAAM,EAAc,KAAK,GACrC,IAAc,EAAc,QAC5B,IAAkB,EAAc,YAChC,IAAe,MAAM,EAAc,KAAK,CAAC,CAAC,YAAY,IAAI;GAEhE,EAAe;IACd,MAAM;IACN,QAAQ;IACR,QAAQ;KACP;KACA,WAAW,EAAY,GAAG,EAAgB;KAC1C,gBAAgB,EAAU;KAC1B,kBAAkB,IAAe,EAAiB,GAAc,CAAC,IAAI;IACtE;GACD,CAAC;EACF;CACD,SAAS,GAAK;EACb,EAAe;GACd,QAAQ,CAAC,0BAA0B,GAAK;GACxC,MAAM;GACN,QAAQ;EACT,CAAC;CACF;AACD"}
|
|
@@ -8,6 +8,7 @@ var r = class {
|
|
|
8
8
|
_status = 500;
|
|
9
9
|
_statusText = "Unknown error";
|
|
10
10
|
_debugColor = "red";
|
|
11
|
+
exposeCauseInProduction = !1;
|
|
11
12
|
get cause() {
|
|
12
13
|
return this._cause;
|
|
13
14
|
}
|
|
@@ -52,10 +53,11 @@ var r = class {
|
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
makeBody() {
|
|
56
|
+
let e = process.env.NODE_ENV === "production" && !this.exposeCauseInProduction;
|
|
55
57
|
return {
|
|
56
58
|
name: this._name,
|
|
57
59
|
message: this._statusText,
|
|
58
|
-
cause: this._cause
|
|
60
|
+
cause: e ? void 0 : this._cause
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_badResponse.js","names":[],"sources":["../../../../src/http/badResponses/_badResponse.ts"],"sourcesContent":["import { formatJsonString } from \"@arkyn/shared\";\n\nimport { DebugService } from \"../../services/debugService\";\nimport { flushDebugLogs } from \"../../utilities/flushDebugLogs\";\n\nclass BadResponse {\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tprivate _cause?: any;\n\tprivate _name: string = \"BadResponse\";\n\tprivate _status: number = 500;\n\tprivate _statusText: string = \"Unknown error\";\n\tprivate _debugColor: \"green\" | \"yellow\" | \"cyan\" | \"red\" = \"red\";\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tget cause(): any {\n\t\treturn this._cause;\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tset cause(value: any) {\n\t\tthis._cause = value;\n\t}\n\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tset name(value: string) {\n\t\tthis._name = value;\n\t}\n\n\tget status(): number {\n\t\treturn this._status;\n\t}\n\n\tset status(value: number) {\n\t\tthis._status = value;\n\t}\n\n\tget statusText(): string {\n\t\treturn this._statusText;\n\t}\n\n\tset statusText(value: string) {\n\t\tthis._statusText = value;\n\t}\n\n\tget debugColor(): \"green\" | \"yellow\" | \"cyan\" | \"red\" {\n\t\treturn this._debugColor;\n\t}\n\n\tset debugColor(value: \"green\" | \"yellow\" | \"cyan\" | \"red\") {\n\t\tif (![\"green\", \"yellow\", \"cyan\", \"red\"].includes(value)) return;\n\t\tthis._debugColor = value;\n\t}\n\n\tonDebug() {\n\t\tconst debugs: string[] = [];\n\t\tconst { callerInfo, functionName } = DebugService.getCaller();\n\n\t\tdebugs.push(`Caller Function: ${functionName}`);\n\t\tdebugs.push(`Caller Location: ${callerInfo}`);\n\n\t\tif (this._statusText) debugs.push(`Message: ${this._statusText}`);\n\t\tif (this._cause) {\n\t\t\tdebugs.push(`Cause: ${formatJsonString(JSON.stringify(this._cause))}`);\n\t\t}\n\n\t\tflushDebugLogs({ scheme: \"red\", name: this._name, debugs });\n\t}\n\n\tmakeBody() {\n\t\treturn {\n\t\t\tname: this._name,\n\t\t\tmessage: this._statusText,\n\t\t\tcause: this._cause,\n\t\t};\n\t}\n}\n\nexport { BadResponse };\n"],"mappings":";;;;AAKA,IAAM,IAAN,MAAkB;CAEjB;CACA,QAAwB;CACxB,UAA0B;CAC1B,cAA8B;CAC9B,cAA2D;
|
|
1
|
+
{"version":3,"file":"_badResponse.js","names":[],"sources":["../../../../src/http/badResponses/_badResponse.ts"],"sourcesContent":["import { formatJsonString } from \"@arkyn/shared\";\n\nimport { DebugService } from \"../../services/debugService\";\nimport { flushDebugLogs } from \"../../utilities/flushDebugLogs\";\n\nclass BadResponse {\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tprivate _cause?: any;\n\tprivate _name: string = \"BadResponse\";\n\tprivate _status: number = 500;\n\tprivate _statusText: string = \"Unknown error\";\n\tprivate _debugColor: \"green\" | \"yellow\" | \"cyan\" | \"red\" = \"red\";\n\t/**\n\t * When `false` (the default), `makeBody()` omits `cause` in production so internal\n\t * details (stack traces, SQL, infra info) never reach the client. Subclasses whose\n\t * `cause` is safe, client-facing data (e.g. `UnprocessableEntity`'s form field errors)\n\t * set this to `true`.\n\t */\n\tprotected exposeCauseInProduction = false;\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tget cause(): any {\n\t\treturn this._cause;\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tset cause(value: any) {\n\t\tthis._cause = value;\n\t}\n\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tset name(value: string) {\n\t\tthis._name = value;\n\t}\n\n\tget status(): number {\n\t\treturn this._status;\n\t}\n\n\tset status(value: number) {\n\t\tthis._status = value;\n\t}\n\n\tget statusText(): string {\n\t\treturn this._statusText;\n\t}\n\n\tset statusText(value: string) {\n\t\tthis._statusText = value;\n\t}\n\n\tget debugColor(): \"green\" | \"yellow\" | \"cyan\" | \"red\" {\n\t\treturn this._debugColor;\n\t}\n\n\tset debugColor(value: \"green\" | \"yellow\" | \"cyan\" | \"red\") {\n\t\tif (![\"green\", \"yellow\", \"cyan\", \"red\"].includes(value)) return;\n\t\tthis._debugColor = value;\n\t}\n\n\tonDebug() {\n\t\tconst debugs: string[] = [];\n\t\tconst { callerInfo, functionName } = DebugService.getCaller();\n\n\t\tdebugs.push(`Caller Function: ${functionName}`);\n\t\tdebugs.push(`Caller Location: ${callerInfo}`);\n\n\t\tif (this._statusText) debugs.push(`Message: ${this._statusText}`);\n\t\tif (this._cause) {\n\t\t\tdebugs.push(`Cause: ${formatJsonString(JSON.stringify(this._cause))}`);\n\t\t}\n\n\t\tflushDebugLogs({ scheme: \"red\", name: this._name, debugs });\n\t}\n\n\tmakeBody() {\n\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\tconst hideCause = isProduction && !this.exposeCauseInProduction;\n\n\t\treturn {\n\t\t\tname: this._name,\n\t\t\tmessage: this._statusText,\n\t\t\tcause: hideCause ? undefined : this._cause,\n\t\t};\n\t}\n}\n\nexport { BadResponse };\n"],"mappings":";;;;AAKA,IAAM,IAAN,MAAkB;CAEjB;CACA,QAAwB;CACxB,UAA0B;CAC1B,cAA8B;CAC9B,cAA2D;CAO3D,0BAAoC;CAGpC,IAAI,QAAa;EAChB,OAAO,KAAK;CACb;CAGA,IAAI,MAAM,GAAY;EACrB,KAAK,SAAS;CACf;CAEA,IAAI,OAAe;EAClB,OAAO,KAAK;CACb;CAEA,IAAI,KAAK,GAAe;EACvB,KAAK,QAAQ;CACd;CAEA,IAAI,SAAiB;EACpB,OAAO,KAAK;CACb;CAEA,IAAI,OAAO,GAAe;EACzB,KAAK,UAAU;CAChB;CAEA,IAAI,aAAqB;EACxB,OAAO,KAAK;CACb;CAEA,IAAI,WAAW,GAAe;EAC7B,KAAK,cAAc;CACpB;CAEA,IAAI,aAAkD;EACrD,OAAO,KAAK;CACb;CAEA,IAAI,WAAW,GAA4C;EACrD;GAAC;GAAS;GAAU;GAAQ;EAAK,CAAC,CAAC,SAAS,CAAK,MACtD,KAAK,cAAc;CACpB;CAEA,UAAU;EACT,IAAM,IAAmB,CAAC,GACpB,EAAE,eAAY,oBAAiB,EAAa,UAAU;EAU5D,AARA,EAAO,KAAK,oBAAoB,GAAc,GAC9C,EAAO,KAAK,oBAAoB,GAAY,GAExC,KAAK,eAAa,EAAO,KAAK,YAAY,KAAK,aAAa,GAC5D,KAAK,UACR,EAAO,KAAK,UAAU,EAAiB,KAAK,UAAU,KAAK,MAAM,CAAC,GAAG,GAGtE,EAAe;GAAE,QAAQ;GAAO,MAAM,KAAK;GAAO;EAAO,CAAC;CAC3D;CAEA,WAAW;EAEV,IAAM,IAAA,QAAA,IAAA,aADwC,gBACZ,CAAC,KAAK;EAExC,OAAO;GACN,MAAM,KAAK;GACX,SAAS,KAAK;GACd,OAAO,IAAY,KAAA,IAAY,KAAK;EACrC;CACD;AACD"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { BadResponse as e } from "./_badResponse.js";
|
|
2
|
+
import { SENSITIVE_DATA_KEYS as t } from "../../utilities/sensitiveDataKeys.js";
|
|
3
|
+
import { parseSensitiveData as n } from "@arkyn/shared";
|
|
2
4
|
//#region src/http/badResponses/unprocessableEntity.ts
|
|
3
|
-
|
|
5
|
+
function r(e) {
|
|
6
|
+
if (e === void 0) return e;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(n(JSON.stringify(e), [...t]));
|
|
9
|
+
} catch {
|
|
10
|
+
return e;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
var i = class extends e {
|
|
4
14
|
constructor(e) {
|
|
5
|
-
super(), this.name = "UnprocessableEntity", this.status = 422, this.statusText = e.message || "Unprocessable entity", this.debugColor = "yellow", this.cause = {
|
|
6
|
-
data: e.data,
|
|
15
|
+
super(), this.name = "UnprocessableEntity", this.status = 422, this.statusText = e.message || "Unprocessable entity", this.debugColor = "yellow", this.exposeCauseInProduction = !0, this.cause = {
|
|
16
|
+
data: r(e.data),
|
|
7
17
|
fieldErrors: e.fieldErrors,
|
|
8
|
-
fields: e.fields
|
|
18
|
+
fields: r(e.fields)
|
|
9
19
|
}, this.onDebug();
|
|
10
20
|
}
|
|
11
21
|
toResponse() {
|
|
@@ -25,6 +35,6 @@ var t = class extends e {
|
|
|
25
35
|
}
|
|
26
36
|
};
|
|
27
37
|
//#endregion
|
|
28
|
-
export {
|
|
38
|
+
export { i as UnprocessableEntity };
|
|
29
39
|
|
|
30
40
|
//# sourceMappingURL=unprocessableEntity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unprocessableEntity.js","names":[],"sources":["../../../../src/http/badResponses/unprocessableEntity.ts"],"sourcesContent":["import { BadResponse } from \"./_badResponse\";\n\n/**\n * HTTP 422 Unprocessable Entity, the request is well-formed but contains semantic validation errors.\n * Typically used for form field validation failures.\n *\n * @example\n * ```typescript\n * throw new UnprocessableEntity({\n * message: \"Validation failed\",\n * fieldErrors: { email: \"Invalid email format\", age: \"Must be 18 or older\" },\n * fields: { email: \"not-an-email\", age: \"15\" },\n * });\n * ```\n */\nclass UnprocessableEntity extends BadResponse {\n\t/**\n\t * @param props.message - Human-readable description of the error.\n\t * @param props.fieldErrors - Per-field validation messages keyed by field name.\n\t * @param props.fields - Original submitted field values (useful for repopulating forms).\n\t * @param props.data - Any extra data to include in the response body.\n\t */\n\tconstructor(props: {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\tdata?: any;\n\t\tfieldErrors?: Record<string, string>;\n\t\tfields?: Record<string, string>;\n\t\tmessage?: string;\n\t}) {\n\t\tsuper();\n\n\t\tthis.name = \"UnprocessableEntity\";\n\t\tthis.status = 422;\n\t\tthis.statusText = props.message || \"Unprocessable entity\";\n\t\tthis.debugColor = \"yellow\";\n\t\tthis.cause = {\n\t\t\tdata: props.data,\n\t\t\tfieldErrors: props.fieldErrors,\n\t\t\tfields: props.fields,\n\t\t};\n\n\t\tthis.onDebug();\n\t}\n\n\t/** Converts to a `Response` with `Content-Type: application/json` header. */\n\ttoResponse(): Response {\n\t\tconst responseInit: ResponseInit = {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tstatus: this.status,\n\t\t\tstatusText: this.statusText,\n\t\t};\n\n\t\treturn new Response(JSON.stringify(this.makeBody()), responseInit);\n\t}\n\n\t/** Converts to a `Response` using `Response.json()`. Alternative to `toResponse()`. */\n\ttoJson(): Response {\n\t\tconst responseInit: ResponseInit = {\n\t\t\tstatus: this.status,\n\t\t\tstatusText: this.statusText,\n\t\t};\n\n\t\treturn Response.json(this.makeBody(), responseInit);\n\t}\n}\n\nexport { UnprocessableEntity };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"unprocessableEntity.js","names":[],"sources":["../../../../src/http/badResponses/unprocessableEntity.ts"],"sourcesContent":["import { parseSensitiveData } from \"@arkyn/shared\";\nimport { SENSITIVE_DATA_KEYS } from \"../../utilities/sensitiveDataKeys\";\nimport { BadResponse } from \"./_badResponse\";\n\n/**\n * Masks sensitive values (passwords, tokens, etc. — see `SENSITIVE_DATA_KEYS`) inside a\n * form-submission payload before it is echoed back to the client. `fields`/`data` on\n * `UnprocessableEntity` exist to repopulate a form, so submitted secrets must never be\n * returned in cleartext.\n */\nfunction redactSensitiveValues<T>(value: T): T {\n\tif (value === undefined) return value;\n\n\ttry {\n\t\treturn JSON.parse(\n\t\t\tparseSensitiveData(JSON.stringify(value), [...SENSITIVE_DATA_KEYS]),\n\t\t);\n\t} catch {\n\t\treturn value;\n\t}\n}\n\n/**\n * HTTP 422 Unprocessable Entity, the request is well-formed but contains semantic validation errors.\n * Typically used for form field validation failures.\n *\n * @example\n * ```typescript\n * throw new UnprocessableEntity({\n * message: \"Validation failed\",\n * fieldErrors: { email: \"Invalid email format\", age: \"Must be 18 or older\" },\n * fields: { email: \"not-an-email\", age: \"15\" },\n * });\n * ```\n */\nclass UnprocessableEntity extends BadResponse {\n\t/**\n\t * @param props.message - Human-readable description of the error.\n\t * @param props.fieldErrors - Per-field validation messages keyed by field name.\n\t * @param props.fields - Original submitted field values (useful for repopulating forms).\n\t * @param props.data - Any extra data to include in the response body.\n\t */\n\tconstructor(props: {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\tdata?: any;\n\t\tfieldErrors?: Record<string, string>;\n\t\tfields?: Record<string, string>;\n\t\tmessage?: string;\n\t}) {\n\t\tsuper();\n\n\t\tthis.name = \"UnprocessableEntity\";\n\t\tthis.status = 422;\n\t\tthis.statusText = props.message || \"Unprocessable entity\";\n\t\tthis.debugColor = \"yellow\";\n\t\t// `cause` here is structured, redacted form-validation data meant for the\n\t\t// client (to repopulate the form) — unlike other responses' `cause`, it stays\n\t\t// visible in production.\n\t\tthis.exposeCauseInProduction = true;\n\t\tthis.cause = {\n\t\t\tdata: redactSensitiveValues(props.data),\n\t\t\tfieldErrors: props.fieldErrors,\n\t\t\tfields: redactSensitiveValues(props.fields),\n\t\t};\n\n\t\tthis.onDebug();\n\t}\n\n\t/** Converts to a `Response` with `Content-Type: application/json` header. */\n\ttoResponse(): Response {\n\t\tconst responseInit: ResponseInit = {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tstatus: this.status,\n\t\t\tstatusText: this.statusText,\n\t\t};\n\n\t\treturn new Response(JSON.stringify(this.makeBody()), responseInit);\n\t}\n\n\t/** Converts to a `Response` using `Response.json()`. Alternative to `toResponse()`. */\n\ttoJson(): Response {\n\t\tconst responseInit: ResponseInit = {\n\t\t\tstatus: this.status,\n\t\t\tstatusText: this.statusText,\n\t\t};\n\n\t\treturn Response.json(this.makeBody(), responseInit);\n\t}\n}\n\nexport { UnprocessableEntity };\n"],"mappings":";;;;AAUA,SAAS,EAAyB,GAAa;CAC9C,IAAI,MAAU,KAAA,GAAW,OAAO;CAEhC,IAAI;EACH,OAAO,KAAK,MACX,EAAmB,KAAK,UAAU,CAAK,GAAG,CAAC,GAAG,CAAmB,CAAC,CACnE;CACD,QAAQ;EACP,OAAO;CACR;AACD;AAeA,IAAM,IAAN,cAAkC,EAAY;CAO7C,YAAY,GAMT;EAiBF,AAhBA,MAAM,GAEN,KAAK,OAAO,uBACZ,KAAK,SAAS,KACd,KAAK,aAAa,EAAM,WAAW,wBACnC,KAAK,aAAa,UAIlB,KAAK,0BAA0B,IAC/B,KAAK,QAAQ;GACZ,MAAM,EAAsB,EAAM,IAAI;GACtC,aAAa,EAAM;GACnB,QAAQ,EAAsB,EAAM,MAAM;EAC3C,GAEA,KAAK,QAAQ;CACd;CAGA,aAAuB;EACtB,IAAM,IAA6B;GAClC,SAAS,EAAE,gBAAgB,mBAAmB;GAC9C,QAAQ,KAAK;GACb,YAAY,KAAK;EAClB;EAEA,OAAO,IAAI,SAAS,KAAK,UAAU,KAAK,SAAS,CAAC,GAAG,CAAY;CAClE;CAGA,SAAmB;EAClB,IAAM,IAA6B;GAClC,QAAQ,KAAK;GACb,YAAY,KAAK;EAClB;EAEA,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG,CAAY;CACnD;AACD"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { flushDebugLogs as e } from "../utilities/flushDebugLogs.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { SENSITIVE_DATA_KEYS as t } from "../utilities/sensitiveDataKeys.js";
|
|
3
|
+
import { deleteRequest as n } from "../http/api/_deleteRequest.js";
|
|
4
|
+
import { getRequest as r } from "../http/api/_getRequest.js";
|
|
5
|
+
import { patchRequest as i } from "../http/api/_patchRequest.js";
|
|
6
|
+
import { postRequest as a } from "../http/api/_postRequest.js";
|
|
7
|
+
import { putRequest as o } from "../http/api/_putRequest.js";
|
|
8
|
+
import { parseSensitiveData as s } from "@arkyn/shared";
|
|
7
9
|
//#region src/services/apiService.ts
|
|
8
|
-
var
|
|
10
|
+
var c = class c {
|
|
9
11
|
baseUrl;
|
|
10
12
|
baseHeaders;
|
|
11
13
|
baseToken;
|
|
@@ -13,10 +15,20 @@ var o = class {
|
|
|
13
15
|
constructor(e) {
|
|
14
16
|
this.baseUrl = e.baseUrl, this.baseHeaders = e.baseHeaders || void 0, this.baseToken = e.baseToken || void 0, this.enableDebug = e.enableDebug || !1;
|
|
15
17
|
}
|
|
18
|
+
static toPlainHeaders(e) {
|
|
19
|
+
return e instanceof Headers ? Object.fromEntries(e.entries()) : Object.fromEntries(new Headers(e).entries());
|
|
20
|
+
}
|
|
21
|
+
static toRedactedJson(e) {
|
|
22
|
+
return s(JSON.stringify(e), [...t]);
|
|
23
|
+
}
|
|
16
24
|
onDebug(t, n, r) {
|
|
17
25
|
if (this.enableDebug) {
|
|
18
|
-
let i = []
|
|
19
|
-
i.push(`Base URL: ${this.baseUrl}`), i.push(`Endpoint: ${t}`), i.push(`Status/Method: ${n} => ${r.status}`), i.push(`Message: ${r.message}`), r.headers
|
|
26
|
+
let i = [];
|
|
27
|
+
if (i.push(`Base URL: ${this.baseUrl}`), i.push(`Endpoint: ${t}`), i.push(`Status/Method: ${n} => ${r.status}`), i.push(`Message: ${r.message}`), r.headers) {
|
|
28
|
+
let e = c.toPlainHeaders(r.headers);
|
|
29
|
+
i.push(`Headers: ${c.toRedactedJson(e)}`);
|
|
30
|
+
}
|
|
31
|
+
r.body && i.push(`Body: ${c.toRedactedJson(r.body)}`), e({
|
|
20
32
|
debugs: i,
|
|
21
33
|
name: "ApiDebug",
|
|
22
34
|
scheme: "yellow"
|
|
@@ -37,19 +49,19 @@ var o = class {
|
|
|
37
49
|
}), n;
|
|
38
50
|
}
|
|
39
51
|
async get(e, t) {
|
|
40
|
-
let
|
|
52
|
+
let n = this.generateHeaders(t?.headers || {}, t?.token), i = await r({
|
|
41
53
|
url: this.baseUrl + e,
|
|
42
54
|
urlParams: t?.urlParams || {},
|
|
43
|
-
headers:
|
|
55
|
+
headers: n
|
|
44
56
|
});
|
|
45
57
|
return this.onDebug(e, "get", {
|
|
46
|
-
headers:
|
|
58
|
+
headers: n,
|
|
47
59
|
message: i.message,
|
|
48
60
|
status: i.status
|
|
49
61
|
}), i;
|
|
50
62
|
}
|
|
51
63
|
async post(e, t) {
|
|
52
|
-
let n = this.generateHeaders(t?.headers || {}, t?.token), r = t?.body,
|
|
64
|
+
let n = this.generateHeaders(t?.headers || {}, t?.token), r = t?.body, i = await a({
|
|
53
65
|
url: this.baseUrl + e,
|
|
54
66
|
urlParams: t?.urlParams || {},
|
|
55
67
|
headers: n,
|
|
@@ -58,12 +70,12 @@ var o = class {
|
|
|
58
70
|
return this.onDebug(e, "post", {
|
|
59
71
|
headers: n,
|
|
60
72
|
body: r,
|
|
61
|
-
message:
|
|
62
|
-
status:
|
|
63
|
-
}),
|
|
73
|
+
message: i.message,
|
|
74
|
+
status: i.status
|
|
75
|
+
}), i;
|
|
64
76
|
}
|
|
65
77
|
async put(e, t) {
|
|
66
|
-
let n = this.generateHeaders(t?.headers || {}, t?.token), r = t?.body, i = await
|
|
78
|
+
let n = this.generateHeaders(t?.headers || {}, t?.token), r = t?.body, i = await o({
|
|
67
79
|
url: this.baseUrl + e,
|
|
68
80
|
urlParams: t?.urlParams || {},
|
|
69
81
|
headers: n,
|
|
@@ -77,23 +89,23 @@ var o = class {
|
|
|
77
89
|
}), i;
|
|
78
90
|
}
|
|
79
91
|
async patch(e, t) {
|
|
80
|
-
let n = this.generateHeaders(t?.headers || {}, t?.token),
|
|
92
|
+
let n = this.generateHeaders(t?.headers || {}, t?.token), r = t?.body, a = await i({
|
|
81
93
|
url: this.baseUrl + e,
|
|
82
94
|
urlParams: t?.urlParams || {},
|
|
83
95
|
headers: n,
|
|
84
|
-
body:
|
|
96
|
+
body: r
|
|
85
97
|
});
|
|
86
98
|
return this.onDebug(e, "patch", {
|
|
87
99
|
headers: n,
|
|
88
|
-
body:
|
|
100
|
+
body: r,
|
|
89
101
|
message: a.message,
|
|
90
102
|
status: a.status
|
|
91
103
|
}), a;
|
|
92
104
|
}
|
|
93
|
-
async delete(e,
|
|
94
|
-
let r = this.generateHeaders(
|
|
105
|
+
async delete(e, t) {
|
|
106
|
+
let r = this.generateHeaders(t?.headers || {}, t?.token), i = t?.body, a = await n({
|
|
95
107
|
url: this.baseUrl + e,
|
|
96
|
-
urlParams:
|
|
108
|
+
urlParams: t?.urlParams || {},
|
|
97
109
|
headers: r,
|
|
98
110
|
body: i
|
|
99
111
|
});
|
|
@@ -106,6 +118,6 @@ var o = class {
|
|
|
106
118
|
}
|
|
107
119
|
};
|
|
108
120
|
//#endregion
|
|
109
|
-
export {
|
|
121
|
+
export { c as ApiService };
|
|
110
122
|
|
|
111
123
|
//# sourceMappingURL=apiService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiService.js","names":[],"sources":["../../../src/services/apiService.ts"],"sourcesContent":["import { deleteRequest } from \"../http/api/_deleteRequest\";\nimport { getRequest } from \"../http/api/_getRequest\";\nimport { patchRequest } from \"../http/api/_patchRequest\";\nimport { postRequest } from \"../http/api/_postRequest\";\nimport { putRequest } from \"../http/api/_putRequest\";\nimport { flushDebugLogs } from \"../utilities/flushDebugLogs\";\n\ntype ApiServiceConstructorProps = {\n\t/** Base URL prepended to every request path (e.g. `\"https://api.example.com\"`). */\n\tbaseUrl: string;\n\t/** Default headers merged into every request. */\n\tbaseHeaders?: HeadersInit;\n\t/** Default Bearer token; can be overridden per request via `data.token`. */\n\tbaseToken?: string | null;\n\t/** When `true`, logs each request and response to the console in development. */\n\tenableDebug?: boolean;\n};\n\ntype ApiRequestDataWithoutBodyProps = {\n\theaders?: HeadersInit;\n\ttoken?: string;\n\turlParams?: Record<string, string>;\n};\n\ntype ApiRequestDataWithBodyProps = {\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tbody?: any;\n\theaders?: HeadersInit;\n\ttoken?: string;\n\turlParams?: Record<string, string>;\n};\n\ntype DebugConfig = {\n\theaders?: HeadersInit;\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tbody?: any;\n\tstatus: number;\n\tmessage: string;\n};\n\n/**\n * HTTP client for external API calls. Wraps fetch with base URL, default headers, optional auth token,\n * and per-request overrides for all standard HTTP methods.\n *\n * @example\n * ```typescript\n * const api = new ApiService({\n * baseUrl: \"https://api.example.com\",\n * baseToken: session.token,\n * enableDebug: true,\n * });\n *\n * const { data } = await api.get(\"/users/me\");\n * const { data: created } = await api.post(\"/orders\", { body: { productId: 1 } });\n * ```\n */\nclass ApiService {\n\tprivate baseUrl: string;\n\tprivate baseHeaders?: HeadersInit;\n\tprivate baseToken?: string;\n\tprivate enableDebug?: boolean;\n\n\tconstructor(props: ApiServiceConstructorProps) {\n\t\tthis.baseUrl = props.baseUrl;\n\t\tthis.baseHeaders = props.baseHeaders || undefined;\n\t\tthis.baseToken = props.baseToken || undefined;\n\t\tthis.enableDebug = props.enableDebug || false;\n\t}\n\n\tprivate onDebug(endpoint: string, method: string, data: DebugConfig) {\n\t\tif (this.enableDebug) {\n\t\t\tconst debugs: string[] = [];\n\t\t\tconst json = (data: unknown) => JSON.stringify(data, null, 2);\n\n\t\t\tdebugs.push(`Base URL: ${this.baseUrl}`);\n\t\t\tdebugs.push(`Endpoint: ${endpoint}`);\n\t\t\tdebugs.push(`Status/Method: ${method} => ${data.status}`);\n\t\t\tdebugs.push(`Message: ${data.message}`);\n\n\t\t\tif (data.headers) debugs.push(`Headers: ${json(data.headers)}`);\n\t\t\tif (data.body) debugs.push(`Body: ${json(data.body)}`);\n\n\t\t\tflushDebugLogs({ debugs, name: \"ApiDebug\", scheme: \"yellow\" });\n\t\t}\n\t}\n\n\tprivate generateHeaders(\n\t\tinitHeaders: HeadersInit,\n\t\ttoken?: string,\n\t): HeadersInit {\n\t\tlet headers: HeadersInit = {};\n\t\tif (this.baseToken) headers = { Authorization: `Bearer ${this.baseToken}` };\n\t\tif (this.baseHeaders) headers = { ...headers, ...this.baseHeaders };\n\n\t\tif (initHeaders) headers = { ...headers, ...initHeaders };\n\t\tif (token) headers = { ...headers, Authorization: `Bearer ${token}` };\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Sends a get request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the get request to.\n\t * @param data - The request data, including optional headers and token.\n\t * @returns The API response data.\n\t */\n\n\tasync get(endpoint: string, data?: ApiRequestDataWithoutBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\n\t\tconst response = await getRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"get\", {\n\t\t\theaders,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a post request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the post request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync post(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await postRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"post\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a put request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the put request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync put(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await putRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"put\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a patch request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the patch request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync patch(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await patchRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"patch\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a delete request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the delete request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync delete(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await deleteRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"delete\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n}\n\nexport { ApiService };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"apiService.js","names":[],"sources":["../../../src/services/apiService.ts"],"sourcesContent":["import { parseSensitiveData } from \"@arkyn/shared\";\nimport { deleteRequest } from \"../http/api/_deleteRequest\";\nimport { getRequest } from \"../http/api/_getRequest\";\nimport { patchRequest } from \"../http/api/_patchRequest\";\nimport { postRequest } from \"../http/api/_postRequest\";\nimport { putRequest } from \"../http/api/_putRequest\";\nimport { flushDebugLogs } from \"../utilities/flushDebugLogs\";\nimport { SENSITIVE_DATA_KEYS } from \"../utilities/sensitiveDataKeys\";\n\ntype ApiServiceConstructorProps = {\n\t/** Base URL prepended to every request path (e.g. `\"https://api.example.com\"`). */\n\tbaseUrl: string;\n\t/** Default headers merged into every request. */\n\tbaseHeaders?: HeadersInit;\n\t/** Default Bearer token; can be overridden per request via `data.token`. */\n\tbaseToken?: string | null;\n\t/** When `true`, logs each request and response to the console in development. */\n\tenableDebug?: boolean;\n};\n\ntype ApiRequestDataWithoutBodyProps = {\n\theaders?: HeadersInit;\n\ttoken?: string;\n\turlParams?: Record<string, string>;\n};\n\ntype ApiRequestDataWithBodyProps = {\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tbody?: any;\n\theaders?: HeadersInit;\n\ttoken?: string;\n\turlParams?: Record<string, string>;\n};\n\ntype DebugConfig = {\n\theaders?: HeadersInit;\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tbody?: any;\n\tstatus: number;\n\tmessage: string;\n};\n\n/**\n * HTTP client for external API calls. Wraps fetch with base URL, default headers, optional auth token,\n * and per-request overrides for all standard HTTP methods.\n *\n * @example\n * ```typescript\n * const api = new ApiService({\n * baseUrl: \"https://api.example.com\",\n * baseToken: session.token,\n * enableDebug: true,\n * });\n *\n * const { data } = await api.get(\"/users/me\");\n * const { data: created } = await api.post(\"/orders\", { body: { productId: 1 } });\n * ```\n */\nclass ApiService {\n\tprivate baseUrl: string;\n\tprivate baseHeaders?: HeadersInit;\n\tprivate baseToken?: string;\n\tprivate enableDebug?: boolean;\n\n\tconstructor(props: ApiServiceConstructorProps) {\n\t\tthis.baseUrl = props.baseUrl;\n\t\tthis.baseHeaders = props.baseHeaders || undefined;\n\t\tthis.baseToken = props.baseToken || undefined;\n\t\tthis.enableDebug = props.enableDebug || false;\n\t}\n\n\t/**\n\t * Converts a `HeadersInit` value into a plain object so it can be safely\n\t * JSON-serialized and redacted, regardless of whether it was provided as a\n\t * `Headers` instance, a plain object, or an array of tuples.\n\t */\n\tprivate static toPlainHeaders(headers: HeadersInit): Record<string, string> {\n\t\tif (headers instanceof Headers)\n\t\t\treturn Object.fromEntries(headers.entries());\n\t\treturn Object.fromEntries(new Headers(headers).entries());\n\t}\n\n\t/**\n\t * Serializes a value to JSON and masks sensitive fields (e.g. `Authorization`\n\t * headers, `password`/`token`/`secret` body fields) before it is written to the\n\t * debug output. See `SENSITIVE_DATA_KEYS`.\n\t */\n\tprivate static toRedactedJson(value: unknown): string {\n\t\treturn parseSensitiveData(JSON.stringify(value), [...SENSITIVE_DATA_KEYS]);\n\t}\n\n\tprivate onDebug(endpoint: string, method: string, data: DebugConfig) {\n\t\tif (this.enableDebug) {\n\t\t\tconst debugs: string[] = [];\n\n\t\t\tdebugs.push(`Base URL: ${this.baseUrl}`);\n\t\t\tdebugs.push(`Endpoint: ${endpoint}`);\n\t\t\tdebugs.push(`Status/Method: ${method} => ${data.status}`);\n\t\t\tdebugs.push(`Message: ${data.message}`);\n\n\t\t\tif (data.headers) {\n\t\t\t\tconst plainHeaders = ApiService.toPlainHeaders(data.headers);\n\t\t\t\tdebugs.push(`Headers: ${ApiService.toRedactedJson(plainHeaders)}`);\n\t\t\t}\n\t\t\tif (data.body)\n\t\t\t\tdebugs.push(`Body: ${ApiService.toRedactedJson(data.body)}`);\n\n\t\t\tflushDebugLogs({ debugs, name: \"ApiDebug\", scheme: \"yellow\" });\n\t\t}\n\t}\n\n\tprivate generateHeaders(\n\t\tinitHeaders: HeadersInit,\n\t\ttoken?: string,\n\t): HeadersInit {\n\t\tlet headers: HeadersInit = {};\n\t\tif (this.baseToken) headers = { Authorization: `Bearer ${this.baseToken}` };\n\t\tif (this.baseHeaders) headers = { ...headers, ...this.baseHeaders };\n\n\t\tif (initHeaders) headers = { ...headers, ...initHeaders };\n\t\tif (token) headers = { ...headers, Authorization: `Bearer ${token}` };\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Sends a get request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the get request to.\n\t * @param data - The request data, including optional headers and token.\n\t * @returns The API response data.\n\t */\n\n\tasync get(endpoint: string, data?: ApiRequestDataWithoutBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\n\t\tconst response = await getRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"get\", {\n\t\t\theaders,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a post request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the post request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync post(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await postRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"post\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a put request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the put request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync put(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await putRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"put\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a patch request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the patch request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync patch(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await patchRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"patch\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Sends a delete request to the specified endpoint.\n\t * @param endpoint - The API endpoint to send the delete request to.\n\t * @param data - The request data, including body, optional headers, and token.\n\t * @returns The API response data.\n\t */\n\n\tasync delete(endpoint: string, data?: ApiRequestDataWithBodyProps) {\n\t\tconst headers = this.generateHeaders(data?.headers || {}, data?.token);\n\t\tconst body = data?.body;\n\n\t\tconst response = await deleteRequest({\n\t\t\turl: this.baseUrl + endpoint,\n\t\t\turlParams: data?.urlParams || {},\n\t\t\theaders,\n\t\t\tbody,\n\t\t});\n\n\t\tthis.onDebug(endpoint, \"delete\", {\n\t\t\theaders,\n\t\t\tbody,\n\t\t\tmessage: response.message,\n\t\t\tstatus: response.status,\n\t\t});\n\n\t\treturn response;\n\t}\n}\n\nexport { ApiService };\n"],"mappings":"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"}
|
|
@@ -1,23 +1,41 @@
|
|
|
1
|
+
import { flushDebugLogs as e } from "../utilities/flushDebugLogs.js";
|
|
1
2
|
//#region src/services/logService.ts
|
|
2
|
-
var
|
|
3
|
+
var t = class t {
|
|
3
4
|
static config;
|
|
4
|
-
static
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
static isSecureEndpoint(e) {
|
|
6
|
+
return e.protocol === "https:" ? !0 : e.hostname === "localhost" || e.hostname === "127.0.0.1";
|
|
7
|
+
}
|
|
8
|
+
static setConfig(n) {
|
|
9
|
+
if (t.config) return;
|
|
10
|
+
let { trafficSourceId: r, userToken: i, logBaseApiUrl: a } = n, o = null;
|
|
11
|
+
if (a) try {
|
|
12
|
+
let n = new URL(a);
|
|
13
|
+
t.isSecureEndpoint(n) ? o = `${a}/ingest-log` : e({
|
|
14
|
+
name: "LogServiceError",
|
|
15
|
+
scheme: "red",
|
|
16
|
+
debugs: [`Insecure logBaseApiUrl "${a}" rejected: use https://, or http:// only for localhost/127.0.0.1. Remote logging disabled.`]
|
|
17
|
+
});
|
|
18
|
+
} catch {
|
|
19
|
+
e({
|
|
20
|
+
name: "LogServiceError",
|
|
21
|
+
scheme: "red",
|
|
22
|
+
debugs: [`Invalid logBaseApiUrl "${a}". Remote logging disabled.`]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
t.config = {
|
|
26
|
+
trafficSourceId: r,
|
|
27
|
+
userToken: i,
|
|
28
|
+
apiUrl: o
|
|
11
29
|
};
|
|
12
30
|
}
|
|
13
31
|
static getConfig() {
|
|
14
|
-
return
|
|
32
|
+
return t.config;
|
|
15
33
|
}
|
|
16
34
|
static resetConfig() {
|
|
17
|
-
|
|
35
|
+
t.config = void 0;
|
|
18
36
|
}
|
|
19
37
|
};
|
|
20
38
|
//#endregion
|
|
21
|
-
export {
|
|
39
|
+
export { t as LogService };
|
|
22
40
|
|
|
23
41
|
//# sourceMappingURL=logService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logService.js","names":[],"sources":["../../../src/services/logService.ts"],"sourcesContent":["/**\n * Static service for log endpoint configuration and access.\n *\n * Stores a singleton configuration containing the traffic source identifier,\n * user token, and log ingestion URL.\n */\nclass LogService {\n\tprivate static config?: {\n\t\ttrafficSourceId: string;\n\t\tuserToken: string;\n\t\tapiUrl: string;\n\t};\n\n\t/**\n\t * Sets the log service configuration once. Subsequent calls are ignored.\n\t *\n\t * @param config.trafficSourceId - Traffic source identifier.\n\t * @param config.userToken - User token for authentication.\n\t * @param config.logBaseApiUrl -
|
|
1
|
+
{"version":3,"file":"logService.js","names":[],"sources":["../../../src/services/logService.ts"],"sourcesContent":["import { flushDebugLogs } from \"../utilities/flushDebugLogs\";\n\n/**\n * Static service for log endpoint configuration and access.\n *\n * Stores a singleton configuration containing the traffic source identifier,\n * user token, and log ingestion URL.\n */\nclass LogService {\n\tprivate static config?: {\n\t\ttrafficSourceId: string;\n\t\tuserToken: string;\n\t\tapiUrl: string | null;\n\t};\n\n\t/**\n\t * Checks whether a log ingestion URL is safe to send telemetry to: `https://`\n\t * is always accepted, and plain `http://` is only accepted for local development\n\t * (`localhost` / `127.0.0.1`). Every other `http://` destination is rejected so\n\t * request/response data is never transmitted in plaintext over the network.\n\t */\n\tprivate static isSecureEndpoint(url: URL): boolean {\n\t\tif (url.protocol === \"https:\") return true;\n\t\treturn url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\";\n\t}\n\n\t/**\n\t * Sets the log service configuration once. Subsequent calls are ignored.\n\t *\n\t * There is no hardcoded fallback endpoint: if `logBaseApiUrl` is omitted, invalid,\n\t * or points at an insecure (`http://`) non-local destination, remote log delivery\n\t * is disabled (`getConfig().apiUrl` is `null`) instead of silently sending data to\n\t * a default/insecure host — `logRequest` skips the network call in that case.\n\t *\n\t * @param config.trafficSourceId - Traffic source identifier.\n\t * @param config.userToken - User token for authentication.\n\t * @param config.logBaseApiUrl - Log ingestion base URL. Must be `https://`, or\n\t * `http://localhost`/`http://127.0.0.1` for local development.\n\t */\n\tstatic setConfig(config: {\n\t\ttrafficSourceId: string;\n\t\tuserToken: string;\n\t\tlogBaseApiUrl?: string;\n\t}): void {\n\t\tif (LogService.config) return;\n\n\t\tconst { trafficSourceId, userToken, logBaseApiUrl } = config;\n\t\tlet apiUrl: string | null = null;\n\n\t\tif (logBaseApiUrl) {\n\t\t\ttry {\n\t\t\t\tconst parsedUrl = new URL(logBaseApiUrl);\n\n\t\t\t\tif (LogService.isSecureEndpoint(parsedUrl)) {\n\t\t\t\t\tapiUrl = `${logBaseApiUrl}/ingest-log`;\n\t\t\t\t} else {\n\t\t\t\t\tflushDebugLogs({\n\t\t\t\t\t\tname: \"LogServiceError\",\n\t\t\t\t\t\tscheme: \"red\",\n\t\t\t\t\t\tdebugs: [\n\t\t\t\t\t\t\t`Insecure logBaseApiUrl \"${logBaseApiUrl}\" rejected: use https://, or http:// only for localhost/127.0.0.1. Remote logging disabled.`,\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tflushDebugLogs({\n\t\t\t\t\tname: \"LogServiceError\",\n\t\t\t\t\tscheme: \"red\",\n\t\t\t\t\tdebugs: [\n\t\t\t\t\t\t`Invalid logBaseApiUrl \"${logBaseApiUrl}\". Remote logging disabled.`,\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tLogService.config = { trafficSourceId, userToken, apiUrl };\n\t}\n\n\t/** Returns the stored configuration, or `undefined` if `setConfig` has not been called. */\n\tstatic getConfig():\n\t\t| { trafficSourceId: string; userToken: string; apiUrl: string | null }\n\t\t| undefined {\n\t\treturn LogService.config;\n\t}\n\n\t/**\n\t * Resets the stored configuration, allowing a new initialization.\n\t */\n\tstatic resetConfig() {\n\t\tLogService.config = undefined;\n\t}\n}\n\nexport { LogService };\n"],"mappings":";;AAQA,IAAM,IAAN,MAAM,EAAW;CAChB,OAAe;CAYf,OAAe,iBAAiB,GAAmB;EAElD,OADI,EAAI,aAAa,WAAiB,KAC/B,EAAI,aAAa,eAAe,EAAI,aAAa;CACzD;CAeA,OAAO,UAAU,GAIR;EACR,IAAI,EAAW,QAAQ;EAEvB,IAAM,EAAE,oBAAiB,cAAW,qBAAkB,GAClD,IAAwB;EAE5B,IAAI,GACH,IAAI;GACH,IAAM,IAAY,IAAI,IAAI,CAAa;GAEvC,AAAI,EAAW,iBAAiB,CAAS,IACxC,IAAS,GAAG,EAAc,eAE1B,EAAe;IACd,MAAM;IACN,QAAQ;IACR,QAAQ,CACP,2BAA2B,EAAc,4FAC1C;GACD,CAAC;EAEH,QAAQ;GACP,EAAe;IACd,MAAM;IACN,QAAQ;IACR,QAAQ,CACP,0BAA0B,EAAc,4BACzC;GACD,CAAC;EACF;EAGD,EAAW,SAAS;GAAE;GAAiB;GAAW;EAAO;CAC1D;CAGA,OAAO,YAEM;EACZ,OAAO,EAAW;CACnB;CAKA,OAAO,cAAc;EACpB,EAAW,SAAS,KAAA;CACrB;AACD"}
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { BadRequest as e } from "../http/badResponses/badRequest.js";
|
|
2
2
|
//#region src/utilities/decodeRequestBody.ts
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
var t = 5 * 1024 * 1024;
|
|
4
|
+
async function n(n, r) {
|
|
5
|
+
let i, a = r?.maxBodySizeBytes ?? t, o = Number(n.headers.get("content-length"));
|
|
6
|
+
if (Number.isFinite(o) && o > a) throw new e("Request body exceeds the maximum allowed size");
|
|
7
|
+
let s = await n.arrayBuffer();
|
|
8
|
+
if (s.byteLength > a) throw new e("Request body exceeds the maximum allowed size");
|
|
9
|
+
let c = new TextDecoder().decode(s);
|
|
5
10
|
try {
|
|
6
|
-
|
|
11
|
+
i = JSON.parse(c);
|
|
7
12
|
} catch {
|
|
8
13
|
try {
|
|
9
|
-
if (
|
|
10
|
-
let e = new URLSearchParams(
|
|
11
|
-
|
|
14
|
+
if (c.includes("=")) {
|
|
15
|
+
let e = new URLSearchParams(c);
|
|
16
|
+
i = Object.fromEntries(e.entries());
|
|
12
17
|
} else throw new e("Invalid URLSearchParams format");
|
|
13
18
|
} catch {
|
|
14
19
|
throw new e("Failed to extract data from request");
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
|
-
return
|
|
22
|
+
return i;
|
|
18
23
|
}
|
|
19
24
|
//#endregion
|
|
20
|
-
export {
|
|
25
|
+
export { n as decodeRequestBody };
|
|
21
26
|
|
|
22
27
|
//# sourceMappingURL=decodeRequestBody.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decodeRequestBody.js","names":[],"sources":["../../../src/utilities/decodeRequestBody.ts"],"sourcesContent":["import { BadRequest } from \"../http/badResponses/badRequest\";\n\n/**\n * Decodes a request body into a plain object, trying JSON first then URL-encoded form data.\n * Throws `BadRequest` if neither format can be parsed
|
|
1
|
+
{"version":3,"file":"decodeRequestBody.js","names":[],"sources":["../../../src/utilities/decodeRequestBody.ts"],"sourcesContent":["import { BadRequest } from \"../http/badResponses/badRequest\";\n\n/** Default maximum accepted request body size (5 MB) when `maxBodySizeBytes` isn't set. */\nconst DEFAULT_MAX_BODY_SIZE_BYTES = 5 * 1024 * 1024;\n\ntype DecodeRequestBodyOptions = {\n\t/** Max accepted body size in bytes. Larger bodies are rejected with `BadRequest`. @default 5242880 (5 MB) */\n\tmaxBodySizeBytes?: number;\n};\n\n/**\n * Decodes a request body into a plain object, trying JSON first then URL-encoded form data.\n * Throws `BadRequest` if neither format can be parsed, or if the body exceeds `maxBodySizeBytes`.\n *\n * @param request - The incoming request whose body will be decoded.\n * @param options.maxBodySizeBytes - Max accepted body size in bytes. Default: 5 MB.\n * @returns The decoded body as a plain object.\n *\n * @example\n * ```typescript\n * export async function action({ request }: ActionFunctionArgs) {\n * const body = await decodeRequestBody(request);\n * // body is now a plain JS object\n * }\n * ```\n */\n\nasync function decodeRequestBody(\n\trequest: Request,\n\toptions?: DecodeRequestBodyOptions,\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n): Promise<any> {\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tlet data: any;\n\n\tconst maxBodySizeBytes =\n\t\toptions?.maxBodySizeBytes ?? DEFAULT_MAX_BODY_SIZE_BYTES;\n\n\tconst contentLength = Number(request.headers.get(\"content-length\"));\n\tif (Number.isFinite(contentLength) && contentLength > maxBodySizeBytes) {\n\t\tthrow new BadRequest(\"Request body exceeds the maximum allowed size\");\n\t}\n\n\tconst arrayBuffer = await request.arrayBuffer();\n\n\tif (arrayBuffer.byteLength > maxBodySizeBytes) {\n\t\tthrow new BadRequest(\"Request body exceeds the maximum allowed size\");\n\t}\n\n\tconst text = new TextDecoder().decode(arrayBuffer);\n\n\ttry {\n\t\tdata = JSON.parse(text);\n\t} catch (_jsonError) {\n\t\ttry {\n\t\t\tif (text.includes(\"=\")) {\n\t\t\t\tconst formData = new URLSearchParams(text);\n\t\t\t\tdata = Object.fromEntries(formData.entries());\n\t\t\t} else {\n\t\t\t\tthrow new BadRequest(\"Invalid URLSearchParams format\");\n\t\t\t}\n\t\t} catch (_formDataError) {\n\t\t\tthrow new BadRequest(\"Failed to extract data from request\");\n\t\t}\n\t}\n\n\treturn data;\n}\n\nexport { decodeRequestBody };\n"],"mappings":";;AAGA,IAAM,IAA8B,IAAI,OAAO;AAwB/C,eAAe,EACd,GACA,GAEe;CAEf,IAAI,GAEE,IACL,GAAS,oBAAoB,GAExB,IAAgB,OAAO,EAAQ,QAAQ,IAAI,gBAAgB,CAAC;CAClE,IAAI,OAAO,SAAS,CAAa,KAAK,IAAgB,GACrD,MAAM,IAAI,EAAW,+CAA+C;CAGrE,IAAM,IAAc,MAAM,EAAQ,YAAY;CAE9C,IAAI,EAAY,aAAa,GAC5B,MAAM,IAAI,EAAW,+CAA+C;CAGrE,IAAM,IAAO,IAAI,YAAY,CAAC,CAAC,OAAO,CAAW;CAEjD,IAAI;EACH,IAAO,KAAK,MAAM,CAAI;CACvB,QAAqB;EACpB,IAAI;GACH,IAAI,EAAK,SAAS,GAAG,GAAG;IACvB,IAAM,IAAW,IAAI,gBAAgB,CAAI;IACzC,IAAO,OAAO,YAAY,EAAS,QAAQ,CAAC;GAC7C,OACC,MAAM,IAAI,EAAW,gCAAgC;EAEvD,QAAyB;GACxB,MAAM,IAAI,EAAW,qCAAqC;EAC3D;CACD;CAEA,OAAO;AACR"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/utilities/sensitiveDataKeys.ts
|
|
2
|
+
var e = [
|
|
3
|
+
"password",
|
|
4
|
+
"Password",
|
|
5
|
+
"confirmPassword",
|
|
6
|
+
"ConfirmPassword",
|
|
7
|
+
"creditCard",
|
|
8
|
+
"CreditCard",
|
|
9
|
+
"authorization",
|
|
10
|
+
"Authorization",
|
|
11
|
+
"cookie",
|
|
12
|
+
"Cookie",
|
|
13
|
+
"set-cookie",
|
|
14
|
+
"Set-Cookie",
|
|
15
|
+
"setCookie",
|
|
16
|
+
"SetCookie",
|
|
17
|
+
"token",
|
|
18
|
+
"Token",
|
|
19
|
+
"refreshToken",
|
|
20
|
+
"RefreshToken",
|
|
21
|
+
"accessToken",
|
|
22
|
+
"AccessToken",
|
|
23
|
+
"apiKey",
|
|
24
|
+
"ApiKey",
|
|
25
|
+
"secret",
|
|
26
|
+
"Secret"
|
|
27
|
+
];
|
|
28
|
+
//#endregion
|
|
29
|
+
export { e as SENSITIVE_DATA_KEYS };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=sensitiveDataKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitiveDataKeys.js","names":[],"sources":["../../../src/utilities/sensitiveDataKeys.ts"],"sourcesContent":["/**\n * Keys treated as sensitive wherever request/response data is written to a debug\n * log or sent to a telemetry sink (see `ApiService`'s debug output and the\n * `LogService` remote logging pipeline).\n *\n * Passed as the `sensitiveKeys` argument to `parseSensitiveData` (from `@arkyn/shared`)\n * so values are masked with `\"****\"` before they reach any console output or network\n * request.\n *\n * Both `lowerCase` and `Capitalized`/`Header-Case` variants are listed explicitly for\n * header-shaped keys (`Authorization`, `Cookie`, `Set-Cookie`, ...). This is\n * intentionally redundant with `parseSensitiveData`'s own case-insensitive matching:\n * it keeps this list correct regardless of which build of `parseSensitiveData` is\n * resolved at runtime, since a `Headers` instance lowercases names on iteration while\n * plain header objects commonly use `Authorization`/`Header-Case`.\n *\n * Extends the default `parseSensitiveData` key list (`password`, `confirmPassword`,\n * `creditCard`) with header/token-shaped keys that commonly carry credentials.\n */\nconst SENSITIVE_DATA_KEYS = [\n\t\"password\",\n\t\"Password\",\n\t\"confirmPassword\",\n\t\"ConfirmPassword\",\n\t\"creditCard\",\n\t\"CreditCard\",\n\t\"authorization\",\n\t\"Authorization\",\n\t\"cookie\",\n\t\"Cookie\",\n\t\"set-cookie\",\n\t\"Set-Cookie\",\n\t\"setCookie\",\n\t\"SetCookie\",\n\t\"token\",\n\t\"Token\",\n\t\"refreshToken\",\n\t\"RefreshToken\",\n\t\"accessToken\",\n\t\"AccessToken\",\n\t\"apiKey\",\n\t\"ApiKey\",\n\t\"secret\",\n\t\"Secret\",\n] as const;\n\nexport { SENSITIVE_DATA_KEYS };\n"],"mappings":";AAmBA,IAAM,IAAsB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD"}
|
|
@@ -31,26 +31,31 @@ var s = [
|
|
|
31
31
|
"MX",
|
|
32
32
|
"A",
|
|
33
33
|
"AAAA"
|
|
34
|
-
];
|
|
35
|
-
async function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
], c = 5e3;
|
|
35
|
+
async function l(t, n, r) {
|
|
36
|
+
return new Promise((i) => {
|
|
37
|
+
let a = !1, o = setTimeout(() => {
|
|
38
|
+
a || (a = !0, i(!1));
|
|
39
|
+
}, r);
|
|
40
|
+
o.unref?.(), e.promises.resolve(t, n).then(() => {
|
|
41
|
+
a || (a = !0, clearTimeout(o), i(!0));
|
|
42
|
+
}).catch(() => {
|
|
43
|
+
a || (a = !0, clearTimeout(o), i(!1));
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function u(e, t) {
|
|
48
|
+
for (let n of s) if (await l(e, n, t)) return !0;
|
|
44
49
|
return !1;
|
|
45
50
|
}
|
|
46
|
-
async function
|
|
51
|
+
async function d(e, n) {
|
|
47
52
|
if (!e || typeof e != "string") return !1;
|
|
48
|
-
let
|
|
49
|
-
if (!t(
|
|
50
|
-
let
|
|
51
|
-
return
|
|
53
|
+
let r = e.trim();
|
|
54
|
+
if (!t(r) || !a(r)) return !1;
|
|
55
|
+
let i = o(r);
|
|
56
|
+
return i ? await u(i, n?.dnsTimeoutMs ?? c) : !1;
|
|
52
57
|
}
|
|
53
58
|
//#endregion
|
|
54
|
-
export {
|
|
59
|
+
export { d as validateEmail };
|
|
55
60
|
|
|
56
61
|
//# sourceMappingURL=validateEmail.js.map
|