@sailfish-ai/recorder 1.2.4 → 1.2.5

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.js CHANGED
@@ -200,14 +200,30 @@ function setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsTo
200
200
  };
201
201
  }
202
202
  // Updated fetch interceptor to bypass for CORS-sensitive domains
203
- function setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
203
+ function setupFetchInterceptor(domainsToNotPatchFetchFor, domainsToPropagateHeadersTo = []) {
204
204
  const originalFetch = window.fetch;
205
205
  const sessionId = getOrSetSessionId();
206
206
  // Combine default and passed ignore domains
207
207
  const combinedIgnoreDomains = [
208
208
  ...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
209
- ...domainsToNotPropagateHeaderTo,
209
+ ...domainsToNotPatchFetchFor,
210
210
  ];
211
+ // Cache results of domain checks to reduce performance overhead
212
+ const cache = new Map();
213
+ // Function to check if the input is a non-standard fetch input (Blob, FormData, etc.)
214
+ function isNonStandardRequestInfo(input) {
215
+ return (input instanceof Blob ||
216
+ input instanceof FormData ||
217
+ input instanceof ArrayBuffer);
218
+ }
219
+ // Function to check if fetch is polyfilled (e.g., in older browsers or Node.js)
220
+ function isPolyfilledFetch() {
221
+ return !window.fetch.toString().includes("[native code]");
222
+ }
223
+ // Log a warning if fetch is polyfilled
224
+ if (isPolyfilledFetch()) {
225
+ console.log("Fetch is polyfilled, behavior may differ from native fetch.");
226
+ }
211
227
  // Proxy to conditionally intercept fetch based on domains
212
228
  window.fetch = new Proxy(originalFetch, {
213
229
  apply: (target, thisArg, args) => {
@@ -224,46 +240,80 @@ function setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagate
224
240
  else if (input instanceof URL) {
225
241
  url = input.href;
226
242
  }
227
- else {
228
- // Unsupported type, skip interception
229
- console.warn("Unsupported input type for fetch:", input);
243
+ else if (isNonStandardRequestInfo(input)) {
244
+ // Pass through non-standard inputs like Blob, FormData, etc.
230
245
  return target.apply(thisArg, args);
231
246
  }
232
- // ** Check if we should skip patching fetch entirely for this domain **
233
- if (matchUrlWithWildcard(url, combinedIgnoreDomains)) {
247
+ else {
248
+ // Unsupported input type, skip interception
249
+ console.warn("Unsupported input type for fetch:", input);
234
250
  return target.apply(thisArg, args);
235
251
  }
236
- // Check if the domain should propagate the header
237
- const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
238
- matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
239
- // ** Skip CORS-sensitive requests **
240
- // Ensure we don't modify headers for cross-origin requests to non-whitelisted domains
241
- if (!shouldPropagateHeader) {
242
- return target.apply(thisArg, args);
252
+ // Check the cache for domain results to avoid redundant checks
253
+ if (cache.has(url)) {
254
+ const cachedResult = cache.get(url);
255
+ if (cachedResult === "ignore") {
256
+ return target.apply(thisArg, args);
257
+ }
258
+ if (cachedResult === "propagate") {
259
+ return injectHeader(target, thisArg, args, input, init, sessionId);
260
+ }
243
261
  }
244
- // ** Add X-Sf3-Rid header if needed **
245
- if (sessionId && shouldPropagateHeader) {
246
- if (input instanceof Request) {
247
- const clonedRequest = input.clone();
248
- const newHeaders = new Headers(clonedRequest.headers);
249
- newHeaders.set("X-Sf3-Rid", sessionId);
250
- const modifiedRequest = new Request(clonedRequest, {
251
- headers: newHeaders,
252
- });
253
- return target.call(thisArg, modifiedRequest, init);
262
+ // ** Security Restriction Handling **
263
+ try {
264
+ // ** Check if we should skip patching fetch entirely for this domain **
265
+ if (matchUrlWithWildcard(url, combinedIgnoreDomains)) {
266
+ // Cache the result for this domain to avoid future checks
267
+ cache.set(url, "ignore");
268
+ return target.apply(thisArg, args);
254
269
  }
255
- else {
256
- const modifiedInit = { ...init };
257
- const newHeaders = new Headers(init.headers || {});
258
- newHeaders.set("X-Sf3-Rid", sessionId);
259
- modifiedInit.headers = newHeaders;
260
- return target.call(thisArg, input, modifiedInit);
270
+ // Check if the domain should propagate the header
271
+ const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
272
+ matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
273
+ // ** Skip CORS-sensitive requests **
274
+ if (!shouldPropagateHeader) {
275
+ // Cache the result for this domain to avoid future checks
276
+ cache.set(url, "ignore");
277
+ return target.apply(thisArg, args);
261
278
  }
279
+ // Cache the result for this domain
280
+ cache.set(url, "propagate");
281
+ // ** Proceed to inject X-Sf3-Rid header **
282
+ return injectHeader(target, thisArg, args, input, init, sessionId);
283
+ }
284
+ catch (error) {
285
+ // ** Handle security restrictions and fallback to the original fetch **
286
+ console.error("Failed to intercept fetch due to security restrictions:", error);
287
+ return target.apply(thisArg, args);
262
288
  }
263
- // If no header propagation, return the original fetch call
264
- return target.apply(thisArg, args);
265
289
  },
266
290
  });
291
+ // Helper function to inject the X-Sf3-Rid header
292
+ function injectHeader(target, thisArg, args, input, init, sessionId) {
293
+ if (sessionId) {
294
+ if (input instanceof Request) {
295
+ // Clone the Request and modify headers
296
+ const clonedRequest = input.clone();
297
+ const newHeaders = new Headers(clonedRequest.headers);
298
+ newHeaders.set("X-Sf3-Rid", sessionId);
299
+ const modifiedRequest = new Request(clonedRequest, {
300
+ headers: newHeaders,
301
+ });
302
+ return target.call(thisArg, modifiedRequest, init);
303
+ }
304
+ else {
305
+ // For string or URL input, modify init to add headers
306
+ const modifiedInit = { ...init };
307
+ const newHeaders = new Headers(init.headers || {});
308
+ newHeaders.set("X-Sf3-Rid", sessionId);
309
+ modifiedInit.headers = newHeaders;
310
+ return target.call(thisArg, input, modifiedInit);
311
+ }
312
+ }
313
+ else {
314
+ return target.apply(thisArg, args);
315
+ }
316
+ }
267
317
  }
268
318
  // Main Recording Function
269
319
  export async function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo = [], domainsToNotPropagateHeaderTo = [], }) {