@sailfish-ai/recorder 1.1.3 → 1.2.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/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # JS/TS Record-Only Package
2
2
 
3
- ## TODO - Rename all Sailfish to GrepLion
3
+ ## TODO - Rename all Sailfish to GrepLion!
package/dist/index.js CHANGED
@@ -92,15 +92,22 @@ function storeCredentialsAndConnection({ apiKey, backendApi, }) {
92
92
  }
93
93
  // Utility function to match domains or paths with wildcard support
94
94
  export function matchUrlWithWildcard(url, patterns) {
95
- // Strip any protocol (e.g., http, https, ws, wss, ftp, etc.) from the URL
96
95
  const strippedUrl = url.replace(/^[a-zA-Z]+:\/\//, "");
97
96
  const parsedUrl = new URL("http://" + strippedUrl); // Add a dummy protocol for URL parsing
98
- const { hostname, pathname } = parsedUrl;
99
- const domain = hostname.toLowerCase();
97
+ const { hostname, pathname, port } = parsedUrl;
98
+ // Handle stripping 'www.' and port
99
+ const domain = hostname.startsWith("www.")
100
+ ? hostname.slice(4).toLowerCase()
101
+ : hostname.toLowerCase();
100
102
  return patterns.some((pattern) => {
101
- // Strip any protocol from the pattern
103
+ // Strip any protocol and handle port in the pattern if present
102
104
  const strippedPattern = pattern.replace(/^[a-zA-Z]+:\/\//, "");
103
105
  let [patternDomain, patternPath] = strippedPattern.split("/", 2);
106
+ // Handle port in pattern
107
+ let patternPort = "";
108
+ if (patternDomain.includes(":")) {
109
+ [patternDomain, patternPort] = patternDomain.split(":");
110
+ }
104
111
  // Handle domain wildcards
105
112
  const normalizedPatternDomain = patternDomain
106
113
  .replace(/\./g, "\\.") // Escape dots for regex
@@ -109,6 +116,10 @@ export function matchUrlWithWildcard(url, patterns) {
109
116
  const domainRegex = new RegExp(`^${normalizedPatternDomain}$`, "i");
110
117
  // Strip 'www.' from both the input domain and the pattern domain for comparison
111
118
  const strippedDomain = domain.startsWith("www.") ? domain.slice(4) : domain;
119
+ // If pattern specifies a port, match the exact port
120
+ if (patternPort && port !== patternPort) {
121
+ return false;
122
+ }
112
123
  // Handle subdomain wildcard (*.) to match both base and subdomains
113
124
  if (patternDomain.startsWith("*.") &&
114
125
  (domain === patternDomain.slice(2) ||
@@ -140,40 +151,36 @@ export function matchUrlWithWildcard(url, patterns) {
140
151
  });
141
152
  }
142
153
  // Updated XMLHttpRequest interceptor with single check function
143
- function setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo) {
144
- // Store references to the original (or patched) send method
154
+ function setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
145
155
  const originalSend = XMLHttpRequest.prototype.send;
146
156
  const sessionId = getOrSetSessionId();
147
- // Combine default and passed domains
148
157
  const combinedIgnoreDomains = [
149
158
  ...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
150
159
  ...domainsToNotPropagateHeaderTo,
151
160
  ];
152
- // Override XMLHttpRequest's send method
153
161
  XMLHttpRequest.prototype.send = function (...args) {
154
162
  const url = this._url;
155
- // Check if URL matches any domain or path pattern
163
+ // Check if URL matches the propagation and exclusion patterns
156
164
  const shouldSkipHeader = matchUrlWithWildcard(url, combinedIgnoreDomains);
157
- if (sessionId && !shouldSkipHeader) {
165
+ const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
166
+ matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
167
+ if (sessionId && shouldPropagateHeader && !shouldSkipHeader) {
158
168
  this.setRequestHeader("X-Sf3-Rid", sessionId);
159
169
  }
160
170
  originalSend.apply(this, args);
161
171
  };
162
172
  }
163
173
  // Updated fetch interceptor with single check function
164
- function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
165
- // Store a reference to the original fetch function
174
+ function setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
166
175
  const originalFetch = window.fetch;
167
176
  const sessionId = getOrSetSessionId();
168
- // Combine default and passed domains
177
+ // Combine default and passed ignore domains
169
178
  const combinedIgnoreDomains = [
170
179
  ...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
171
180
  ...domainsToNotPropagateHeaderTo,
172
181
  ];
173
- // Define our fetch wrapper
174
182
  window.fetch = function (input, init) {
175
183
  let url;
176
- // Determine the URL based on input type
177
184
  if (typeof input === "string") {
178
185
  url = input;
179
186
  }
@@ -181,60 +188,48 @@ function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
181
188
  url = input.url;
182
189
  }
183
190
  else {
184
- // Unknown input type; defer to the original fetch
185
191
  return originalFetch.apply(this, arguments);
186
192
  }
187
- // Check if URL matches any domain or path pattern
193
+ // Check if URL matches the propagation and exclusion patterns
188
194
  const shouldSkipHeader = matchUrlWithWildcard(url, combinedIgnoreDomains);
189
- // Use the original fetch if the domain matches the ignore patterns
190
- if (shouldSkipHeader) {
191
- // Call the original fetch with the original arguments
192
- return originalFetch.apply(this, arguments);
193
- }
194
- // Only modify the request if we need to add the header
195
- if (sessionId) {
195
+ const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
196
+ matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
197
+ // Proceed with fetch if header should propagate and not be excluded
198
+ if (sessionId && shouldPropagateHeader && !shouldSkipHeader) {
196
199
  if (input instanceof Request) {
197
- // Clone the original request
198
200
  const clonedRequest = input.clone();
199
- // Clone the headers and add the custom header
200
201
  const newHeaders = new Headers(clonedRequest.headers);
201
202
  newHeaders.set("X-Sf3-Rid", sessionId);
202
- // Create a new Request with the modified headers
203
203
  const modifiedRequest = new Request(clonedRequest, {
204
204
  headers: newHeaders,
205
205
  });
206
- // Call the original fetch with the modified Request
207
206
  return originalFetch.call(this, modifiedRequest);
208
207
  }
209
208
  else {
210
- // Input is a URL string
211
- // Clone and modify the init object
212
209
  const modifiedInit = { ...init };
213
- // Clone the headers
214
210
  const newHeaders = new Headers(init?.headers || {});
215
211
  newHeaders.set("X-Sf3-Rid", sessionId);
216
212
  modifiedInit.headers = newHeaders;
217
- // Call the original fetch with the modified init
218
213
  return originalFetch.call(this, input, modifiedInit);
219
214
  }
220
215
  }
221
216
  else {
222
- // No sessionId; call the original fetch
223
217
  return originalFetch.apply(this, arguments);
224
218
  }
225
219
  };
226
220
  }
227
221
  // Main Recording Function
228
- export async function startRecording({ apiKey, backendApi, domainsToNotPropagateHeaderTo = [], }) {
222
+ // Main Recording Function
223
+ export async function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo = [], domainsToNotPropagateHeaderTo = [], }) {
229
224
  let sessionId = getOrSetSessionId();
230
225
  storeCredentialsAndConnection({ apiKey, backendApi });
231
226
  // Non-blocking GraphQL request to send the domains if provided
232
227
  if (domainsToNotPropagateHeaderTo.length > 0) {
233
228
  sendDomainsToNotPropagateHeaderTo(apiKey, domainsToNotPropagateHeaderTo, backendApi).catch((error) => console.error("Failed to send domains to not propagate header to:", error));
234
229
  }
235
- // Setup interceptors with custom ignore domains
236
- setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo);
237
- setupFetchInterceptor(domainsToNotPropagateHeaderTo);
230
+ // Setup interceptors with custom ignore and propagate domains
231
+ setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
232
+ setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
238
233
  gatherAndCacheDeviceInfo();
239
234
  try {
240
235
  const captureSettingsResponse = await fetchCaptureSettings(apiKey, backendApi);