@sailfish-ai/recorder 1.1.3 → 1.2.1
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 +47 -40
- package/dist/sailfish-recorder.cjs.js +1 -1
- package/dist/sailfish-recorder.cjs.js.br +0 -0
- package/dist/sailfish-recorder.cjs.js.gz +0 -0
- package/dist/sailfish-recorder.es.js +1 -1
- package/dist/sailfish-recorder.es.js.br +0 -0
- package/dist/sailfish-recorder.es.js.gz +0 -0
- package/dist/sailfish-recorder.umd.js +1 -1
- package/dist/sailfish-recorder.umd.js.br +0 -0
- package/dist/sailfish-recorder.umd.js.gz +0 -0
- package/dist/types/index.d.ts +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fetchCaptureSettings, sendDomainsToNotPropagateHeaderTo, startRecording
|
|
|
6
6
|
import { initializeRecording } from "./recording";
|
|
7
7
|
// Default list of domains to ignore
|
|
8
8
|
const DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT = [
|
|
9
|
+
"t.co",
|
|
9
10
|
"identitytoolkit.googleapis.com",
|
|
10
11
|
];
|
|
11
12
|
const DOMAINS_TO_NOT_RECORD_NETWORK_REQUESTS_TO = [];
|
|
@@ -92,15 +93,27 @@ function storeCredentialsAndConnection({ apiKey, backendApi, }) {
|
|
|
92
93
|
}
|
|
93
94
|
// Utility function to match domains or paths with wildcard support
|
|
94
95
|
export function matchUrlWithWildcard(url, patterns) {
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
if (!url || typeof url !== "string") {
|
|
97
|
+
throw new Error("Invalid URL input");
|
|
98
|
+
}
|
|
99
|
+
// Ensure the URL has a protocol. If not, prepend "http://"
|
|
100
|
+
const formattedUrl = url.match(/^[a-zA-Z]+:\/\//) ? url : `http://${url}`;
|
|
101
|
+
const strippedUrl = formattedUrl.replace(/^[a-zA-Z]+:\/\//, "");
|
|
97
102
|
const parsedUrl = new URL("http://" + strippedUrl); // Add a dummy protocol for URL parsing
|
|
98
|
-
const { hostname, pathname } = parsedUrl;
|
|
99
|
-
|
|
103
|
+
const { hostname, pathname, port } = parsedUrl;
|
|
104
|
+
// Handle stripping 'www.' and port
|
|
105
|
+
const domain = hostname.startsWith("www.")
|
|
106
|
+
? hostname.slice(4).toLowerCase()
|
|
107
|
+
: hostname.toLowerCase();
|
|
100
108
|
return patterns.some((pattern) => {
|
|
101
|
-
// Strip any protocol
|
|
109
|
+
// Strip any protocol and handle port in the pattern if present
|
|
102
110
|
const strippedPattern = pattern.replace(/^[a-zA-Z]+:\/\//, "");
|
|
103
111
|
let [patternDomain, patternPath] = strippedPattern.split("/", 2);
|
|
112
|
+
// Handle port in pattern
|
|
113
|
+
let patternPort = "";
|
|
114
|
+
if (patternDomain.includes(":")) {
|
|
115
|
+
[patternDomain, patternPort] = patternDomain.split(":");
|
|
116
|
+
}
|
|
104
117
|
// Handle domain wildcards
|
|
105
118
|
const normalizedPatternDomain = patternDomain
|
|
106
119
|
.replace(/\./g, "\\.") // Escape dots for regex
|
|
@@ -109,6 +122,10 @@ export function matchUrlWithWildcard(url, patterns) {
|
|
|
109
122
|
const domainRegex = new RegExp(`^${normalizedPatternDomain}$`, "i");
|
|
110
123
|
// Strip 'www.' from both the input domain and the pattern domain for comparison
|
|
111
124
|
const strippedDomain = domain.startsWith("www.") ? domain.slice(4) : domain;
|
|
125
|
+
// If pattern specifies a port, match the exact port
|
|
126
|
+
if (patternPort && port !== patternPort) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
112
129
|
// Handle subdomain wildcard (*.) to match both base and subdomains
|
|
113
130
|
if (patternDomain.startsWith("*.") &&
|
|
114
131
|
(domain === patternDomain.slice(2) ||
|
|
@@ -140,40 +157,41 @@ export function matchUrlWithWildcard(url, patterns) {
|
|
|
140
157
|
});
|
|
141
158
|
}
|
|
142
159
|
// Updated XMLHttpRequest interceptor with single check function
|
|
143
|
-
|
|
144
|
-
|
|
160
|
+
// Updated XMLHttpRequest interceptor to bypass for CORS-sensitive domains
|
|
161
|
+
function setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
|
|
145
162
|
const originalSend = XMLHttpRequest.prototype.send;
|
|
146
163
|
const sessionId = getOrSetSessionId();
|
|
147
|
-
// Combine default and passed domains
|
|
164
|
+
// Combine default and passed ignore domains
|
|
148
165
|
const combinedIgnoreDomains = [
|
|
149
166
|
...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
|
|
150
167
|
...domainsToNotPropagateHeaderTo,
|
|
151
168
|
];
|
|
152
|
-
// Override XMLHttpRequest's send method
|
|
153
169
|
XMLHttpRequest.prototype.send = function (...args) {
|
|
154
170
|
const url = this._url;
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
171
|
+
// Bypass logic for domains listed in the combinedIgnoreDomains
|
|
172
|
+
if (matchUrlWithWildcard(url, combinedIgnoreDomains)) {
|
|
173
|
+
return originalSend.apply(this, args);
|
|
174
|
+
}
|
|
175
|
+
// Check if the domain should propagate headers
|
|
176
|
+
const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
|
|
177
|
+
matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
|
|
178
|
+
if (sessionId && shouldPropagateHeader) {
|
|
158
179
|
this.setRequestHeader("X-Sf3-Rid", sessionId);
|
|
159
180
|
}
|
|
160
|
-
originalSend.apply(this, args);
|
|
181
|
+
return originalSend.apply(this, args);
|
|
161
182
|
};
|
|
162
183
|
}
|
|
163
|
-
// Updated fetch interceptor
|
|
164
|
-
function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
|
|
165
|
-
// Store a reference to the original fetch function
|
|
184
|
+
// Updated fetch interceptor to bypass for CORS-sensitive domains
|
|
185
|
+
function setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
|
|
166
186
|
const originalFetch = window.fetch;
|
|
167
187
|
const sessionId = getOrSetSessionId();
|
|
168
|
-
// Combine default and passed domains
|
|
188
|
+
// Combine default and passed ignore domains
|
|
169
189
|
const combinedIgnoreDomains = [
|
|
170
190
|
...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
|
|
171
191
|
...domainsToNotPropagateHeaderTo,
|
|
172
192
|
];
|
|
173
|
-
// Define our fetch wrapper
|
|
174
193
|
window.fetch = function (input, init) {
|
|
175
194
|
let url;
|
|
176
|
-
// Determine the URL based on input type
|
|
177
195
|
if (typeof input === "string") {
|
|
178
196
|
url = input;
|
|
179
197
|
}
|
|
@@ -181,60 +199,49 @@ function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
|
|
|
181
199
|
url = input.url;
|
|
182
200
|
}
|
|
183
201
|
else {
|
|
184
|
-
// Unknown input type; defer to the original fetch
|
|
185
202
|
return originalFetch.apply(this, arguments);
|
|
186
203
|
}
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
// Use the original fetch if the domain matches the ignore patterns
|
|
190
|
-
if (shouldSkipHeader) {
|
|
191
|
-
// Call the original fetch with the original arguments
|
|
204
|
+
// Bypass logic for domains listed in the combinedIgnoreDomains
|
|
205
|
+
if (matchUrlWithWildcard(url, combinedIgnoreDomains)) {
|
|
192
206
|
return originalFetch.apply(this, arguments);
|
|
193
207
|
}
|
|
194
|
-
//
|
|
195
|
-
|
|
208
|
+
// Check if the domain should propagate headers
|
|
209
|
+
const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
|
|
210
|
+
matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
|
|
211
|
+
if (sessionId && shouldPropagateHeader) {
|
|
196
212
|
if (input instanceof Request) {
|
|
197
|
-
// Clone the original request
|
|
198
213
|
const clonedRequest = input.clone();
|
|
199
|
-
// Clone the headers and add the custom header
|
|
200
214
|
const newHeaders = new Headers(clonedRequest.headers);
|
|
201
215
|
newHeaders.set("X-Sf3-Rid", sessionId);
|
|
202
|
-
// Create a new Request with the modified headers
|
|
203
216
|
const modifiedRequest = new Request(clonedRequest, {
|
|
204
217
|
headers: newHeaders,
|
|
205
218
|
});
|
|
206
|
-
// Call the original fetch with the modified Request
|
|
207
219
|
return originalFetch.call(this, modifiedRequest);
|
|
208
220
|
}
|
|
209
221
|
else {
|
|
210
|
-
// Input is a URL string
|
|
211
|
-
// Clone and modify the init object
|
|
212
222
|
const modifiedInit = { ...init };
|
|
213
|
-
// Clone the headers
|
|
214
223
|
const newHeaders = new Headers(init?.headers || {});
|
|
215
224
|
newHeaders.set("X-Sf3-Rid", sessionId);
|
|
216
225
|
modifiedInit.headers = newHeaders;
|
|
217
|
-
// Call the original fetch with the modified init
|
|
218
226
|
return originalFetch.call(this, input, modifiedInit);
|
|
219
227
|
}
|
|
220
228
|
}
|
|
221
229
|
else {
|
|
222
|
-
// No sessionId; call the original fetch
|
|
223
230
|
return originalFetch.apply(this, arguments);
|
|
224
231
|
}
|
|
225
232
|
};
|
|
226
233
|
}
|
|
227
234
|
// Main Recording Function
|
|
228
|
-
export async function startRecording({ apiKey, backendApi, domainsToNotPropagateHeaderTo = [], }) {
|
|
235
|
+
export async function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo = [], domainsToNotPropagateHeaderTo = [], }) {
|
|
229
236
|
let sessionId = getOrSetSessionId();
|
|
230
237
|
storeCredentialsAndConnection({ apiKey, backendApi });
|
|
231
238
|
// Non-blocking GraphQL request to send the domains if provided
|
|
232
239
|
if (domainsToNotPropagateHeaderTo.length > 0) {
|
|
233
240
|
sendDomainsToNotPropagateHeaderTo(apiKey, domainsToNotPropagateHeaderTo, backendApi).catch((error) => console.error("Failed to send domains to not propagate header to:", error));
|
|
234
241
|
}
|
|
235
|
-
// Setup interceptors with custom ignore domains
|
|
236
|
-
setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo);
|
|
237
|
-
setupFetchInterceptor(domainsToNotPropagateHeaderTo);
|
|
242
|
+
// Setup interceptors with custom ignore and propagate domains
|
|
243
|
+
setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
|
|
244
|
+
setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
|
|
238
245
|
gatherAndCacheDeviceInfo();
|
|
239
246
|
try {
|
|
240
247
|
const captureSettingsResponse = await fetchCaptureSettings(apiKey, backendApi);
|