@sailfish-ai/recorder 1.1.2 → 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 +53 -29
- 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,41 +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
|
-
const originalOpen = XMLHttpRequest.prototype.open;
|
|
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
|
-
XMLHttpRequest.prototype.open = function (...args) {
|
|
153
|
-
this._url = args[1]; // Store the request URL
|
|
154
|
-
originalOpen.apply(this, args);
|
|
155
|
-
};
|
|
156
161
|
XMLHttpRequest.prototype.send = function (...args) {
|
|
157
162
|
const url = this._url;
|
|
158
|
-
// Check if URL matches
|
|
163
|
+
// Check if URL matches the propagation and exclusion patterns
|
|
159
164
|
const shouldSkipHeader = matchUrlWithWildcard(url, combinedIgnoreDomains);
|
|
160
|
-
|
|
165
|
+
const shouldPropagateHeader = domainsToPropagateHeadersTo.length === 0 ||
|
|
166
|
+
matchUrlWithWildcard(url, domainsToPropagateHeadersTo);
|
|
167
|
+
if (sessionId && shouldPropagateHeader && !shouldSkipHeader) {
|
|
161
168
|
this.setRequestHeader("X-Sf3-Rid", sessionId);
|
|
162
169
|
}
|
|
163
170
|
originalSend.apply(this, args);
|
|
164
171
|
};
|
|
165
172
|
}
|
|
166
173
|
// Updated fetch interceptor with single check function
|
|
167
|
-
function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
|
|
174
|
+
function setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeadersTo = []) {
|
|
168
175
|
const originalFetch = window.fetch;
|
|
169
176
|
const sessionId = getOrSetSessionId();
|
|
170
|
-
// Combine default and passed domains
|
|
177
|
+
// Combine default and passed ignore domains
|
|
171
178
|
const combinedIgnoreDomains = [
|
|
172
179
|
...DOMAINS_TO_NOT_PROPAGATE_HEADER_TO_DEFAULT,
|
|
173
180
|
...domainsToNotPropagateHeaderTo,
|
|
174
181
|
];
|
|
175
|
-
window.fetch =
|
|
182
|
+
window.fetch = function (input, init) {
|
|
176
183
|
let url;
|
|
177
|
-
// Check if input is a string (URL) or a Request object
|
|
178
184
|
if (typeof input === "string") {
|
|
179
185
|
url = input;
|
|
180
186
|
}
|
|
@@ -182,30 +188,48 @@ function setupFetchInterceptor(domainsToNotPropagateHeaderTo) {
|
|
|
182
188
|
url = input.url;
|
|
183
189
|
}
|
|
184
190
|
else {
|
|
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
|
-
|
|
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) {
|
|
199
|
+
if (input instanceof Request) {
|
|
200
|
+
const clonedRequest = input.clone();
|
|
201
|
+
const newHeaders = new Headers(clonedRequest.headers);
|
|
202
|
+
newHeaders.set("X-Sf3-Rid", sessionId);
|
|
203
|
+
const modifiedRequest = new Request(clonedRequest, {
|
|
204
|
+
headers: newHeaders,
|
|
205
|
+
});
|
|
206
|
+
return originalFetch.call(this, modifiedRequest);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const modifiedInit = { ...init };
|
|
210
|
+
const newHeaders = new Headers(init?.headers || {});
|
|
211
|
+
newHeaders.set("X-Sf3-Rid", sessionId);
|
|
212
|
+
modifiedInit.headers = newHeaders;
|
|
213
|
+
return originalFetch.call(this, input, modifiedInit);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
return originalFetch.apply(this, arguments);
|
|
194
218
|
}
|
|
195
|
-
return originalFetch(input, init);
|
|
196
219
|
};
|
|
197
220
|
}
|
|
198
221
|
// Main Recording Function
|
|
199
|
-
|
|
222
|
+
// Main Recording Function
|
|
223
|
+
export async function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo = [], domainsToNotPropagateHeaderTo = [], }) {
|
|
200
224
|
let sessionId = getOrSetSessionId();
|
|
201
225
|
storeCredentialsAndConnection({ apiKey, backendApi });
|
|
202
226
|
// Non-blocking GraphQL request to send the domains if provided
|
|
203
227
|
if (domainsToNotPropagateHeaderTo.length > 0) {
|
|
204
228
|
sendDomainsToNotPropagateHeaderTo(apiKey, domainsToNotPropagateHeaderTo, backendApi).catch((error) => console.error("Failed to send domains to not propagate header to:", error));
|
|
205
229
|
}
|
|
206
|
-
// Setup interceptors with custom ignore domains
|
|
207
|
-
setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo);
|
|
208
|
-
setupFetchInterceptor(domainsToNotPropagateHeaderTo);
|
|
230
|
+
// Setup interceptors with custom ignore and propagate domains
|
|
231
|
+
setupXMLHttpRequestInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
|
|
232
|
+
setupFetchInterceptor(domainsToNotPropagateHeaderTo, domainsToPropagateHeaderTo);
|
|
209
233
|
gatherAndCacheDeviceInfo();
|
|
210
234
|
try {
|
|
211
235
|
const captureSettingsResponse = await fetchCaptureSettings(apiKey, backendApi);
|