@diegotsi/flint-core 1.9.1 → 1.10.0
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/index.cjs +108 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +108 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -903,7 +903,8 @@ function captureHeaders(raw, max) {
|
|
|
903
903
|
count++;
|
|
904
904
|
}
|
|
905
905
|
} else {
|
|
906
|
-
const
|
|
906
|
+
const headersLike = raw;
|
|
907
|
+
const entries = typeof headersLike.entries === "function" && typeof headersLike.forEach === "function" ? headersLike.entries() : Array.isArray(raw) ? raw : Object.entries(raw);
|
|
907
908
|
for (const [k, v] of entries) {
|
|
908
909
|
total++;
|
|
909
910
|
if (count >= max) continue;
|
|
@@ -921,7 +922,7 @@ function captureHeaders(raw, max) {
|
|
|
921
922
|
function extractContentType(headers) {
|
|
922
923
|
if (!headers) return void 0;
|
|
923
924
|
try {
|
|
924
|
-
if (typeof
|
|
925
|
+
if (typeof headers.get === "function") return headers.get("content-type") ?? void 0;
|
|
925
926
|
if (Array.isArray(headers)) {
|
|
926
927
|
const found = headers.find(([k]) => k.toLowerCase() === "content-type");
|
|
927
928
|
return found?.[1];
|
|
@@ -934,17 +935,22 @@ function extractContentType(headers) {
|
|
|
934
935
|
}
|
|
935
936
|
return void 0;
|
|
936
937
|
}
|
|
937
|
-
function createNetworkCollector(extraBlockedHosts = []) {
|
|
938
|
+
function createNetworkCollector(extraBlockedHosts = [], options) {
|
|
939
|
+
const maxEntries = options?.maxEntries ?? MAX_ENTRIES3;
|
|
940
|
+
const maxResponseBody = options?.maxResponseBody ?? MAX_RESPONSE_BODY;
|
|
938
941
|
const entries = [];
|
|
939
942
|
const blocked = /* @__PURE__ */ new Set([...DEFAULT_BLOCKED_HOSTS, ...extraBlockedHosts]);
|
|
940
943
|
let origFetch = null;
|
|
941
944
|
let origXHROpen = null;
|
|
942
945
|
let origXHRSend = null;
|
|
943
946
|
let origXHRSetHeader = null;
|
|
947
|
+
let perfObserver = null;
|
|
944
948
|
let active = false;
|
|
949
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
945
950
|
function push(entry) {
|
|
951
|
+
seenUrls.add(entry.fullUrl ?? entry.url);
|
|
946
952
|
entries.push(entry);
|
|
947
|
-
if (entries.length >
|
|
953
|
+
if (entries.length > maxEntries) entries.shift();
|
|
948
954
|
}
|
|
949
955
|
return {
|
|
950
956
|
start() {
|
|
@@ -952,19 +958,50 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
952
958
|
active = true;
|
|
953
959
|
origFetch = window.fetch;
|
|
954
960
|
window.fetch = async (input, init2) => {
|
|
955
|
-
const
|
|
956
|
-
const
|
|
961
|
+
const reqObj = typeof Request !== "undefined" && input instanceof Request ? input : null;
|
|
962
|
+
const method = (init2?.method ?? reqObj?.method ?? "GET").toUpperCase();
|
|
963
|
+
const url = reqObj ? reqObj.url : typeof input === "string" ? input : input.href;
|
|
957
964
|
const startTime = Date.now();
|
|
958
|
-
const
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
|
|
965
|
+
const reqHeaders = captureHeaders(init2?.headers ?? reqObj?.headers, MAX_HEADERS);
|
|
966
|
+
const reqContentType = extractContentType(init2?.headers ?? reqObj?.headers);
|
|
967
|
+
let reqBody = safeBodyPreview(init2?.body, MAX_REQUEST_BODY);
|
|
968
|
+
if (reqBody === void 0 && reqObj && !shouldIgnore(url, blocked)) {
|
|
969
|
+
try {
|
|
970
|
+
const t = await reqObj.clone().text();
|
|
971
|
+
if (t) reqBody = t.length > MAX_REQUEST_BODY ? t.slice(0, MAX_REQUEST_BODY) + "\u2026" : t;
|
|
972
|
+
} catch {
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
let res;
|
|
976
|
+
try {
|
|
977
|
+
res = await origFetch.call(window, input, init2);
|
|
978
|
+
} catch (err) {
|
|
979
|
+
if (!shouldIgnore(url, blocked)) {
|
|
980
|
+
push({
|
|
981
|
+
method,
|
|
982
|
+
url: truncateUrl(url),
|
|
983
|
+
fullUrl: captureFullUrl(url),
|
|
984
|
+
status: 0,
|
|
985
|
+
duration: Date.now() - startTime,
|
|
986
|
+
timestamp: startTime,
|
|
987
|
+
source: "fetch",
|
|
988
|
+
failed: true,
|
|
989
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
990
|
+
requestHeaders: reqHeaders,
|
|
991
|
+
requestBody: reqBody,
|
|
992
|
+
requestContentType: reqContentType
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
throw err;
|
|
996
|
+
}
|
|
962
997
|
if (!shouldIgnore(url, blocked)) {
|
|
963
998
|
const entry = {
|
|
964
999
|
method,
|
|
965
1000
|
url: truncateUrl(url),
|
|
966
1001
|
fullUrl: captureFullUrl(url),
|
|
967
1002
|
status: res.status,
|
|
1003
|
+
statusText: res.statusText || void 0,
|
|
1004
|
+
source: "fetch",
|
|
968
1005
|
duration: Date.now() - startTime,
|
|
969
1006
|
timestamp: startTime,
|
|
970
1007
|
requestHeaders: reqHeaders,
|
|
@@ -977,7 +1014,7 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
977
1014
|
try {
|
|
978
1015
|
const clone = res.clone();
|
|
979
1016
|
clone.text().then((text) => {
|
|
980
|
-
entry.responseBody = text.length >
|
|
1017
|
+
entry.responseBody = text.length > maxResponseBody ? text.slice(0, maxResponseBody) + "\u2026" : text;
|
|
981
1018
|
if (!entry.responseSize && text.length) entry.responseSize = text.length;
|
|
982
1019
|
}).catch(() => {
|
|
983
1020
|
});
|
|
@@ -1014,13 +1051,16 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1014
1051
|
XMLHttpRequest.prototype.open = function(method, url, async, username, password) {
|
|
1015
1052
|
const startTime = Date.now();
|
|
1016
1053
|
const urlStr = typeof url === "string" ? url : url.href;
|
|
1054
|
+
let captured = false;
|
|
1017
1055
|
this.addEventListener("load", () => {
|
|
1056
|
+
if (captured) return;
|
|
1057
|
+
captured = true;
|
|
1018
1058
|
if (!shouldIgnore(urlStr, blocked)) {
|
|
1019
1059
|
const meta = xhrMeta.get(this);
|
|
1020
1060
|
let resBody;
|
|
1021
1061
|
try {
|
|
1022
1062
|
const text = this.responseText;
|
|
1023
|
-
resBody = text && text.length >
|
|
1063
|
+
resBody = text && text.length > maxResponseBody ? text.slice(0, maxResponseBody) + "\u2026" : text || void 0;
|
|
1024
1064
|
} catch {
|
|
1025
1065
|
}
|
|
1026
1066
|
push({
|
|
@@ -1028,6 +1068,8 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1028
1068
|
url: truncateUrl(urlStr),
|
|
1029
1069
|
fullUrl: captureFullUrl(urlStr),
|
|
1030
1070
|
status: this.status,
|
|
1071
|
+
statusText: this.statusText || void 0,
|
|
1072
|
+
source: "xhr",
|
|
1031
1073
|
duration: Date.now() - startTime,
|
|
1032
1074
|
timestamp: startTime,
|
|
1033
1075
|
requestHeaders: meta?.reqHeaders && Object.keys(meta.reqHeaders).length > 0 ? meta.reqHeaders : void 0,
|
|
@@ -1040,8 +1082,58 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1040
1082
|
});
|
|
1041
1083
|
}
|
|
1042
1084
|
});
|
|
1085
|
+
const pushFailure = (errorMessage) => {
|
|
1086
|
+
if (captured) return;
|
|
1087
|
+
captured = true;
|
|
1088
|
+
if (shouldIgnore(urlStr, blocked)) return;
|
|
1089
|
+
const meta = xhrMeta.get(this);
|
|
1090
|
+
push({
|
|
1091
|
+
method: method.toUpperCase(),
|
|
1092
|
+
url: truncateUrl(urlStr),
|
|
1093
|
+
fullUrl: captureFullUrl(urlStr),
|
|
1094
|
+
status: 0,
|
|
1095
|
+
source: "xhr",
|
|
1096
|
+
failed: true,
|
|
1097
|
+
errorMessage,
|
|
1098
|
+
duration: Date.now() - startTime,
|
|
1099
|
+
timestamp: startTime,
|
|
1100
|
+
requestHeaders: meta?.reqHeaders && Object.keys(meta.reqHeaders).length > 0 ? meta.reqHeaders : void 0,
|
|
1101
|
+
requestBody: meta?.reqBody,
|
|
1102
|
+
requestContentType: meta?.reqContentType
|
|
1103
|
+
});
|
|
1104
|
+
};
|
|
1105
|
+
this.addEventListener("error", () => pushFailure("Network error"));
|
|
1106
|
+
this.addEventListener("timeout", () => pushFailure("Timeout"));
|
|
1107
|
+
this.addEventListener("abort", () => pushFailure("Aborted"));
|
|
1043
1108
|
return origXHROpen.apply(this, [method, url, async ?? true, username, password]);
|
|
1044
1109
|
};
|
|
1110
|
+
if (typeof PerformanceObserver !== "undefined") {
|
|
1111
|
+
try {
|
|
1112
|
+
perfObserver = new PerformanceObserver((list) => {
|
|
1113
|
+
for (const entry of list.getEntries()) {
|
|
1114
|
+
const res = entry;
|
|
1115
|
+
if (res.initiatorType !== "fetch" && res.initiatorType !== "xmlhttprequest") continue;
|
|
1116
|
+
const url = res.name;
|
|
1117
|
+
if (shouldIgnore(url, blocked)) continue;
|
|
1118
|
+
if (seenUrls.has(captureFullUrl(url)) || seenUrls.has(truncateUrl(url))) continue;
|
|
1119
|
+
push({
|
|
1120
|
+
// Resource timing does not expose the HTTP method; default to GET.
|
|
1121
|
+
method: "GET",
|
|
1122
|
+
url: truncateUrl(url),
|
|
1123
|
+
fullUrl: captureFullUrl(url),
|
|
1124
|
+
status: res.responseStatus ?? 0,
|
|
1125
|
+
source: "perf",
|
|
1126
|
+
duration: Math.round(res.duration),
|
|
1127
|
+
timestamp: Math.round(performance.timeOrigin + res.startTime),
|
|
1128
|
+
responseSize: res.transferSize || res.encodedBodySize || void 0
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
perfObserver.observe({ type: "resource", buffered: true });
|
|
1133
|
+
} catch {
|
|
1134
|
+
perfObserver = null;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1045
1137
|
},
|
|
1046
1138
|
stop() {
|
|
1047
1139
|
if (!active) return;
|
|
@@ -1050,6 +1142,10 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1050
1142
|
if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;
|
|
1051
1143
|
if (origXHRSend) XMLHttpRequest.prototype.send = origXHRSend;
|
|
1052
1144
|
if (origXHRSetHeader) XMLHttpRequest.prototype.setRequestHeader = origXHRSetHeader;
|
|
1145
|
+
if (perfObserver) {
|
|
1146
|
+
perfObserver.disconnect();
|
|
1147
|
+
perfObserver = null;
|
|
1148
|
+
}
|
|
1053
1149
|
},
|
|
1054
1150
|
getEntries() {
|
|
1055
1151
|
return [...entries];
|