@buoy-gg/impersonate 7.0.41 → 7.0.43
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 +12 -80
- package/lib/commonjs/impersonate/components/DataNukeSettings.js +8 -675
- package/lib/commonjs/impersonate/components/ImpersonateBanner.js +1 -221
- package/lib/commonjs/impersonate/components/ImpersonateHistoryList.js +1 -181
- package/lib/commonjs/impersonate/components/ImpersonateModal.js +1 -319
- package/lib/commonjs/impersonate/components/ImpersonateOverlay.js +1 -26
- package/lib/commonjs/impersonate/components/ImpersonateStatusBar.js +1 -130
- package/lib/commonjs/impersonate/components/UserAvatar.js +1 -146
- package/lib/commonjs/impersonate/components/UserCard.js +1 -201
- package/lib/commonjs/impersonate/components/UserSearchView.js +1 -227
- package/lib/commonjs/impersonate/hooks/asyncStoragePeer.js +1 -17
- package/lib/commonjs/impersonate/hooks/asyncStoragePeer.web.js +1 -11
- package/lib/commonjs/impersonate/hooks/useAutoClearAsyncStorage.js +1 -134
- package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.js +1 -155
- package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.web.js +1 -20
- package/lib/commonjs/impersonate/hooks/useAutoClearRedux.js +1 -188
- package/lib/commonjs/impersonate/hooks/useAutoClearRedux.web.js +1 -27
- package/lib/commonjs/impersonate/hooks/useImpersonate.js +1 -215
- package/lib/commonjs/impersonate/hooks/useImpersonateHistory.js +1 -56
- package/lib/commonjs/impersonate/types/index.js +1 -16
- package/lib/commonjs/impersonate/types/types.js +1 -1
- package/lib/commonjs/impersonate/utils/impersonateListener.js +1 -350
- package/lib/commonjs/impersonate/utils/impersonateStore.js +1 -689
- package/lib/commonjs/index.js +1 -150
- package/lib/commonjs/preset.js +1 -232
- package/lib/commonjs/sync/impersonateSyncAdapter.js +1 -170
- package/lib/module/impersonate/components/DataNukeSettings.js +8 -670
- package/lib/module/impersonate/components/ImpersonateBanner.js +1 -215
- package/lib/module/impersonate/components/ImpersonateHistoryList.js +1 -176
- package/lib/module/impersonate/components/ImpersonateModal.js +1 -314
- package/lib/module/impersonate/components/ImpersonateOverlay.js +1 -21
- package/lib/module/impersonate/components/ImpersonateStatusBar.js +1 -125
- package/lib/module/impersonate/components/UserAvatar.js +1 -140
- package/lib/module/impersonate/components/UserCard.js +1 -196
- package/lib/module/impersonate/components/UserSearchView.js +1 -222
- package/lib/module/impersonate/hooks/asyncStoragePeer.js +1 -13
- package/lib/module/impersonate/hooks/asyncStoragePeer.web.js +1 -6
- package/lib/module/impersonate/hooks/useAutoClearAsyncStorage.js +1 -130
- package/lib/module/impersonate/hooks/useAutoClearReactQuery.js +1 -151
- package/lib/module/impersonate/hooks/useAutoClearReactQuery.web.js +1 -16
- package/lib/module/impersonate/hooks/useAutoClearRedux.js +1 -183
- package/lib/module/impersonate/hooks/useAutoClearRedux.web.js +1 -22
- package/lib/module/impersonate/hooks/useImpersonate.js +1 -212
- package/lib/module/impersonate/hooks/useImpersonateHistory.js +1 -52
- package/lib/module/impersonate/types/index.js +1 -3
- package/lib/module/impersonate/types/types.js +1 -1
- package/lib/module/impersonate/utils/impersonateListener.js +1 -341
- package/lib/module/impersonate/utils/impersonateStore.js +1 -686
- package/lib/module/index.js +1 -117
- package/lib/module/preset.js +1 -216
- package/lib/module/sync/impersonateSyncAdapter.js +1 -162
- package/lib/web/index.mjs +7 -8
- package/package.json +3 -6
- package/lib/typescript/impersonate/components/DataNukeSettings.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/ImpersonateBanner.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/ImpersonateHistoryList.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/ImpersonateModal.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/ImpersonateOverlay.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/ImpersonateStatusBar.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/UserAvatar.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/UserCard.d.ts.map +0 -1
- package/lib/typescript/impersonate/components/UserSearchView.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.web.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.web.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useAutoClearRedux.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useAutoClearRedux.web.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useImpersonate.d.ts.map +0 -1
- package/lib/typescript/impersonate/hooks/useImpersonateHistory.d.ts.map +0 -1
- package/lib/typescript/impersonate/types/index.d.ts.map +0 -1
- package/lib/typescript/impersonate/types/types.d.ts.map +0 -1
- package/lib/typescript/impersonate/utils/impersonateListener.d.ts.map +0 -1
- package/lib/typescript/impersonate/utils/impersonateStore.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/sync/impersonateSyncAdapter.d.ts.map +0 -1
|
@@ -1,16 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var _types = require("./types");
|
|
7
|
-
Object.keys(_types).forEach(function (key) {
|
|
8
|
-
if (key === "default" || key === "__esModule") return;
|
|
9
|
-
if (key in exports && exports[key] === _types[key]) return;
|
|
10
|
-
Object.defineProperty(exports, key, {
|
|
11
|
-
enumerable: true,
|
|
12
|
-
get: function () {
|
|
13
|
-
return _types[key];
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _types=require("./types");Object.keys(_types).forEach(function(e){if(e==="default"||e==="__esModule")return;if(e in exports&&exports[e]===_types[e])return;Object.defineProperty(exports,e,{enumerable:true,get:function(){return _types[e]}})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
@@ -1,350 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getImpersonatedUserId = getImpersonatedUserId;
|
|
7
|
-
exports.impersonateListener = impersonateListener;
|
|
8
|
-
exports.isImpersonating = isImpersonating;
|
|
9
|
-
exports.setImpersonateConfig = setImpersonateConfig;
|
|
10
|
-
exports.startImpersonateListener = startImpersonateListener;
|
|
11
|
-
exports.stopImpersonateListener = stopImpersonateListener;
|
|
12
|
-
/**
|
|
13
|
-
* Impersonate Listener - Header Injection via Fetch/XHR Monkey-Patching
|
|
14
|
-
*
|
|
15
|
-
* This module intercepts all network requests and injects the impersonation
|
|
16
|
-
* header when impersonation is active. It follows the same singleton pattern
|
|
17
|
-
* as @buoy-gg/network's networkListener.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
// Extended XMLHttpRequest interface for tracking URL
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Default URL patterns to ignore (won't inject header)
|
|
24
|
-
* These are development-related URLs that shouldn't have impersonation
|
|
25
|
-
*/
|
|
26
|
-
const DEFAULT_IGNORE_PATTERNS = [/\/symbolicate$/, /\/logs$/, /\/debugger-proxy/, /\/reload$/, /\/launch-js-devtools/, /localhost:8081/, /100\.64\.\d+\.\d+:8081/,
|
|
27
|
-
// iOS simulator Metro
|
|
28
|
-
/10\.0\.\d+\.\d+:8081/,
|
|
29
|
-
// Android emulator Metro
|
|
30
|
-
/\.hot-update\./, /__metro/];
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Impersonation header injector for network requests
|
|
34
|
-
*
|
|
35
|
-
* This class monkey-patches fetch and XMLHttpRequest to inject the
|
|
36
|
-
* impersonation header on all outgoing requests when impersonation is active.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```typescript
|
|
40
|
-
* // Get the singleton instance
|
|
41
|
-
* const listener = impersonateListener();
|
|
42
|
-
*
|
|
43
|
-
* // Configure impersonation
|
|
44
|
-
* listener.setConfig({
|
|
45
|
-
* headerKey: 'x-impersonate-user-id',
|
|
46
|
-
* userId: '12345',
|
|
47
|
-
* ignorePatterns: [/\/health/]
|
|
48
|
-
* });
|
|
49
|
-
*
|
|
50
|
-
* // Start injecting headers
|
|
51
|
-
* listener.startListening();
|
|
52
|
-
*
|
|
53
|
-
* // All fetch/XHR requests will now include the header
|
|
54
|
-
*
|
|
55
|
-
* // Stop injecting when done
|
|
56
|
-
* listener.stopListening();
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
/**
|
|
60
|
-
* Cooperating-interceptor protocol with @buoy-gg/network: its interceptors
|
|
61
|
-
* carry `__buoy*` marker properties, and it re-installs itself whenever the
|
|
62
|
-
* marker disappears from the live global (that's how it survives being
|
|
63
|
-
* clobbered by Expo/DevTools re-assigning fetch). We wrap its functions, so
|
|
64
|
-
* the markers must ride along on our wrappers — otherwise the network tool
|
|
65
|
-
* would conclude it lost interception and stack a fresh patch on every check.
|
|
66
|
-
*/
|
|
67
|
-
function carryBuoyMarkers(wrapper, wrapped) {
|
|
68
|
-
for (const key of Object.keys(wrapped)) {
|
|
69
|
-
if (key.startsWith("__buoy")) {
|
|
70
|
-
wrapper[key] = wrapped[key];
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
class ImpersonateListener {
|
|
75
|
-
isListeningFlag = false;
|
|
76
|
-
|
|
77
|
-
// Store original methods - MUST be captured before other tools patch
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* The wrappers this instance installed, for identity checks — stopListening
|
|
81
|
-
* only restores globals that are still literally ours (see there).
|
|
82
|
-
*/
|
|
83
|
-
patchedFetch = null;
|
|
84
|
-
patchedXHROpen = null;
|
|
85
|
-
patchedXHRSend = null;
|
|
86
|
-
constructor() {
|
|
87
|
-
// Initialize with current fetch - will be re-captured in startListening
|
|
88
|
-
this.originalFetch = globalThis.fetch.bind(globalThis);
|
|
89
|
-
this.originalXHROpen = XMLHttpRequest.prototype.open;
|
|
90
|
-
this.originalXHRSend = XMLHttpRequest.prototype.send;
|
|
91
|
-
this.config = {
|
|
92
|
-
headerKey: "x-impersonate-user-id",
|
|
93
|
-
userId: null,
|
|
94
|
-
ignorePatterns: [...DEFAULT_IGNORE_PATTERNS]
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Update impersonation config without restarting listener
|
|
100
|
-
*
|
|
101
|
-
* This is the primary way to activate/deactivate impersonation.
|
|
102
|
-
* Set userId to null to stop injecting headers.
|
|
103
|
-
*/
|
|
104
|
-
setConfig(partial) {
|
|
105
|
-
this.config = {
|
|
106
|
-
...this.config,
|
|
107
|
-
...partial
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// Merge ignore patterns if provided
|
|
111
|
-
if (partial.ignorePatterns) {
|
|
112
|
-
this.config.ignorePatterns = [...DEFAULT_IGNORE_PATTERNS, ...partial.ignorePatterns];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Get current configuration
|
|
118
|
-
*/
|
|
119
|
-
getConfig() {
|
|
120
|
-
return {
|
|
121
|
-
...this.config
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Check if URL should have header injected
|
|
127
|
-
*
|
|
128
|
-
* Returns false if:
|
|
129
|
-
* - No userId is set (not impersonating)
|
|
130
|
-
* - URL matches any ignore pattern
|
|
131
|
-
*/
|
|
132
|
-
shouldInjectHeader(url) {
|
|
133
|
-
// Not impersonating
|
|
134
|
-
if (!this.config.userId) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
if (this.config.gate && !this.config.gate()) {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Check ignore patterns
|
|
142
|
-
return !this.config.ignorePatterns.some(pattern => pattern.test(url));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Extract URL from various input types
|
|
147
|
-
*/
|
|
148
|
-
extractUrl(input) {
|
|
149
|
-
if (typeof input === "string") {
|
|
150
|
-
return input;
|
|
151
|
-
}
|
|
152
|
-
if (input instanceof URL) {
|
|
153
|
-
return input.href;
|
|
154
|
-
}
|
|
155
|
-
// Request object
|
|
156
|
-
return input.url;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Start intercepting and injecting headers
|
|
161
|
-
*
|
|
162
|
-
* This patches globalThis.fetch and XMLHttpRequest.prototype methods
|
|
163
|
-
* to inject the impersonation header on all requests.
|
|
164
|
-
*/
|
|
165
|
-
startListening() {
|
|
166
|
-
if (this.isListeningFlag) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// CRITICAL: Re-capture fetch/XHR NOW, not at construction time
|
|
171
|
-
// This ensures we patch OVER any existing interceptors (like @buoy-gg/network)
|
|
172
|
-
// so our modifications are visible to them
|
|
173
|
-
//
|
|
174
|
-
// Keep the UNBOUND functions too: @buoy-gg/network stamps `__buoy*` marker
|
|
175
|
-
// properties on its interceptors and re-installs when the marker vanishes
|
|
176
|
-
// from the live global — and `.bind()` drops own properties, so the
|
|
177
|
-
// markers must be read off the unbound originals and carried forward onto
|
|
178
|
-
// our wrappers (see below).
|
|
179
|
-
const wrappedFetch = globalThis.fetch;
|
|
180
|
-
const wrappedXHROpen = XMLHttpRequest.prototype.open;
|
|
181
|
-
const wrappedXHRSend = XMLHttpRequest.prototype.send;
|
|
182
|
-
this.originalFetch = wrappedFetch.bind(globalThis);
|
|
183
|
-
this.originalXHROpen = wrappedXHROpen;
|
|
184
|
-
this.originalXHRSend = wrappedXHRSend;
|
|
185
|
-
const self = this;
|
|
186
|
-
|
|
187
|
-
// =======================================================================
|
|
188
|
-
// PATCH FETCH
|
|
189
|
-
// =======================================================================
|
|
190
|
-
const patchedFetch = async function (input, init) {
|
|
191
|
-
const url = self.extractUrl(input);
|
|
192
|
-
if (self.shouldInjectHeader(url)) {
|
|
193
|
-
// Create new headers with impersonation header added
|
|
194
|
-
const existingHeaders = init?.headers ?? (typeof input === 'object' && 'headers' in input ? input.headers : undefined);
|
|
195
|
-
const headers = new Headers(existingHeaders);
|
|
196
|
-
headers.set(self.config.headerKey, self.config.userId);
|
|
197
|
-
|
|
198
|
-
// Call original fetch with modified init
|
|
199
|
-
return self.originalFetch(input, {
|
|
200
|
-
...init,
|
|
201
|
-
headers
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Not injecting - call original fetch as-is
|
|
206
|
-
return self.originalFetch(input, init);
|
|
207
|
-
};
|
|
208
|
-
carryBuoyMarkers(patchedFetch, wrappedFetch);
|
|
209
|
-
this.patchedFetch = patchedFetch;
|
|
210
|
-
globalThis.fetch = this.patchedFetch;
|
|
211
|
-
|
|
212
|
-
// =======================================================================
|
|
213
|
-
// PATCH XMLHttpRequest
|
|
214
|
-
// =======================================================================
|
|
215
|
-
|
|
216
|
-
// Patch open() to store the URL for later use in send()
|
|
217
|
-
const patchedOpen = function (method, url, async = true, username, password) {
|
|
218
|
-
const xhr = this;
|
|
219
|
-
xhr._impersonateUrl = typeof url === "string" ? url : url.href;
|
|
220
|
-
const urlStr = typeof url === "string" ? url : url.toString();
|
|
221
|
-
return self.originalXHROpen.call(this, method, urlStr, async, username, password);
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
// Patch send() to inject header before sending
|
|
225
|
-
const patchedSend = function (body) {
|
|
226
|
-
const xhr = this;
|
|
227
|
-
if (xhr._impersonateUrl && self.shouldInjectHeader(xhr._impersonateUrl)) {
|
|
228
|
-
// Inject the impersonation header
|
|
229
|
-
this.setRequestHeader(self.config.headerKey, self.config.userId);
|
|
230
|
-
}
|
|
231
|
-
return self.originalXHRSend.call(this, body);
|
|
232
|
-
};
|
|
233
|
-
carryBuoyMarkers(patchedOpen, wrappedXHROpen);
|
|
234
|
-
carryBuoyMarkers(patchedSend, wrappedXHRSend);
|
|
235
|
-
this.patchedXHROpen = patchedOpen;
|
|
236
|
-
this.patchedXHRSend = patchedSend;
|
|
237
|
-
XMLHttpRequest.prototype.open = this.patchedXHROpen;
|
|
238
|
-
XMLHttpRequest.prototype.send = this.patchedXHRSend;
|
|
239
|
-
|
|
240
|
-
// Tell @buoy-gg/network which header this adds, so its row shows it.
|
|
241
|
-
// Network usually wraps this wrapper and records before the header is set.
|
|
242
|
-
const g = globalThis;
|
|
243
|
-
const injectors = g.__buoyHeaderInjectors ??= [];
|
|
244
|
-
if (!injectors.includes(this.reportHeader)) injectors.push(this.reportHeader);
|
|
245
|
-
this.isListeningFlag = true;
|
|
246
|
-
}
|
|
247
|
-
reportHeader = url => this.shouldInjectHeader(url) ? {
|
|
248
|
-
[this.config.headerKey]: this.config.userId
|
|
249
|
-
} : null;
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Stop intercepting - restore original methods
|
|
253
|
-
*
|
|
254
|
-
* Note: This restores fetch/XHR to their state when ImpersonateListener
|
|
255
|
-
* was constructed. If other interceptors were installed after, this may
|
|
256
|
-
* break their functionality.
|
|
257
|
-
*/
|
|
258
|
-
stopListening() {
|
|
259
|
-
if (!this.isListeningFlag) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Restore ONLY what is still literally ours: if another interceptor
|
|
264
|
-
// patched after us (the network tool re-asserting itself, a debugger),
|
|
265
|
-
// assigning our saved originals would silently wipe its patch. Leaving our
|
|
266
|
-
// wrapper in a foreign chain is safe — with no userId configured it is a
|
|
267
|
-
// pure pass-through.
|
|
268
|
-
if (this.patchedFetch && globalThis.fetch === this.patchedFetch) {
|
|
269
|
-
globalThis.fetch = this.originalFetch;
|
|
270
|
-
}
|
|
271
|
-
if (this.patchedXHROpen && XMLHttpRequest.prototype.open === this.patchedXHROpen) {
|
|
272
|
-
XMLHttpRequest.prototype.open = this.originalXHROpen;
|
|
273
|
-
}
|
|
274
|
-
if (this.patchedXHRSend && XMLHttpRequest.prototype.send === this.patchedXHRSend) {
|
|
275
|
-
XMLHttpRequest.prototype.send = this.originalXHRSend;
|
|
276
|
-
}
|
|
277
|
-
this.patchedFetch = null;
|
|
278
|
-
this.patchedXHROpen = null;
|
|
279
|
-
this.patchedXHRSend = null;
|
|
280
|
-
const injectors = globalThis.__buoyHeaderInjectors;
|
|
281
|
-
const at = injectors?.indexOf(this.reportHeader) ?? -1;
|
|
282
|
-
if (injectors && at >= 0) injectors.splice(at, 1);
|
|
283
|
-
this.isListeningFlag = false;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Check if listener is currently active
|
|
288
|
-
*/
|
|
289
|
-
get isListening() {
|
|
290
|
-
return this.isListeningFlag;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Check if impersonation is currently active (has userId set)
|
|
295
|
-
*/
|
|
296
|
-
get isImpersonating() {
|
|
297
|
-
return this.config.userId !== null && (this.config.gate?.() ?? true);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// =============================================================================
|
|
302
|
-
// SINGLETON PATTERN
|
|
303
|
-
// =============================================================================
|
|
304
|
-
|
|
305
|
-
let _instance = null;
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Get the singleton ImpersonateListener instance
|
|
309
|
-
*/
|
|
310
|
-
function impersonateListener() {
|
|
311
|
-
if (!_instance) {
|
|
312
|
-
_instance = new ImpersonateListener();
|
|
313
|
-
}
|
|
314
|
-
return _instance;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Convenience function to start the listener
|
|
319
|
-
*/
|
|
320
|
-
function startImpersonateListener() {
|
|
321
|
-
impersonateListener().startListening();
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Convenience function to stop the listener
|
|
326
|
-
*/
|
|
327
|
-
function stopImpersonateListener() {
|
|
328
|
-
impersonateListener().stopListening();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Convenience function to update config
|
|
333
|
-
*/
|
|
334
|
-
function setImpersonateConfig(config) {
|
|
335
|
-
impersonateListener().setConfig(config);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Convenience function to check if impersonating
|
|
340
|
-
*/
|
|
341
|
-
function isImpersonating() {
|
|
342
|
-
return _instance?.isImpersonating ?? false;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Convenience function to get impersonated user ID
|
|
347
|
-
*/
|
|
348
|
-
function getImpersonatedUserId() {
|
|
349
|
-
return _instance?.getConfig().userId ?? null;
|
|
350
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getImpersonatedUserId=getImpersonatedUserId;exports.impersonateListener=impersonateListener;exports.isImpersonating=isImpersonating;exports.setImpersonateConfig=setImpersonateConfig;exports.startImpersonateListener=startImpersonateListener;exports.stopImpersonateListener=stopImpersonateListener;const DEFAULT_IGNORE_PATTERNS=[/\/symbolicate$/,/\/logs$/,/\/debugger-proxy/,/\/reload$/,/\/launch-js-devtools/,/localhost:8081/,/100\.64\.\d+\.\d+:8081/,/10\.0\.\d+\.\d+:8081/,/\.hot-update\./,/__metro/];function carryBuoyMarkers(r,e){for(const s of Object.keys(e)){if(s.startsWith("__buoy")){r[s]=e[s]}}}class ImpersonateListener{isListeningFlag=false;patchedFetch=null;patchedXHROpen=null;patchedXHRSend=null;constructor(){this.originalFetch=globalThis.fetch.bind(globalThis);this.originalXHROpen=XMLHttpRequest.prototype.open;this.originalXHRSend=XMLHttpRequest.prototype.send;this.config={headerKey:"x-impersonate-user-id",userId:null,ignorePatterns:[...DEFAULT_IGNORE_PATTERNS]}}setConfig(e){this.config={...this.config,...e};if(e.ignorePatterns){this.config.ignorePatterns=[...DEFAULT_IGNORE_PATTERNS,...e.ignorePatterns]}}getConfig(){return{...this.config}}shouldInjectHeader(e){if(!this.config.userId){return false}if(this.config.gate&&!this.config.gate()){return false}return!this.config.ignorePatterns.some(s=>s.test(e))}extractUrl(e){if(typeof e==="string"){return e}if(e instanceof URL){return e.href}return e.url}startListening(){if(this.isListeningFlag){return}const e=globalThis.fetch;const s=XMLHttpRequest.prototype.open;const c=XMLHttpRequest.prototype.send;this.originalFetch=e.bind(globalThis);this.originalXHROpen=s;this.originalXHRSend=c;const n=this;const p=async function(i,t){const a=n.extractUrl(i);if(n.shouldInjectHeader(a)){const h=t?.headers??(typeof i==="object"&&"headers"in i?i.headers:void 0);const o=new Headers(h);o.set(n.config.headerKey,n.config.userId);return n.originalFetch(i,{...t,headers:o})}return n.originalFetch(i,t)};carryBuoyMarkers(p,e);this.patchedFetch=p;globalThis.fetch=this.patchedFetch;const d=function(i,t,a=true,h,o){const u=this;u._impersonateUrl=typeof t==="string"?t:t.href;const H=typeof t==="string"?t:t.toString();return n.originalXHROpen.call(this,i,H,a,h,o)};const g=function(i){const t=this;if(t._impersonateUrl&&n.shouldInjectHeader(t._impersonateUrl)){this.setRequestHeader(n.config.headerKey,n.config.userId)}return n.originalXHRSend.call(this,i)};carryBuoyMarkers(d,s);carryBuoyMarkers(g,c);this.patchedXHROpen=d;this.patchedXHRSend=g;XMLHttpRequest.prototype.open=this.patchedXHROpen;XMLHttpRequest.prototype.send=this.patchedXHRSend;const f=globalThis;const l=f.__buoyHeaderInjectors??=[];if(!l.includes(this.reportHeader))l.push(this.reportHeader);this.isListeningFlag=true}reportHeader=e=>this.shouldInjectHeader(e)?{[this.config.headerKey]:this.config.userId}:null;stopListening(){if(!this.isListeningFlag){return}if(this.patchedFetch&&globalThis.fetch===this.patchedFetch){globalThis.fetch=this.originalFetch}if(this.patchedXHROpen&&XMLHttpRequest.prototype.open===this.patchedXHROpen){XMLHttpRequest.prototype.open=this.originalXHROpen}if(this.patchedXHRSend&&XMLHttpRequest.prototype.send===this.patchedXHRSend){XMLHttpRequest.prototype.send=this.originalXHRSend}this.patchedFetch=null;this.patchedXHROpen=null;this.patchedXHRSend=null;const e=globalThis.__buoyHeaderInjectors;const s=e?.indexOf(this.reportHeader)??-1;if(e&&s>=0)e.splice(s,1);this.isListeningFlag=false}get isListening(){return this.isListeningFlag}get isImpersonating(){return this.config.userId!==null&&(this.config.gate?.()??true)}}let _instance=null;function impersonateListener(){if(!_instance){_instance=new ImpersonateListener}return _instance}function startImpersonateListener(){impersonateListener().startListening()}function stopImpersonateListener(){impersonateListener().stopListening()}function setImpersonateConfig(r){impersonateListener().setConfig(r)}function isImpersonating(){return _instance?.isImpersonating??false}function getImpersonatedUserId(){return _instance?.getConfig().userId??null}
|