@arkyn/server 3.0.7 → 3.0.9
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/AGENTS.md +200 -0
- package/dist/http/api/_logRequest.d.ts.map +1 -1
- package/dist/index.js +200 -146
- package/dist/index.js.map +1 -1
- package/dist/modules/http/api/_logRequest.js +31 -28
- package/dist/modules/http/api/_logRequest.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/sensitiveDataKeys.js +31 -0
- package/dist/modules/utilities/sensitiveDataKeys.js.map +1 -0
- 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/sensitiveDataKeys.d.ts +22 -0
- package/dist/utilities/sensitiveDataKeys.d.ts.map +1 -0
- package/package.json +7 -6
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
import { flushDebugLogs as e } from "../../utilities/flushDebugLogs.js";
|
|
2
2
|
import { LogService as t } from "../../services/logService.js";
|
|
3
|
-
import {
|
|
3
|
+
import { SENSITIVE_DATA_KEYS as n } from "../../utilities/sensitiveDataKeys.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 = t.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 t = new URL(
|
|
11
|
-
t.protocol === "http:" && (
|
|
12
|
-
let
|
|
13
|
+
let t = new URL(v), a = "https";
|
|
14
|
+
t.protocol === "http:" && (a = "http");
|
|
15
|
+
let o = JSON.stringify({
|
|
13
16
|
domainUrl: `${t.protocol}//${t.host}`,
|
|
14
17
|
pathnameUrl: t.pathname,
|
|
15
|
-
trafficSourceId:
|
|
16
|
-
status:
|
|
17
|
-
protocol:
|
|
18
|
-
method:
|
|
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), [...n]),
|
|
25
|
+
requestBody: i(JSON.stringify(p), [...n]),
|
|
26
|
+
queryParams: JSON.stringify(f),
|
|
27
|
+
responseHeaders: i(JSON.stringify(g), [...n]),
|
|
28
|
+
responseBody: i(JSON.stringify(h), [...n])
|
|
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"}
|
|
@@ -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"}
|
|
@@ -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"}
|
|
@@ -41,6 +41,18 @@ declare class ApiService {
|
|
|
41
41
|
private baseToken?;
|
|
42
42
|
private enableDebug?;
|
|
43
43
|
constructor(props: ApiServiceConstructorProps);
|
|
44
|
+
/**
|
|
45
|
+
* Converts a `HeadersInit` value into a plain object so it can be safely
|
|
46
|
+
* JSON-serialized and redacted, regardless of whether it was provided as a
|
|
47
|
+
* `Headers` instance, a plain object, or an array of tuples.
|
|
48
|
+
*/
|
|
49
|
+
private static toPlainHeaders;
|
|
50
|
+
/**
|
|
51
|
+
* Serializes a value to JSON and masks sensitive fields (e.g. `Authorization`
|
|
52
|
+
* headers, `password`/`token`/`secret` body fields) before it is written to the
|
|
53
|
+
* debug output. See `SENSITIVE_DATA_KEYS`.
|
|
54
|
+
*/
|
|
55
|
+
private static toRedactedJson;
|
|
44
56
|
private onDebug;
|
|
45
57
|
private generateHeaders;
|
|
46
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiService.d.ts","sourceRoot":"","sources":["../../src/services/apiService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apiService.d.ts","sourceRoot":"","sources":["../../src/services/apiService.ts"],"names":[],"mappings":"AASA,KAAK,0BAA0B,GAAG;IACjC,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iFAAiF;IACjF,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACrC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,2BAA2B,GAAG;IAElC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAUF;;;;;;;;;;;;;;;GAeG;AACH,cAAM,UAAU;IACf,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAC,CAAU;gBAElB,KAAK,EAAE,0BAA0B;IAO7C;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAM7B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,eAAe;IAcvB;;;;;OAKG;IAEG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,8BAA8B;IAkBjE;;;;;OAKG;IAEG,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,2BAA2B;IAqB/D;;;;;OAKG;IAEG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,2BAA2B;IAqB9D;;;;;OAKG;IAEG,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,2BAA2B;IAqBhE;;;;;OAKG;IAEG,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,2BAA2B;CAoBjE;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -6,12 +6,25 @@
|
|
|
6
6
|
*/
|
|
7
7
|
declare class LogService {
|
|
8
8
|
private static config?;
|
|
9
|
+
/**
|
|
10
|
+
* Checks whether a log ingestion URL is safe to send telemetry to: `https://`
|
|
11
|
+
* is always accepted, and plain `http://` is only accepted for local development
|
|
12
|
+
* (`localhost` / `127.0.0.1`). Every other `http://` destination is rejected so
|
|
13
|
+
* request/response data is never transmitted in plaintext over the network.
|
|
14
|
+
*/
|
|
15
|
+
private static isSecureEndpoint;
|
|
9
16
|
/**
|
|
10
17
|
* Sets the log service configuration once. Subsequent calls are ignored.
|
|
11
18
|
*
|
|
19
|
+
* There is no hardcoded fallback endpoint: if `logBaseApiUrl` is omitted, invalid,
|
|
20
|
+
* or points at an insecure (`http://`) non-local destination, remote log delivery
|
|
21
|
+
* is disabled (`getConfig().apiUrl` is `null`) instead of silently sending data to
|
|
22
|
+
* a default/insecure host — `logRequest` skips the network call in that case.
|
|
23
|
+
*
|
|
12
24
|
* @param config.trafficSourceId - Traffic source identifier.
|
|
13
25
|
* @param config.userToken - User token for authentication.
|
|
14
|
-
* @param config.logBaseApiUrl -
|
|
26
|
+
* @param config.logBaseApiUrl - Log ingestion base URL. Must be `https://`, or
|
|
27
|
+
* `http://localhost`/`http://127.0.0.1` for local development.
|
|
15
28
|
*/
|
|
16
29
|
static setConfig(config: {
|
|
17
30
|
trafficSourceId: string;
|
|
@@ -22,7 +35,7 @@ declare class LogService {
|
|
|
22
35
|
static getConfig(): {
|
|
23
36
|
trafficSourceId: string;
|
|
24
37
|
userToken: string;
|
|
25
|
-
apiUrl: string;
|
|
38
|
+
apiUrl: string | null;
|
|
26
39
|
} | undefined;
|
|
27
40
|
/**
|
|
28
41
|
* Resets the stored configuration, allowing a new initialization.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logService.d.ts","sourceRoot":"","sources":["../../src/services/logService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logService.d.ts","sourceRoot":"","sources":["../../src/services/logService.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,cAAM,UAAU;IACf,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAIpB;IAEF;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;QACxB,eAAe,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,IAAI;IAmCR,2FAA2F;IAC3F,MAAM,CAAC,SAAS,IACb;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACrE,SAAS;IAIZ;;OAEG;IACH,MAAM,CAAC,WAAW;CAGlB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys treated as sensitive wherever request/response data is written to a debug
|
|
3
|
+
* log or sent to a telemetry sink (see `ApiService`'s debug output and the
|
|
4
|
+
* `LogService` remote logging pipeline).
|
|
5
|
+
*
|
|
6
|
+
* Passed as the `sensitiveKeys` argument to `parseSensitiveData` (from `@arkyn/shared`)
|
|
7
|
+
* so values are masked with `"****"` before they reach any console output or network
|
|
8
|
+
* request.
|
|
9
|
+
*
|
|
10
|
+
* Both `lowerCase` and `Capitalized`/`Header-Case` variants are listed explicitly for
|
|
11
|
+
* header-shaped keys (`Authorization`, `Cookie`, `Set-Cookie`, ...). This is
|
|
12
|
+
* intentionally redundant with `parseSensitiveData`'s own case-insensitive matching:
|
|
13
|
+
* it keeps this list correct regardless of which build of `parseSensitiveData` is
|
|
14
|
+
* resolved at runtime, since a `Headers` instance lowercases names on iteration while
|
|
15
|
+
* plain header objects commonly use `Authorization`/`Header-Case`.
|
|
16
|
+
*
|
|
17
|
+
* Extends the default `parseSensitiveData` key list (`password`, `confirmPassword`,
|
|
18
|
+
* `creditCard`) with header/token-shaped keys that commonly carry credentials.
|
|
19
|
+
*/
|
|
20
|
+
declare const SENSITIVE_DATA_KEYS: readonly ["password", "Password", "confirmPassword", "ConfirmPassword", "creditCard", "CreditCard", "authorization", "Authorization", "cookie", "Cookie", "set-cookie", "Set-Cookie", "setCookie", "SetCookie", "token", "Token", "refreshToken", "RefreshToken", "accessToken", "AccessToken", "apiKey", "ApiKey", "secret", "Secret"];
|
|
21
|
+
export { SENSITIVE_DATA_KEYS };
|
|
22
|
+
//# sourceMappingURL=sensitiveDataKeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitiveDataKeys.d.ts","sourceRoot":"","sources":["../../src/utilities/sensitiveDataKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,mBAAmB,yUAyBf,CAAC;AAEX,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkyn/server",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.9",
|
|
4
4
|
"author": "Arkyn | Lucas Gonçalves",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -35,19 +35,20 @@
|
|
|
35
35
|
"files": [
|
|
36
36
|
"dist",
|
|
37
37
|
"README.md",
|
|
38
|
+
"AGENTS.md",
|
|
38
39
|
"LICENSE.txt"
|
|
39
40
|
],
|
|
40
41
|
"sideEffects": false,
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"@arkyn/shared": "
|
|
43
|
-
"@arkyn/templates": "
|
|
43
|
+
"@arkyn/shared": "^3.0.2",
|
|
44
|
+
"@arkyn/templates": "^3.0.2"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
|
-
"audit": "bun audit
|
|
47
|
+
"audit": "bun audit",
|
|
47
48
|
"build": "bunx vite build && bunx tsc --project tsconfig.json --emitDeclarationOnly && bun ./generate-exports.ts && rm -f dist/modules/index.js dist/modules/style.css",
|
|
48
49
|
"prebuild": "rm -rf dist",
|
|
49
|
-
"publish:beta": "
|
|
50
|
-
"publish:latest": "
|
|
50
|
+
"publish:beta": "bash ../../scripts/publish-idempotent.sh beta",
|
|
51
|
+
"publish:latest": "bash ../../scripts/publish-idempotent.sh latest",
|
|
51
52
|
"release:beta": "bun ./generate-version.ts beta",
|
|
52
53
|
"release:patch": "bun ./generate-version.ts patch",
|
|
53
54
|
"release:minor": "bun ./generate-version.ts minor",
|