@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.
Files changed (78) hide show
  1. package/README.md +12 -80
  2. package/lib/commonjs/impersonate/components/DataNukeSettings.js +8 -675
  3. package/lib/commonjs/impersonate/components/ImpersonateBanner.js +1 -221
  4. package/lib/commonjs/impersonate/components/ImpersonateHistoryList.js +1 -181
  5. package/lib/commonjs/impersonate/components/ImpersonateModal.js +1 -319
  6. package/lib/commonjs/impersonate/components/ImpersonateOverlay.js +1 -26
  7. package/lib/commonjs/impersonate/components/ImpersonateStatusBar.js +1 -130
  8. package/lib/commonjs/impersonate/components/UserAvatar.js +1 -146
  9. package/lib/commonjs/impersonate/components/UserCard.js +1 -201
  10. package/lib/commonjs/impersonate/components/UserSearchView.js +1 -227
  11. package/lib/commonjs/impersonate/hooks/asyncStoragePeer.js +1 -17
  12. package/lib/commonjs/impersonate/hooks/asyncStoragePeer.web.js +1 -11
  13. package/lib/commonjs/impersonate/hooks/useAutoClearAsyncStorage.js +1 -134
  14. package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.js +1 -155
  15. package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.web.js +1 -20
  16. package/lib/commonjs/impersonate/hooks/useAutoClearRedux.js +1 -188
  17. package/lib/commonjs/impersonate/hooks/useAutoClearRedux.web.js +1 -27
  18. package/lib/commonjs/impersonate/hooks/useImpersonate.js +1 -215
  19. package/lib/commonjs/impersonate/hooks/useImpersonateHistory.js +1 -56
  20. package/lib/commonjs/impersonate/types/index.js +1 -16
  21. package/lib/commonjs/impersonate/types/types.js +1 -1
  22. package/lib/commonjs/impersonate/utils/impersonateListener.js +1 -350
  23. package/lib/commonjs/impersonate/utils/impersonateStore.js +1 -689
  24. package/lib/commonjs/index.js +1 -150
  25. package/lib/commonjs/preset.js +1 -232
  26. package/lib/commonjs/sync/impersonateSyncAdapter.js +1 -170
  27. package/lib/module/impersonate/components/DataNukeSettings.js +8 -670
  28. package/lib/module/impersonate/components/ImpersonateBanner.js +1 -215
  29. package/lib/module/impersonate/components/ImpersonateHistoryList.js +1 -176
  30. package/lib/module/impersonate/components/ImpersonateModal.js +1 -314
  31. package/lib/module/impersonate/components/ImpersonateOverlay.js +1 -21
  32. package/lib/module/impersonate/components/ImpersonateStatusBar.js +1 -125
  33. package/lib/module/impersonate/components/UserAvatar.js +1 -140
  34. package/lib/module/impersonate/components/UserCard.js +1 -196
  35. package/lib/module/impersonate/components/UserSearchView.js +1 -222
  36. package/lib/module/impersonate/hooks/asyncStoragePeer.js +1 -13
  37. package/lib/module/impersonate/hooks/asyncStoragePeer.web.js +1 -6
  38. package/lib/module/impersonate/hooks/useAutoClearAsyncStorage.js +1 -130
  39. package/lib/module/impersonate/hooks/useAutoClearReactQuery.js +1 -151
  40. package/lib/module/impersonate/hooks/useAutoClearReactQuery.web.js +1 -16
  41. package/lib/module/impersonate/hooks/useAutoClearRedux.js +1 -183
  42. package/lib/module/impersonate/hooks/useAutoClearRedux.web.js +1 -22
  43. package/lib/module/impersonate/hooks/useImpersonate.js +1 -212
  44. package/lib/module/impersonate/hooks/useImpersonateHistory.js +1 -52
  45. package/lib/module/impersonate/types/index.js +1 -3
  46. package/lib/module/impersonate/types/types.js +1 -1
  47. package/lib/module/impersonate/utils/impersonateListener.js +1 -341
  48. package/lib/module/impersonate/utils/impersonateStore.js +1 -686
  49. package/lib/module/index.js +1 -117
  50. package/lib/module/preset.js +1 -216
  51. package/lib/module/sync/impersonateSyncAdapter.js +1 -162
  52. package/lib/web/index.mjs +7 -8
  53. package/package.json +3 -6
  54. package/lib/typescript/impersonate/components/DataNukeSettings.d.ts.map +0 -1
  55. package/lib/typescript/impersonate/components/ImpersonateBanner.d.ts.map +0 -1
  56. package/lib/typescript/impersonate/components/ImpersonateHistoryList.d.ts.map +0 -1
  57. package/lib/typescript/impersonate/components/ImpersonateModal.d.ts.map +0 -1
  58. package/lib/typescript/impersonate/components/ImpersonateOverlay.d.ts.map +0 -1
  59. package/lib/typescript/impersonate/components/ImpersonateStatusBar.d.ts.map +0 -1
  60. package/lib/typescript/impersonate/components/UserAvatar.d.ts.map +0 -1
  61. package/lib/typescript/impersonate/components/UserCard.d.ts.map +0 -1
  62. package/lib/typescript/impersonate/components/UserSearchView.d.ts.map +0 -1
  63. package/lib/typescript/impersonate/hooks/asyncStoragePeer.d.ts.map +0 -1
  64. package/lib/typescript/impersonate/hooks/asyncStoragePeer.web.d.ts.map +0 -1
  65. package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts.map +0 -1
  66. package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.d.ts.map +0 -1
  67. package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.web.d.ts.map +0 -1
  68. package/lib/typescript/impersonate/hooks/useAutoClearRedux.d.ts.map +0 -1
  69. package/lib/typescript/impersonate/hooks/useAutoClearRedux.web.d.ts.map +0 -1
  70. package/lib/typescript/impersonate/hooks/useImpersonate.d.ts.map +0 -1
  71. package/lib/typescript/impersonate/hooks/useImpersonateHistory.d.ts.map +0 -1
  72. package/lib/typescript/impersonate/types/index.d.ts.map +0 -1
  73. package/lib/typescript/impersonate/types/types.d.ts.map +0 -1
  74. package/lib/typescript/impersonate/utils/impersonateListener.d.ts.map +0 -1
  75. package/lib/typescript/impersonate/utils/impersonateStore.d.ts.map +0 -1
  76. package/lib/typescript/index.d.ts.map +0 -1
  77. package/lib/typescript/preset.d.ts.map +0 -1
  78. 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}