@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.cjs
CHANGED
|
@@ -989,7 +989,8 @@ function captureHeaders(raw, max) {
|
|
|
989
989
|
count++;
|
|
990
990
|
}
|
|
991
991
|
} else {
|
|
992
|
-
const
|
|
992
|
+
const headersLike = raw;
|
|
993
|
+
const entries = typeof headersLike.entries === "function" && typeof headersLike.forEach === "function" ? headersLike.entries() : Array.isArray(raw) ? raw : Object.entries(raw);
|
|
993
994
|
for (const [k, v] of entries) {
|
|
994
995
|
total++;
|
|
995
996
|
if (count >= max) continue;
|
|
@@ -1007,7 +1008,7 @@ function captureHeaders(raw, max) {
|
|
|
1007
1008
|
function extractContentType(headers) {
|
|
1008
1009
|
if (!headers) return void 0;
|
|
1009
1010
|
try {
|
|
1010
|
-
if (typeof
|
|
1011
|
+
if (typeof headers.get === "function") return headers.get("content-type") ?? void 0;
|
|
1011
1012
|
if (Array.isArray(headers)) {
|
|
1012
1013
|
const found = headers.find(([k]) => k.toLowerCase() === "content-type");
|
|
1013
1014
|
return found?.[1];
|
|
@@ -1020,17 +1021,22 @@ function extractContentType(headers) {
|
|
|
1020
1021
|
}
|
|
1021
1022
|
return void 0;
|
|
1022
1023
|
}
|
|
1023
|
-
function createNetworkCollector(extraBlockedHosts = []) {
|
|
1024
|
+
function createNetworkCollector(extraBlockedHosts = [], options) {
|
|
1025
|
+
const maxEntries = options?.maxEntries ?? MAX_ENTRIES3;
|
|
1026
|
+
const maxResponseBody = options?.maxResponseBody ?? MAX_RESPONSE_BODY;
|
|
1024
1027
|
const entries = [];
|
|
1025
1028
|
const blocked = /* @__PURE__ */ new Set([...DEFAULT_BLOCKED_HOSTS, ...extraBlockedHosts]);
|
|
1026
1029
|
let origFetch = null;
|
|
1027
1030
|
let origXHROpen = null;
|
|
1028
1031
|
let origXHRSend = null;
|
|
1029
1032
|
let origXHRSetHeader = null;
|
|
1033
|
+
let perfObserver = null;
|
|
1030
1034
|
let active = false;
|
|
1035
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
1031
1036
|
function push(entry) {
|
|
1037
|
+
seenUrls.add(entry.fullUrl ?? entry.url);
|
|
1032
1038
|
entries.push(entry);
|
|
1033
|
-
if (entries.length >
|
|
1039
|
+
if (entries.length > maxEntries) entries.shift();
|
|
1034
1040
|
}
|
|
1035
1041
|
return {
|
|
1036
1042
|
start() {
|
|
@@ -1038,19 +1044,50 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1038
1044
|
active = true;
|
|
1039
1045
|
origFetch = window.fetch;
|
|
1040
1046
|
window.fetch = async (input, init2) => {
|
|
1041
|
-
const
|
|
1042
|
-
const
|
|
1047
|
+
const reqObj = typeof Request !== "undefined" && input instanceof Request ? input : null;
|
|
1048
|
+
const method = (init2?.method ?? reqObj?.method ?? "GET").toUpperCase();
|
|
1049
|
+
const url = reqObj ? reqObj.url : typeof input === "string" ? input : input.href;
|
|
1043
1050
|
const startTime = Date.now();
|
|
1044
|
-
const
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1051
|
+
const reqHeaders = captureHeaders(init2?.headers ?? reqObj?.headers, MAX_HEADERS);
|
|
1052
|
+
const reqContentType = extractContentType(init2?.headers ?? reqObj?.headers);
|
|
1053
|
+
let reqBody = safeBodyPreview(init2?.body, MAX_REQUEST_BODY);
|
|
1054
|
+
if (reqBody === void 0 && reqObj && !shouldIgnore(url, blocked)) {
|
|
1055
|
+
try {
|
|
1056
|
+
const t = await reqObj.clone().text();
|
|
1057
|
+
if (t) reqBody = t.length > MAX_REQUEST_BODY ? t.slice(0, MAX_REQUEST_BODY) + "\u2026" : t;
|
|
1058
|
+
} catch {
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
let res;
|
|
1062
|
+
try {
|
|
1063
|
+
res = await origFetch.call(window, input, init2);
|
|
1064
|
+
} catch (err) {
|
|
1065
|
+
if (!shouldIgnore(url, blocked)) {
|
|
1066
|
+
push({
|
|
1067
|
+
method,
|
|
1068
|
+
url: truncateUrl(url),
|
|
1069
|
+
fullUrl: captureFullUrl(url),
|
|
1070
|
+
status: 0,
|
|
1071
|
+
duration: Date.now() - startTime,
|
|
1072
|
+
timestamp: startTime,
|
|
1073
|
+
source: "fetch",
|
|
1074
|
+
failed: true,
|
|
1075
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
1076
|
+
requestHeaders: reqHeaders,
|
|
1077
|
+
requestBody: reqBody,
|
|
1078
|
+
requestContentType: reqContentType
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
throw err;
|
|
1082
|
+
}
|
|
1048
1083
|
if (!shouldIgnore(url, blocked)) {
|
|
1049
1084
|
const entry = {
|
|
1050
1085
|
method,
|
|
1051
1086
|
url: truncateUrl(url),
|
|
1052
1087
|
fullUrl: captureFullUrl(url),
|
|
1053
1088
|
status: res.status,
|
|
1089
|
+
statusText: res.statusText || void 0,
|
|
1090
|
+
source: "fetch",
|
|
1054
1091
|
duration: Date.now() - startTime,
|
|
1055
1092
|
timestamp: startTime,
|
|
1056
1093
|
requestHeaders: reqHeaders,
|
|
@@ -1063,7 +1100,7 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1063
1100
|
try {
|
|
1064
1101
|
const clone = res.clone();
|
|
1065
1102
|
clone.text().then((text) => {
|
|
1066
|
-
entry.responseBody = text.length >
|
|
1103
|
+
entry.responseBody = text.length > maxResponseBody ? text.slice(0, maxResponseBody) + "\u2026" : text;
|
|
1067
1104
|
if (!entry.responseSize && text.length) entry.responseSize = text.length;
|
|
1068
1105
|
}).catch(() => {
|
|
1069
1106
|
});
|
|
@@ -1100,13 +1137,16 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1100
1137
|
XMLHttpRequest.prototype.open = function(method, url, async, username, password) {
|
|
1101
1138
|
const startTime = Date.now();
|
|
1102
1139
|
const urlStr = typeof url === "string" ? url : url.href;
|
|
1140
|
+
let captured = false;
|
|
1103
1141
|
this.addEventListener("load", () => {
|
|
1142
|
+
if (captured) return;
|
|
1143
|
+
captured = true;
|
|
1104
1144
|
if (!shouldIgnore(urlStr, blocked)) {
|
|
1105
1145
|
const meta = xhrMeta.get(this);
|
|
1106
1146
|
let resBody;
|
|
1107
1147
|
try {
|
|
1108
1148
|
const text = this.responseText;
|
|
1109
|
-
resBody = text && text.length >
|
|
1149
|
+
resBody = text && text.length > maxResponseBody ? text.slice(0, maxResponseBody) + "\u2026" : text || void 0;
|
|
1110
1150
|
} catch {
|
|
1111
1151
|
}
|
|
1112
1152
|
push({
|
|
@@ -1114,6 +1154,8 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1114
1154
|
url: truncateUrl(urlStr),
|
|
1115
1155
|
fullUrl: captureFullUrl(urlStr),
|
|
1116
1156
|
status: this.status,
|
|
1157
|
+
statusText: this.statusText || void 0,
|
|
1158
|
+
source: "xhr",
|
|
1117
1159
|
duration: Date.now() - startTime,
|
|
1118
1160
|
timestamp: startTime,
|
|
1119
1161
|
requestHeaders: meta?.reqHeaders && Object.keys(meta.reqHeaders).length > 0 ? meta.reqHeaders : void 0,
|
|
@@ -1126,8 +1168,58 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1126
1168
|
});
|
|
1127
1169
|
}
|
|
1128
1170
|
});
|
|
1171
|
+
const pushFailure = (errorMessage) => {
|
|
1172
|
+
if (captured) return;
|
|
1173
|
+
captured = true;
|
|
1174
|
+
if (shouldIgnore(urlStr, blocked)) return;
|
|
1175
|
+
const meta = xhrMeta.get(this);
|
|
1176
|
+
push({
|
|
1177
|
+
method: method.toUpperCase(),
|
|
1178
|
+
url: truncateUrl(urlStr),
|
|
1179
|
+
fullUrl: captureFullUrl(urlStr),
|
|
1180
|
+
status: 0,
|
|
1181
|
+
source: "xhr",
|
|
1182
|
+
failed: true,
|
|
1183
|
+
errorMessage,
|
|
1184
|
+
duration: Date.now() - startTime,
|
|
1185
|
+
timestamp: startTime,
|
|
1186
|
+
requestHeaders: meta?.reqHeaders && Object.keys(meta.reqHeaders).length > 0 ? meta.reqHeaders : void 0,
|
|
1187
|
+
requestBody: meta?.reqBody,
|
|
1188
|
+
requestContentType: meta?.reqContentType
|
|
1189
|
+
});
|
|
1190
|
+
};
|
|
1191
|
+
this.addEventListener("error", () => pushFailure("Network error"));
|
|
1192
|
+
this.addEventListener("timeout", () => pushFailure("Timeout"));
|
|
1193
|
+
this.addEventListener("abort", () => pushFailure("Aborted"));
|
|
1129
1194
|
return origXHROpen.apply(this, [method, url, async ?? true, username, password]);
|
|
1130
1195
|
};
|
|
1196
|
+
if (typeof PerformanceObserver !== "undefined") {
|
|
1197
|
+
try {
|
|
1198
|
+
perfObserver = new PerformanceObserver((list) => {
|
|
1199
|
+
for (const entry of list.getEntries()) {
|
|
1200
|
+
const res = entry;
|
|
1201
|
+
if (res.initiatorType !== "fetch" && res.initiatorType !== "xmlhttprequest") continue;
|
|
1202
|
+
const url = res.name;
|
|
1203
|
+
if (shouldIgnore(url, blocked)) continue;
|
|
1204
|
+
if (seenUrls.has(captureFullUrl(url)) || seenUrls.has(truncateUrl(url))) continue;
|
|
1205
|
+
push({
|
|
1206
|
+
// Resource timing does not expose the HTTP method; default to GET.
|
|
1207
|
+
method: "GET",
|
|
1208
|
+
url: truncateUrl(url),
|
|
1209
|
+
fullUrl: captureFullUrl(url),
|
|
1210
|
+
status: res.responseStatus ?? 0,
|
|
1211
|
+
source: "perf",
|
|
1212
|
+
duration: Math.round(res.duration),
|
|
1213
|
+
timestamp: Math.round(performance.timeOrigin + res.startTime),
|
|
1214
|
+
responseSize: res.transferSize || res.encodedBodySize || void 0
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
perfObserver.observe({ type: "resource", buffered: true });
|
|
1219
|
+
} catch {
|
|
1220
|
+
perfObserver = null;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1131
1223
|
},
|
|
1132
1224
|
stop() {
|
|
1133
1225
|
if (!active) return;
|
|
@@ -1136,6 +1228,10 @@ function createNetworkCollector(extraBlockedHosts = []) {
|
|
|
1136
1228
|
if (origXHROpen) XMLHttpRequest.prototype.open = origXHROpen;
|
|
1137
1229
|
if (origXHRSend) XMLHttpRequest.prototype.send = origXHRSend;
|
|
1138
1230
|
if (origXHRSetHeader) XMLHttpRequest.prototype.setRequestHeader = origXHRSetHeader;
|
|
1231
|
+
if (perfObserver) {
|
|
1232
|
+
perfObserver.disconnect();
|
|
1233
|
+
perfObserver = null;
|
|
1234
|
+
}
|
|
1139
1235
|
},
|
|
1140
1236
|
getEntries() {
|
|
1141
1237
|
return [...entries];
|