@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 +1 -1
- package/dist/index.js +32 -37
- 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/README.md
CHANGED
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
|
-
|
|
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
|
|
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
|
|
163
|
+
// Check if URL matches the propagation and exclusion patterns
|
|
156
164
|
const shouldSkipHeader = matchUrlWithWildcard(url, combinedIgnoreDomains);
|
|
157
|
-
|
|
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
|
|
193
|
+
// Check if URL matches the propagation and exclusion patterns
|
|
188
194
|
const shouldSkipHeader = matchUrlWithWildcard(url, combinedIgnoreDomains);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
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);
|