@buoy-gg/impersonate 7.0.40 → 7.0.41
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 +4 -0
- package/lib/commonjs/impersonate/hooks/asyncStoragePeer.js +17 -0
- package/lib/commonjs/impersonate/hooks/asyncStoragePeer.web.js +11 -0
- package/lib/commonjs/impersonate/hooks/useAutoClearAsyncStorage.js +3 -13
- package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.web.js +20 -0
- package/lib/commonjs/impersonate/hooks/useAutoClearRedux.web.js +27 -0
- package/lib/commonjs/impersonate/utils/impersonateListener.js +17 -2
- package/lib/commonjs/impersonate/utils/impersonateStore.js +18 -4
- package/lib/commonjs/preset.js +4 -4
- package/lib/commonjs/sync/impersonateSyncAdapter.js +10 -1
- package/lib/module/impersonate/hooks/asyncStoragePeer.js +13 -0
- package/lib/module/impersonate/hooks/asyncStoragePeer.web.js +6 -0
- package/lib/module/impersonate/hooks/useAutoClearAsyncStorage.js +1 -11
- package/lib/module/impersonate/hooks/useAutoClearReactQuery.web.js +16 -0
- package/lib/module/impersonate/hooks/useAutoClearRedux.web.js +22 -0
- package/lib/module/impersonate/utils/impersonateListener.js +17 -2
- package/lib/module/impersonate/utils/impersonateStore.js +19 -5
- package/lib/module/preset.js +4 -4
- package/lib/module/sync/impersonateSyncAdapter.js +10 -1
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.d.ts +7 -0
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.d.ts.map +1 -0
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.web.d.ts +2 -0
- package/lib/typescript/impersonate/hooks/asyncStoragePeer.web.d.ts.map +1 -0
- package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts +3 -12
- package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts.map +1 -1
- package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.web.d.ts +3 -0
- package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.web.d.ts.map +1 -0
- package/lib/typescript/impersonate/hooks/useAutoClearRedux.web.d.ts +4 -0
- package/lib/typescript/impersonate/hooks/useAutoClearRedux.web.d.ts.map +1 -0
- package/lib/typescript/impersonate/types/types.d.ts +6 -0
- package/lib/typescript/impersonate/types/types.d.ts.map +1 -1
- package/lib/typescript/impersonate/utils/impersonateListener.d.ts +1 -0
- package/lib/typescript/impersonate/utils/impersonateListener.d.ts.map +1 -1
- package/lib/typescript/impersonate/utils/impersonateStore.d.ts.map +1 -1
- package/lib/typescript/preset.d.ts.map +1 -1
- package/lib/typescript/sync/impersonateSyncAdapter.d.ts.map +1 -1
- package/lib/web/index.mjs +11 -0
- package/package.json +32 -10
package/README.md
CHANGED
|
@@ -89,3 +89,7 @@ Use a Free or Pro Buoy account. History limits and paid features vary by tool; s
|
|
|
89
89
|
📚 [Full docs](https://buoy.gg/buoy/latest/docs/tools/impersonate) · [All Buoy tools](https://github.com/Buoy-gg/buoy)
|
|
90
90
|
|
|
91
91
|
Proprietary software. © Buoy LLC. [Terms](https://buoy.gg/terms)
|
|
92
|
+
|
|
93
|
+
## Web support (unreleased)
|
|
94
|
+
|
|
95
|
+
Register this package’s /web namespace in FloatingDevTools modules to use its shared panels and actions in a browser app. The browser build is available in this checkout and has not been published yet. See the [web setup guide](https://buoy.gg/buoy/latest/docs/web-preview) for registration, dependencies, and browser boundaries.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getAsyncStorage = getAsyncStorage;
|
|
7
|
+
function getAsyncStorage() {
|
|
8
|
+
try {
|
|
9
|
+
// Dynamic require to handle cases where async-storage isn't installed
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const AsyncStorage = require("@react-native-async-storage/async-storage").default;
|
|
12
|
+
return AsyncStorage;
|
|
13
|
+
} catch {
|
|
14
|
+
// @react-native-async-storage/async-storage not available
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getAsyncStorage = getAsyncStorage;
|
|
7
|
+
var _asyncStorage = _interopRequireDefault(require("@react-native-async-storage/async-storage"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
function getAsyncStorage() {
|
|
10
|
+
return _asyncStorage.default;
|
|
11
|
+
}
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.useAsyncStorageAvailability = useAsyncStorageAvailability;
|
|
7
7
|
exports.useAutoClearAsyncStorage = useAutoClearAsyncStorage;
|
|
8
|
+
var _asyncStoragePeer = require("./asyncStoragePeer");
|
|
8
9
|
var _react = require("react");
|
|
9
10
|
/**
|
|
10
11
|
* useAutoClearAsyncStorage Hook
|
|
@@ -32,17 +33,6 @@ let isClearing = false;
|
|
|
32
33
|
/**
|
|
33
34
|
* Safely attempt to load @react-native-async-storage/async-storage
|
|
34
35
|
*/
|
|
35
|
-
function getAsyncStorage() {
|
|
36
|
-
try {
|
|
37
|
-
// Dynamic require to handle cases where async-storage isn't installed
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
39
|
-
const AsyncStorage = require("@react-native-async-storage/async-storage").default;
|
|
40
|
-
return AsyncStorage;
|
|
41
|
-
} catch {
|
|
42
|
-
// @react-native-async-storage/async-storage not available
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
36
|
|
|
47
37
|
// ============================================
|
|
48
38
|
// Main Hook
|
|
@@ -72,7 +62,7 @@ function useAutoClearAsyncStorage() {
|
|
|
72
62
|
|
|
73
63
|
// Check for AsyncStorage on mount
|
|
74
64
|
(0, _react.useEffect)(() => {
|
|
75
|
-
const storage = getAsyncStorage();
|
|
65
|
+
const storage = (0, _asyncStoragePeer.getAsyncStorage)();
|
|
76
66
|
if (storage) {
|
|
77
67
|
setAsyncStorage(storage);
|
|
78
68
|
setError(null);
|
|
@@ -130,7 +120,7 @@ function useAutoClearAsyncStorage() {
|
|
|
130
120
|
* without creating the clear function
|
|
131
121
|
*/
|
|
132
122
|
function useAsyncStorageAvailability() {
|
|
133
|
-
const storage = getAsyncStorage();
|
|
123
|
+
const storage = (0, _asyncStoragePeer.getAsyncStorage)();
|
|
134
124
|
if (!storage) {
|
|
135
125
|
return {
|
|
136
126
|
isInstalled: false,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useAutoClearReactQuery = useAutoClearReactQuery;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
9
|
+
function useAutoClearReactQuery() {
|
|
10
|
+
const available = Boolean((0, _sharedUi.getToolAdapters)().query);
|
|
11
|
+
const clearCache = (0, _react.useCallback)(async () => {
|
|
12
|
+
await (0, _sharedUi.dispatchToolAction)('query', 'clearQueryCache');
|
|
13
|
+
await (0, _sharedUi.dispatchToolAction)('query', 'clearMutationCache');
|
|
14
|
+
}, []);
|
|
15
|
+
return {
|
|
16
|
+
isAvailable: available,
|
|
17
|
+
error: available ? null : 'Connect React Query to Buoy or provide onClearReactQuery.',
|
|
18
|
+
clearCache: available ? clearCache : null
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.REDUX_RESET_ACTION_TYPE = void 0;
|
|
7
|
+
exports.useAutoClearRedux = useAutoClearRedux;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
10
|
+
const REDUX_RESET_ACTION_TYPE = exports.REDUX_RESET_ACTION_TYPE = '@@RESET';
|
|
11
|
+
function useAutoClearRedux({
|
|
12
|
+
resetActionType = REDUX_RESET_ACTION_TYPE
|
|
13
|
+
} = {}) {
|
|
14
|
+
const available = Boolean((0, _sharedUi.getToolAdapters)().redux);
|
|
15
|
+
const resetStore = (0, _react.useCallback)(async () => {
|
|
16
|
+
await (0, _sharedUi.dispatchToolAction)('redux', 'dispatch', {
|
|
17
|
+
action: {
|
|
18
|
+
type: resetActionType
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}, [resetActionType]);
|
|
22
|
+
return {
|
|
23
|
+
isAvailable: available,
|
|
24
|
+
error: available ? null : 'Connect Redux to Buoy or provide onClearRedux.',
|
|
25
|
+
resetStore: available ? resetStore : null
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -134,6 +134,9 @@ class ImpersonateListener {
|
|
|
134
134
|
if (!this.config.userId) {
|
|
135
135
|
return false;
|
|
136
136
|
}
|
|
137
|
+
if (this.config.gate && !this.config.gate()) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
137
140
|
|
|
138
141
|
// Check ignore patterns
|
|
139
142
|
return !this.config.ignorePatterns.some(pattern => pattern.test(url));
|
|
@@ -188,7 +191,7 @@ class ImpersonateListener {
|
|
|
188
191
|
const url = self.extractUrl(input);
|
|
189
192
|
if (self.shouldInjectHeader(url)) {
|
|
190
193
|
// Create new headers with impersonation header added
|
|
191
|
-
const existingHeaders = init?.headers;
|
|
194
|
+
const existingHeaders = init?.headers ?? (typeof input === 'object' && 'headers' in input ? input.headers : undefined);
|
|
192
195
|
const headers = new Headers(existingHeaders);
|
|
193
196
|
headers.set(self.config.headerKey, self.config.userId);
|
|
194
197
|
|
|
@@ -233,8 +236,17 @@ class ImpersonateListener {
|
|
|
233
236
|
this.patchedXHRSend = patchedSend;
|
|
234
237
|
XMLHttpRequest.prototype.open = this.patchedXHROpen;
|
|
235
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);
|
|
236
245
|
this.isListeningFlag = true;
|
|
237
246
|
}
|
|
247
|
+
reportHeader = url => this.shouldInjectHeader(url) ? {
|
|
248
|
+
[this.config.headerKey]: this.config.userId
|
|
249
|
+
} : null;
|
|
238
250
|
|
|
239
251
|
/**
|
|
240
252
|
* Stop intercepting - restore original methods
|
|
@@ -265,6 +277,9 @@ class ImpersonateListener {
|
|
|
265
277
|
this.patchedFetch = null;
|
|
266
278
|
this.patchedXHROpen = null;
|
|
267
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);
|
|
268
283
|
this.isListeningFlag = false;
|
|
269
284
|
}
|
|
270
285
|
|
|
@@ -279,7 +294,7 @@ class ImpersonateListener {
|
|
|
279
294
|
* Check if impersonation is currently active (has userId set)
|
|
280
295
|
*/
|
|
281
296
|
get isImpersonating() {
|
|
282
|
-
return this.config.userId !== null;
|
|
297
|
+
return this.config.userId !== null && (this.config.gate?.() ?? true);
|
|
283
298
|
}
|
|
284
299
|
}
|
|
285
300
|
|
|
@@ -112,8 +112,18 @@ class ImpersonateStore {
|
|
|
112
112
|
// Try to load persisted state synchronously
|
|
113
113
|
this.loadFromStorage();
|
|
114
114
|
Promise.resolve().then(() => {
|
|
115
|
+
// Only a sign-out ends the session: access that was admitted and is now
|
|
116
|
+
// locked. The license reports "locked" for a moment while it boots or
|
|
117
|
+
// reloads, before validation starts, and ending the session then wiped a
|
|
118
|
+
// restored impersonation for good. The per-request gate already keeps
|
|
119
|
+
// the header off whenever access isn't admitted.
|
|
120
|
+
let wasAdmitted = false;
|
|
115
121
|
const reconcile = () => {
|
|
116
|
-
|
|
122
|
+
const status = (0, _sharedUi.getAccountAccess)().status;
|
|
123
|
+
if (status === "admitted") wasAdmitted = true;else if (status === "locked" && wasAdmitted) {
|
|
124
|
+
wasAdmitted = false;
|
|
125
|
+
this.disposeAccountSession();
|
|
126
|
+
}
|
|
117
127
|
};
|
|
118
128
|
(0, _sharedUi.subscribeAccountAccess)(reconcile);
|
|
119
129
|
reconcile();
|
|
@@ -602,12 +612,16 @@ class ImpersonateStore {
|
|
|
602
612
|
void this.persist();
|
|
603
613
|
}
|
|
604
614
|
syncWithListener() {
|
|
605
|
-
// When paused, don't inject headers (pass null userId)
|
|
606
|
-
|
|
615
|
+
// When paused, don't inject headers (pass null userId). Account access is
|
|
616
|
+
// checked per request by the gate, not here: a session restored at launch
|
|
617
|
+
// syncs before the account check finishes, and reading it once here sent
|
|
618
|
+
// no header for the rest of the run, until a pause and resume re-synced.
|
|
619
|
+
const shouldInject = this.state.isActive && !this.state.isPaused;
|
|
607
620
|
(0, _impersonateListener.setImpersonateConfig)({
|
|
608
621
|
headerKey: this.state.headerKey,
|
|
609
622
|
userId: shouldInject ? this.state.currentUser?.id ?? null : null,
|
|
610
|
-
ignorePatterns: this.state.ignorePatterns.map(p => new RegExp(p))
|
|
623
|
+
ignorePatterns: this.state.ignorePatterns.map(p => new RegExp(p)),
|
|
624
|
+
gate: _sharedUi.hasAccountAccess
|
|
611
625
|
});
|
|
612
626
|
|
|
613
627
|
// Ensure listener is started
|
package/lib/commonjs/preset.js
CHANGED
|
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "ImpersonateIcon", {
|
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
exports.createImpersonateTool = createImpersonateTool;
|
|
19
|
+
var _asyncStoragePeer = require("./impersonate/hooks/asyncStoragePeer");
|
|
19
20
|
var _react = _interopRequireDefault(require("react"));
|
|
20
21
|
var _ImpersonateModal = require("./impersonate/components/ImpersonateModal");
|
|
21
22
|
var _ImpersonateBanner = require("./impersonate/components/ImpersonateBanner");
|
|
@@ -49,7 +50,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
49
50
|
|
|
50
51
|
let bootstrapStarted = false;
|
|
51
52
|
async function bootstrapImpersonate() {
|
|
52
|
-
if (bootstrapStarted) return;
|
|
53
|
+
if (typeof window === 'undefined' || bootstrapStarted) return;
|
|
53
54
|
bootstrapStarted = true;
|
|
54
55
|
|
|
55
56
|
// eslint-disable-next-line no-console
|
|
@@ -67,11 +68,10 @@ async function bootstrapImpersonate() {
|
|
|
67
68
|
// back to localStorage handled synchronously in its constructor.
|
|
68
69
|
try {
|
|
69
70
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
70
|
-
const
|
|
71
|
-
const AsyncStorage = mod?.default ?? mod;
|
|
71
|
+
const AsyncStorage = (0, _asyncStoragePeer.getAsyncStorage)();
|
|
72
72
|
if (!AsyncStorage || typeof AsyncStorage.getItem !== "function") {
|
|
73
73
|
// eslint-disable-next-line no-console
|
|
74
|
-
console.warn("[impersonate] bootstrap: AsyncStorage shape unexpected", Object.keys(
|
|
74
|
+
console.warn("[impersonate] bootstrap: AsyncStorage shape unexpected", Object.keys(AsyncStorage ?? {}));
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
const adapter = {
|
|
@@ -115,7 +115,16 @@ function buildActions(onSearchUsers) {
|
|
|
115
115
|
stopImpersonation: () => _impersonateStore.impersonateStore.stopImpersonation(),
|
|
116
116
|
pauseImpersonation: () => _impersonateStore.impersonateStore.pauseImpersonation(),
|
|
117
117
|
resumeImpersonation: () => _impersonateStore.impersonateStore.resumeImpersonation(),
|
|
118
|
-
updateSettings: params =>
|
|
118
|
+
updateSettings: params => {
|
|
119
|
+
// The documented shape is { settings: {...} }, but the flat patch is the
|
|
120
|
+
// obvious guess and used to crash with "Cannot read property 'headerKey'
|
|
121
|
+
// of undefined". Accept both; refuse anything else by name.
|
|
122
|
+
|
|
123
|
+
const p = params ?? {};
|
|
124
|
+
const settings = p.settings ?? (["headerKey", "ignorePatterns", "showBanner", "dataNukeSettings"].some(k => k in p) ? p : undefined);
|
|
125
|
+
if (!settings) throw new Error("updateSettings needs { settings: { headerKey?, ignorePatterns?, showBanner?, dataNukeSettings? } }.");
|
|
126
|
+
return _impersonateStore.impersonateStore.updateSettings(settings);
|
|
127
|
+
},
|
|
119
128
|
removeFromHistory: params => _impersonateStore.impersonateStore.removeFromHistory(params.userId),
|
|
120
129
|
clearHistory: () => _impersonateStore.impersonateStore.clearHistory()
|
|
121
130
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function getAsyncStorage() {
|
|
4
|
+
try {
|
|
5
|
+
// Dynamic require to handle cases where async-storage isn't installed
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
7
|
+
const AsyncStorage = require("@react-native-async-storage/async-storage").default;
|
|
8
|
+
return AsyncStorage;
|
|
9
|
+
} catch {
|
|
10
|
+
// @react-native-async-storage/async-storage not available
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { getAsyncStorage } from './asyncStoragePeer';
|
|
3
4
|
/**
|
|
4
5
|
* useAutoClearAsyncStorage Hook
|
|
5
6
|
*
|
|
@@ -28,17 +29,6 @@ let isClearing = false;
|
|
|
28
29
|
/**
|
|
29
30
|
* Safely attempt to load @react-native-async-storage/async-storage
|
|
30
31
|
*/
|
|
31
|
-
function getAsyncStorage() {
|
|
32
|
-
try {
|
|
33
|
-
// Dynamic require to handle cases where async-storage isn't installed
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
35
|
-
const AsyncStorage = require("@react-native-async-storage/async-storage").default;
|
|
36
|
-
return AsyncStorage;
|
|
37
|
-
} catch {
|
|
38
|
-
// @react-native-async-storage/async-storage not available
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
32
|
|
|
43
33
|
// ============================================
|
|
44
34
|
// Main Hook
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { dispatchToolAction, getToolAdapters } from '@buoy-gg/shared-ui';
|
|
5
|
+
export function useAutoClearReactQuery() {
|
|
6
|
+
const available = Boolean(getToolAdapters().query);
|
|
7
|
+
const clearCache = useCallback(async () => {
|
|
8
|
+
await dispatchToolAction('query', 'clearQueryCache');
|
|
9
|
+
await dispatchToolAction('query', 'clearMutationCache');
|
|
10
|
+
}, []);
|
|
11
|
+
return {
|
|
12
|
+
isAvailable: available,
|
|
13
|
+
error: available ? null : 'Connect React Query to Buoy or provide onClearReactQuery.',
|
|
14
|
+
clearCache: available ? clearCache : null
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { dispatchToolAction, getToolAdapters } from '@buoy-gg/shared-ui';
|
|
5
|
+
export const REDUX_RESET_ACTION_TYPE = '@@RESET';
|
|
6
|
+
export function useAutoClearRedux({
|
|
7
|
+
resetActionType = REDUX_RESET_ACTION_TYPE
|
|
8
|
+
} = {}) {
|
|
9
|
+
const available = Boolean(getToolAdapters().redux);
|
|
10
|
+
const resetStore = useCallback(async () => {
|
|
11
|
+
await dispatchToolAction('redux', 'dispatch', {
|
|
12
|
+
action: {
|
|
13
|
+
type: resetActionType
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}, [resetActionType]);
|
|
17
|
+
return {
|
|
18
|
+
isAvailable: available,
|
|
19
|
+
error: available ? null : 'Connect Redux to Buoy or provide onClearRedux.',
|
|
20
|
+
resetStore: available ? resetStore : null
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -125,6 +125,9 @@ class ImpersonateListener {
|
|
|
125
125
|
if (!this.config.userId) {
|
|
126
126
|
return false;
|
|
127
127
|
}
|
|
128
|
+
if (this.config.gate && !this.config.gate()) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
128
131
|
|
|
129
132
|
// Check ignore patterns
|
|
130
133
|
return !this.config.ignorePatterns.some(pattern => pattern.test(url));
|
|
@@ -179,7 +182,7 @@ class ImpersonateListener {
|
|
|
179
182
|
const url = self.extractUrl(input);
|
|
180
183
|
if (self.shouldInjectHeader(url)) {
|
|
181
184
|
// Create new headers with impersonation header added
|
|
182
|
-
const existingHeaders = init?.headers;
|
|
185
|
+
const existingHeaders = init?.headers ?? (typeof input === 'object' && 'headers' in input ? input.headers : undefined);
|
|
183
186
|
const headers = new Headers(existingHeaders);
|
|
184
187
|
headers.set(self.config.headerKey, self.config.userId);
|
|
185
188
|
|
|
@@ -224,8 +227,17 @@ class ImpersonateListener {
|
|
|
224
227
|
this.patchedXHRSend = patchedSend;
|
|
225
228
|
XMLHttpRequest.prototype.open = this.patchedXHROpen;
|
|
226
229
|
XMLHttpRequest.prototype.send = this.patchedXHRSend;
|
|
230
|
+
|
|
231
|
+
// Tell @buoy-gg/network which header this adds, so its row shows it.
|
|
232
|
+
// Network usually wraps this wrapper and records before the header is set.
|
|
233
|
+
const g = globalThis;
|
|
234
|
+
const injectors = g.__buoyHeaderInjectors ??= [];
|
|
235
|
+
if (!injectors.includes(this.reportHeader)) injectors.push(this.reportHeader);
|
|
227
236
|
this.isListeningFlag = true;
|
|
228
237
|
}
|
|
238
|
+
reportHeader = url => this.shouldInjectHeader(url) ? {
|
|
239
|
+
[this.config.headerKey]: this.config.userId
|
|
240
|
+
} : null;
|
|
229
241
|
|
|
230
242
|
/**
|
|
231
243
|
* Stop intercepting - restore original methods
|
|
@@ -256,6 +268,9 @@ class ImpersonateListener {
|
|
|
256
268
|
this.patchedFetch = null;
|
|
257
269
|
this.patchedXHROpen = null;
|
|
258
270
|
this.patchedXHRSend = null;
|
|
271
|
+
const injectors = globalThis.__buoyHeaderInjectors;
|
|
272
|
+
const at = injectors?.indexOf(this.reportHeader) ?? -1;
|
|
273
|
+
if (injectors && at >= 0) injectors.splice(at, 1);
|
|
259
274
|
this.isListeningFlag = false;
|
|
260
275
|
}
|
|
261
276
|
|
|
@@ -270,7 +285,7 @@ class ImpersonateListener {
|
|
|
270
285
|
* Check if impersonation is currently active (has userId set)
|
|
271
286
|
*/
|
|
272
287
|
get isImpersonating() {
|
|
273
|
-
return this.config.userId !== null;
|
|
288
|
+
return this.config.userId !== null && (this.config.gate?.() ?? true);
|
|
274
289
|
}
|
|
275
290
|
}
|
|
276
291
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { assertAccountAccess, hasAccountAccess, subscribeAccountAccess } from "@buoy-gg/shared-ui";
|
|
3
|
+
import { assertAccountAccess, getAccountAccess, hasAccountAccess, subscribeAccountAccess } from "@buoy-gg/shared-ui";
|
|
4
4
|
/**
|
|
5
5
|
* Impersonate Store - State Management with Persistence
|
|
6
6
|
*
|
|
@@ -109,8 +109,18 @@ class ImpersonateStore {
|
|
|
109
109
|
// Try to load persisted state synchronously
|
|
110
110
|
this.loadFromStorage();
|
|
111
111
|
Promise.resolve().then(() => {
|
|
112
|
+
// Only a sign-out ends the session: access that was admitted and is now
|
|
113
|
+
// locked. The license reports "locked" for a moment while it boots or
|
|
114
|
+
// reloads, before validation starts, and ending the session then wiped a
|
|
115
|
+
// restored impersonation for good. The per-request gate already keeps
|
|
116
|
+
// the header off whenever access isn't admitted.
|
|
117
|
+
let wasAdmitted = false;
|
|
112
118
|
const reconcile = () => {
|
|
113
|
-
|
|
119
|
+
const status = getAccountAccess().status;
|
|
120
|
+
if (status === "admitted") wasAdmitted = true;else if (status === "locked" && wasAdmitted) {
|
|
121
|
+
wasAdmitted = false;
|
|
122
|
+
this.disposeAccountSession();
|
|
123
|
+
}
|
|
114
124
|
};
|
|
115
125
|
subscribeAccountAccess(reconcile);
|
|
116
126
|
reconcile();
|
|
@@ -599,12 +609,16 @@ class ImpersonateStore {
|
|
|
599
609
|
void this.persist();
|
|
600
610
|
}
|
|
601
611
|
syncWithListener() {
|
|
602
|
-
// When paused, don't inject headers (pass null userId)
|
|
603
|
-
|
|
612
|
+
// When paused, don't inject headers (pass null userId). Account access is
|
|
613
|
+
// checked per request by the gate, not here: a session restored at launch
|
|
614
|
+
// syncs before the account check finishes, and reading it once here sent
|
|
615
|
+
// no header for the rest of the run, until a pause and resume re-synced.
|
|
616
|
+
const shouldInject = this.state.isActive && !this.state.isPaused;
|
|
604
617
|
setImpersonateConfig({
|
|
605
618
|
headerKey: this.state.headerKey,
|
|
606
619
|
userId: shouldInject ? this.state.currentUser?.id ?? null : null,
|
|
607
|
-
ignorePatterns: this.state.ignorePatterns.map(p => new RegExp(p))
|
|
620
|
+
ignorePatterns: this.state.ignorePatterns.map(p => new RegExp(p)),
|
|
621
|
+
gate: hasAccountAccess
|
|
608
622
|
});
|
|
609
623
|
|
|
610
624
|
// Ensure listener is started
|
package/lib/module/preset.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { getAsyncStorage } from './impersonate/hooks/asyncStoragePeer';
|
|
3
4
|
/**
|
|
4
5
|
* Impersonate Tool Preset
|
|
5
6
|
*
|
|
@@ -30,7 +31,7 @@ import { registerImpersonateSearchUsers } from "./sync/impersonateSyncAdapter";
|
|
|
30
31
|
|
|
31
32
|
let bootstrapStarted = false;
|
|
32
33
|
async function bootstrapImpersonate() {
|
|
33
|
-
if (bootstrapStarted) return;
|
|
34
|
+
if (typeof window === 'undefined' || bootstrapStarted) return;
|
|
34
35
|
bootstrapStarted = true;
|
|
35
36
|
|
|
36
37
|
// eslint-disable-next-line no-console
|
|
@@ -48,11 +49,10 @@ async function bootstrapImpersonate() {
|
|
|
48
49
|
// back to localStorage handled synchronously in its constructor.
|
|
49
50
|
try {
|
|
50
51
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
51
|
-
const
|
|
52
|
-
const AsyncStorage = mod?.default ?? mod;
|
|
52
|
+
const AsyncStorage = getAsyncStorage();
|
|
53
53
|
if (!AsyncStorage || typeof AsyncStorage.getItem !== "function") {
|
|
54
54
|
// eslint-disable-next-line no-console
|
|
55
|
-
console.warn("[impersonate] bootstrap: AsyncStorage shape unexpected", Object.keys(
|
|
55
|
+
console.warn("[impersonate] bootstrap: AsyncStorage shape unexpected", Object.keys(AsyncStorage ?? {}));
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
const adapter = {
|
|
@@ -107,7 +107,16 @@ function buildActions(onSearchUsers) {
|
|
|
107
107
|
stopImpersonation: () => impersonateStore.stopImpersonation(),
|
|
108
108
|
pauseImpersonation: () => impersonateStore.pauseImpersonation(),
|
|
109
109
|
resumeImpersonation: () => impersonateStore.resumeImpersonation(),
|
|
110
|
-
updateSettings: params =>
|
|
110
|
+
updateSettings: params => {
|
|
111
|
+
// The documented shape is { settings: {...} }, but the flat patch is the
|
|
112
|
+
// obvious guess and used to crash with "Cannot read property 'headerKey'
|
|
113
|
+
// of undefined". Accept both; refuse anything else by name.
|
|
114
|
+
|
|
115
|
+
const p = params ?? {};
|
|
116
|
+
const settings = p.settings ?? (["headerKey", "ignorePatterns", "showBanner", "dataNukeSettings"].some(k => k in p) ? p : undefined);
|
|
117
|
+
if (!settings) throw new Error("updateSettings needs { settings: { headerKey?, ignorePatterns?, showBanner?, dataNukeSettings? } }.");
|
|
118
|
+
return impersonateStore.updateSettings(settings);
|
|
119
|
+
},
|
|
111
120
|
removeFromHistory: params => impersonateStore.removeFromHistory(params.userId),
|
|
112
121
|
clearHistory: () => impersonateStore.clearHistory()
|
|
113
122
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function getAsyncStorage(): {
|
|
2
|
+
getItem(key: string): Promise<string | null>;
|
|
3
|
+
setItem(key: string, value: string): Promise<void>;
|
|
4
|
+
getAllKeys(): Promise<readonly string[]>;
|
|
5
|
+
multiRemove(keys: string[]): Promise<void>;
|
|
6
|
+
} | null;
|
|
7
|
+
//# sourceMappingURL=asyncStoragePeer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncStoragePeer.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/asyncStoragePeer.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,IAAI;IAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,UAAU,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAAG,IAAI,CAUnO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncStoragePeer.web.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/asyncStoragePeer.web.ts"],"names":[],"mappings":"AACA,wBAAgB,eAAe,2EAA2B"}
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useAutoClearAsyncStorage Hook
|
|
3
|
-
*
|
|
4
|
-
* Auto-detects AsyncStorage and provides a clear function.
|
|
5
|
-
* Follows the same pattern as useAutoClearReactQuery and useAutoClearRedux.
|
|
6
|
-
*
|
|
7
|
-
* This hook:
|
|
8
|
-
* 1. Dynamically requires @react-native-async-storage/async-storage
|
|
9
|
-
* 2. Returns a clearStorage function that removes all non-buoy keys
|
|
10
|
-
*
|
|
11
|
-
* IMPORTANT: This preserves all @buoy/* keys to avoid clearing our own state.
|
|
12
|
-
*/
|
|
13
1
|
export interface UseAutoClearAsyncStorageResult {
|
|
14
2
|
/** Whether AsyncStorage is available */
|
|
15
3
|
isAvailable: boolean;
|
|
@@ -18,6 +6,9 @@ export interface UseAutoClearAsyncStorageResult {
|
|
|
18
6
|
/** Function to clear all non-buoy keys from AsyncStorage */
|
|
19
7
|
clearStorage: (() => Promise<void>) | null;
|
|
20
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Safely attempt to load @react-native-async-storage/async-storage
|
|
11
|
+
*/
|
|
21
12
|
/**
|
|
22
13
|
* Hook to auto-detect AsyncStorage and provide clearing functionality.
|
|
23
14
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutoClearAsyncStorage.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useAutoClearAsyncStorage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAutoClearAsyncStorage.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useAutoClearAsyncStorage.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,8BAA8B;IAC7C,wCAAwC;IACxC,WAAW,EAAE,OAAO,CAAC;IACrB,qCAAqC;IACrC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,YAAY,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;CAC5C;AAMD;;GAEG;AAOH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,IAAI,8BAA8B,CA+DzE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI;IAC7C,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAcA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAutoClearReactQuery.web.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useAutoClearReactQuery.web.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AAC7E,wBAAgB,sBAAsB,IAAI,4BAA4B,CAOrE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UseAutoClearReduxOptions, UseAutoClearReduxResult } from './useAutoClearRedux';
|
|
2
|
+
export declare const REDUX_RESET_ACTION_TYPE = "@@RESET";
|
|
3
|
+
export declare function useAutoClearRedux({ resetActionType }?: UseAutoClearReduxOptions): UseAutoClearReduxResult;
|
|
4
|
+
//# sourceMappingURL=useAutoClearRedux.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAutoClearRedux.web.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useAutoClearRedux.web.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,eAAO,MAAM,uBAAuB,YAAY,CAAC;AACjD,wBAAgB,iBAAiB,CAAC,EAAE,eAAyC,EAAE,GAAE,wBAA6B,GAAG,uBAAuB,CAIvI"}
|
|
@@ -69,6 +69,12 @@ export interface ImpersonateListenerConfig {
|
|
|
69
69
|
userId: string | null;
|
|
70
70
|
/** URL patterns to ignore (won't inject header) */
|
|
71
71
|
ignorePatterns: RegExp[];
|
|
72
|
+
/**
|
|
73
|
+
* Checked on every request; false holds the header back. Lets a session
|
|
74
|
+
* restored before the account check finishes start sending the header the
|
|
75
|
+
* moment access is admitted, without anything re-syncing it.
|
|
76
|
+
*/
|
|
77
|
+
gate?: () => boolean;
|
|
72
78
|
}
|
|
73
79
|
/**
|
|
74
80
|
* Developer-configurable defaults for the impersonate tool
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/types/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,IAAI,EAAE,IAAI,CAAC;IACX,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,YAAY,EAAE,OAAO,CAAC;IACtB,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yDAAyD;IACzD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,yDAAyD;IACzD,UAAU,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mDAAmD;IACnD,cAAc,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/types/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonateListener.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateListener.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAqE1D,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,eAAe,CAAS;IAGhC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,eAAe,CAAuC;IAE9D;;;OAGG;IACH,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,cAAc,CAAqD;;IAe3E;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAY5D;;OAEG;IACH,SAAS,IAAI,yBAAyB;IAItC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;
|
|
1
|
+
{"version":3,"file":"impersonateListener.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateListener.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAqE1D,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,eAAe,CAAS;IAGhC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,eAAe,CAAuC;IAE9D;;;OAGG;IACH,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,cAAc,CAAqD;;IAe3E;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAY5D;;OAEG;IACH,SAAS,IAAI,yBAAyB;IAItC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;;;;OAKG;IACH,cAAc,IAAI,IAAI;IA4GtB,OAAO,CAAC,YAAY,CACqE;IAEzF;;;;;;OAMG;IACH,aAAa,IAAI,IAAI;IAmCrB;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,OAAO,CAE7B;CACF;AAQD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,mBAAmB,CAKzD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,CAAC,yBAAyB,CAAC,GACzC,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonateStore.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateStore.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,IAAI,EAEJ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAmClB,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAEzD,UAAU,aAAa;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAiDD;;;;;;;;GAQG;AACH,cAAM,gBAAgB;IACpB,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAGP;IAChB,OAAO,CAAC,mBAAmB,CAA8B;IACzD,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,iBAAiB,CAAoC;;
|
|
1
|
+
{"version":3,"file":"impersonateStore.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAI/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAwEjE;;;;;;;GAOG;AACH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC;AAWnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB;;;;;2BAkCxC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;uBAGnC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE;;;;;EAmB3H"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonateSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/impersonateSyncAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAErE,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAO7D,8EAA8E;AAC9E,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,kBAAkB,GAAG,IAAI,GACjC,IAAI,CAEN;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAW,CAAC;AAClD,eAAO,MAAM,8BAA8B,QAAY,CAAC;AAQxD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUrE;
|
|
1
|
+
{"version":3,"file":"impersonateSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/impersonateSyncAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAErE,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAO7D,8EAA8E;AAC9E,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,kBAAkB,GAAG,IAAI,GACjC,IAAI,CAEN;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAW,CAAC;AAClD,eAAO,MAAM,8BAA8B,QAAY,CAAC;AAQxD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUrE;AAgGD,UAAU,mCAAmC;IAC3C;;;OAGG;IACH,aAAa,EAAE,kBAAkB,CAAC;CACnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,aAAa,GACd,EAAE,mCAAmC;;uBAGjB,kBAAkB;0BACb,MAAM,IAAI;;8BA/DJ,OAAO;sCAQC,OAAO;;;;;;;kCAajB,OAAO;qCAYJ,OAAO;;;EAiCvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;uBAGhB,kBAAkB;0BACb,MAAM,IAAI;;8BA9EF,OAAO;sCAQC,OAAO;;;;;;;kCAajB,OAAO;qCAYJ,OAAO;;;CAsDvC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var yt=Object.defineProperty;var mo=Object.getOwnPropertyDescriptor;var ho=Object.getOwnPropertyNames;var yo=Object.prototype.hasOwnProperty;var fo=(t,e)=>{for(var o in e)yt(t,o,{get:e[o],enumerable:!0})},ht=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ho(e))!yo.call(t,r)&&r!==o&&yt(t,r,{get:()=>e[r],enumerable:!(n=mo(e,r))||n.enumerable});return t},I=(t,e,o)=>(ht(t,e,"default"),o&&ht(o,e,"default"));typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import So from"@buoy-gg/shared-ui/web/asyncStorage";function ve(){return So}import{useState as Ze,useCallback as he,useRef as Nt,useEffect as Lt}from"react";var f={};fo(f,{AccessibilityInfo:()=>Uo,ActivityIndicator:()=>De,Alert:()=>Ao,Animated:()=>Bo,AppRegistry:()=>No,AppState:()=>Lo,Appearance:()=>Do,BackHandler:()=>Eo,Button:()=>ko,CheckBox:()=>Go,Clipboard:()=>Vo,DeviceEventEmitter:()=>gr,Dimensions:()=>zo,Easing:()=>Oo,FlatList:()=>ae,I18nManager:()=>Wo,Image:()=>Zo,ImageBackground:()=>er,InteractionManager:()=>Fo,Keyboard:()=>Mo,KeyboardAvoidingView:()=>tr,LayoutAnimation:()=>Ko,Linking:()=>_o,LogBox:()=>pr,Modal:()=>Co,NativeEventEmitter:()=>Xo,NativeModules:()=>Po,PanResponder:()=>qo,Picker:()=>or,PixelRatio:()=>Qo,Platform:()=>jo,Pressable:()=>Io,ProgressBar:()=>rr,RefreshControl:()=>nr,SafeAreaView:()=>sr,ScrollView:()=>Be,SectionList:()=>ar,Share:()=>$o,StatusBar:()=>ir,StyleSheet:()=>H,Switch:()=>To,Text:()=>u,TextInput:()=>Ue,Touchable:()=>cr,TouchableHighlight:()=>xo,TouchableNativeFeedback:()=>lr,TouchableOpacity:()=>C,TouchableWithoutFeedback:()=>wo,UIManager:()=>Jo,Vibration:()=>Yo,View:()=>s,VirtualizedList:()=>dr,YellowBox:()=>ur,findNodeHandle:()=>Ro,unstable_createElement:()=>Ho,useColorScheme:()=>mr,useLocaleContext:()=>hr,useWindowDimensions:()=>yr});I(f,Xn);import*as Xn from"react-native-web";import{unstable_createElement as Ho,NativeModules as Po,AccessibilityInfo as Uo,Animated as Bo,Appearance as Do,AppRegistry as No,AppState as Lo,BackHandler as Eo,Clipboard as Vo,Dimensions as zo,Easing as Oo,I18nManager as Wo,Keyboard as Mo,InteractionManager as Fo,LayoutAnimation as Ko,Linking as _o,NativeEventEmitter as Xo,PanResponder as qo,PixelRatio as Qo,Platform as jo,Share as $o,StyleSheet as H,UIManager as Jo,Vibration as Yo,CheckBox as Go,FlatList as ae,Image as Zo,ImageBackground as er,KeyboardAvoidingView as tr,Picker as or,ProgressBar as rr,RefreshControl as nr,SafeAreaView as sr,SectionList as ar,StatusBar as ir,Touchable as cr,TouchableNativeFeedback as lr,VirtualizedList as dr,YellowBox as ur,LogBox as pr,DeviceEventEmitter as gr,useColorScheme as mr,useLocaleContext as hr,useWindowDimensions as yr}from"react-native-web";import*as S from"react-native-web";import{createElement as bo,forwardRef as vo}from"react";function z(t){let e=vo((n,r)=>{let{accessibilityState:g,accessibilityValue:c,...m}=n;for(let a of["busy","checked","disabled","expanded","selected"])g?.[a]!==void 0&&m[`aria-${a}`]===void 0&&(m[`aria-${a}`]=g[a]);for(let[a,h]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))c?.[a]!==void 0&&m[`aria-${h}`]===void 0&&(m[`aria-${h}`]=c[a]);return bo(t,{...m,ref:r})}),o=t.State;return o&&Object.assign(e,{State:o}),e.displayName=t.displayName??t.name??"NativeWebView",e}var s=z(S.View),u=z(S.Text),Ue=z(S.TextInput),C=z(S.TouchableOpacity),xo=z(S.TouchableHighlight),wo=z(S.TouchableWithoutFeedback),Io=z(S.Pressable),Be=z(S.ScrollView),Co=z(S.Modal),To=z(S.Switch),De=z(S.ActivityIndicator),ko=z(S.Button),Ro=S.findNodeHandle,Ao={alert(t,e,o,n){if(typeof document>"u")return;let r=document.createElement("dialog");r.dataset.buoyRoot="",r.setAttribute("aria-label",t),r.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let g=document.createElement("h2");if(g.textContent=t,g.style.cssText="font-size:18px;margin:0 0 12px",r.appendChild(g),e){let h=document.createElement("p");h.textContent=e,h.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",r.appendChild(h)}let c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let m=o?.length?o:[{text:"OK"}],a=()=>{r.close?.(),r.remove()};for(let h of m){let y=document.createElement("button");y.type="button",y.textContent=h.text??"OK",y.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${h.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,y.onclick=()=>{a(),h.onPress?.()},c.appendChild(y)}r.addEventListener("cancel",h=>{h.preventDefault(),n?.cancelable!==!1&&(a(),n?.onDismiss?.())}),r.appendChild(c),document.body.appendChild(r),r.showModal?r.showModal():r.setAttribute("open","")}};import{JsModal as ln,TabSelector as dn,ModalHeader as ye,buoyColors as un,night as Vt,Search as pn,TickProvider as Et,windowDragProps as gn}from"@buoy-gg/shared-ui/web";import{useState as xe,useEffect as xt,useCallback as W,useSyncExternalStore as Tr}from"react";import{assertAccountAccess as St,getAccountAccess as xr,hasAccountAccess as wr,subscribeAccountAccess as Ir}from"@buoy-gg/shared-ui/web";var ft=[/\/symbolicate$/,/\/logs$/,/\/debugger-proxy/,/\/reload$/,/\/launch-js-devtools/,/localhost:8081/,/100\.64\.\d+\.\d+:8081/,/10\.0\.\d+\.\d+:8081/,/\.hot-update\./,/__metro/];function Ne(t,e){for(let o of Object.keys(e))o.startsWith("__buoy")&&(t[o]=e[o])}var Le=class{constructor(){this.isListeningFlag=!1;this.patchedFetch=null;this.patchedXHROpen=null;this.patchedXHRSend=null;this.reportHeader=e=>this.shouldInjectHeader(e)?{[this.config.headerKey]:this.config.userId}:null;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:[...ft]}}setConfig(e){this.config={...this.config,...e},e.ignorePatterns&&(this.config.ignorePatterns=[...ft,...e.ignorePatterns])}getConfig(){return{...this.config}}shouldInjectHeader(e){return!this.config.userId||this.config.gate&&!this.config.gate()?!1:!this.config.ignorePatterns.some(o=>o.test(e))}extractUrl(e){return typeof e=="string"?e:e instanceof URL?e.href:e.url}startListening(){if(this.isListeningFlag)return;let e=globalThis.fetch,o=XMLHttpRequest.prototype.open,n=XMLHttpRequest.prototype.send;this.originalFetch=e.bind(globalThis),this.originalXHROpen=o,this.originalXHRSend=n;let r=this,g=async function(y,v){let T=r.extractUrl(y);if(r.shouldInjectHeader(T)){let D=v?.headers??(typeof y=="object"&&"headers"in y?y.headers:void 0),N=new Headers(D);return N.set(r.config.headerKey,r.config.userId),r.originalFetch(y,{...v,headers:N})}return r.originalFetch(y,v)};Ne(g,e),this.patchedFetch=g,globalThis.fetch=this.patchedFetch;let c=function(y,v,T=!0,D,N){let O=this;O._impersonateUrl=typeof v=="string"?v:v.href;let Z=typeof v=="string"?v:v.toString();return r.originalXHROpen.call(this,y,Z,T,D,N)},m=function(y){let v=this;return v._impersonateUrl&&r.shouldInjectHeader(v._impersonateUrl)&&this.setRequestHeader(r.config.headerKey,r.config.userId),r.originalXHRSend.call(this,y)};Ne(c,o),Ne(m,n),this.patchedXHROpen=c,this.patchedXHRSend=m,XMLHttpRequest.prototype.open=this.patchedXHROpen,XMLHttpRequest.prototype.send=this.patchedXHRSend;let a=globalThis,h=a.__buoyHeaderInjectors??(a.__buoyHeaderInjectors=[]);h.includes(this.reportHeader)||h.push(this.reportHeader),this.isListeningFlag=!0}stopListening(){if(!this.isListeningFlag)return;this.patchedFetch&&globalThis.fetch===this.patchedFetch&&(globalThis.fetch=this.originalFetch),this.patchedXHROpen&&XMLHttpRequest.prototype.open===this.patchedXHROpen&&(XMLHttpRequest.prototype.open=this.originalXHROpen),this.patchedXHRSend&&XMLHttpRequest.prototype.send===this.patchedXHRSend&&(XMLHttpRequest.prototype.send=this.originalXHRSend),this.patchedFetch=null,this.patchedXHROpen=null,this.patchedXHRSend=null;let e=globalThis.__buoyHeaderInjectors,o=e?.indexOf(this.reportHeader)??-1;e&&o>=0&&e.splice(o,1),this.isListeningFlag=!1}get isListening(){return this.isListeningFlag}get isImpersonating(){return this.config.userId!==null&&(this.config.gate?.()??!0)}},ie=null;function L(){return ie||(ie=new Le),ie}function fr(){L().startListening()}function Sr(){L().stopListening()}function Ee(t){L().setConfig(t)}function br(){return ie?.isImpersonating??!1}function vr(){return ie?.getConfig().userId??null}var ce="@buoy/impersonate/state",Cr=10,vt={reactQuery:!0,redux:!0,asyncStorage:!1,mmkv:!1},re={isActive:!1,isPaused:!1,currentUser:null,headerKey:"x-impersonate-user-id",ignorePatterns:[],dataNukeSettings:vt,showBanner:!0,history:[]},Ve=!1,bt={getItem:t=>{try{return typeof localStorage<"u"?localStorage.getItem(t):null}catch{return null}},setItem:(t,e)=>{try{typeof localStorage<"u"&&localStorage.setItem(t,e)}catch{}},removeItem:t=>{try{typeof localStorage<"u"&&localStorage.removeItem(t)}catch{}}},ze=class{constructor(){this.state={...re};this.listeners=new Set;this.nukeCallbacks={};this.isInitialized=!1;this.asyncStorageRef=null;this.storageReadyPromise=null;this.resolveStorageReady=null;this.developerDefaults=null;this.getSnapshot=()=>this.state;this.subscribe=e=>(this.listeners.add(e),()=>this.listeners.delete(e));this.remoteHandler=null;this.loadFromStorage(),Promise.resolve().then(()=>{let e=!1,o=()=>{let n=xr().status;n==="admitted"?e=!0:n==="locked"&&e&&(e=!1,this.disposeAccountSession())};Ir(o),o()}),typeof localStorage<"u"?this.storageReadyPromise=Promise.resolve():this.storageReadyPromise=new Promise(e=>{this.resolveStorageReady=e})}loadFromStorage(){try{let e=bt.getItem(ce),o=this.getEffectiveDefaults();if(e){let n=JSON.parse(e);this.state={...re,headerKey:n.headerKey??o.headerKey,ignorePatterns:n.ignorePatterns??re.ignorePatterns,dataNukeSettings:{...o.dataNukeSettings,...n.dataNukeSettings},showBanner:n.showBanner??o.showBanner,history:n.history??[],isActive:n.isActive??!1,isPaused:n.isPaused??!1,currentUser:n.currentUser??null},this.state.isActive&&this.state.currentUser&&this.syncWithListener()}else this.state={...re,headerKey:o.headerKey,dataNukeSettings:o.dataNukeSettings,showBanner:o.showBanner};this.isInitialized=!0}catch{this.isInitialized=!0}}setAsyncStorage(e){this.asyncStorageRef=e,this.resolveStorageReady&&(this.resolveStorageReady(),this.resolveStorageReady=null)}setDeveloperDefaults(e){this.developerDefaults=e;let o=this.getEffectiveDefaults();this.isInitialized||(this.state={...this.state,headerKey:o.headerKey,dataNukeSettings:o.dataNukeSettings,showBanner:o.showBanner})}getEffectiveDefaults(){return{headerKey:this.developerDefaults?.headerKey??re.headerKey,dataNukeSettings:{...vt,...this.developerDefaults?.dataNukeSettings},showBanner:this.developerDefaults?.showBanner??re.showBanner}}getDeveloperDefaults(){return this.developerDefaults}async initializeAsync(e){if(e){this.asyncStorageRef=e;try{let o=await e.getItem(ce);if(console.log(`[impersonate] initializeAsync read STORAGE_KEY=${ce} stored=${o?o.slice(0,200):"null"}`),o){let n=JSON.parse(o);this.state={...this.state,headerKey:n.headerKey??this.state.headerKey,ignorePatterns:n.ignorePatterns??this.state.ignorePatterns,dataNukeSettings:{...this.state.dataNukeSettings,...n.dataNukeSettings},showBanner:n.showBanner??this.state.showBanner,history:n.history??this.state.history,isActive:n.isActive??this.state.isActive,isPaused:n.isPaused??this.state.isPaused,currentUser:n.currentUser??this.state.currentUser},this.state.isActive&&this.state.currentUser&&this.syncWithListener(),this.notify()}}catch{}}}registerNukeCallbacks(e){this.nukeCallbacks={...this.nukeCallbacks,...e}}getState(){return{...this.state}}setRemoteHandler(e){this.remoteHandler=e}replaceState(e){this.state=e,this.notify()}async startImpersonation(e){if(St(),this.remoteHandler){this.remoteHandler("startImpersonation",{user:e});return}let n=[{user:e,lastUsedAt:new Date().toISOString()},...this.state.history.filter(r=>r.user.id!==e.id)].slice(0,Cr);this.state={...this.state,isActive:!0,currentUser:e,history:n},this.syncWithListener(),this.notify(),await this.executeDataNuke(),await this.persist()}async stopImpersonation(){if(this.remoteHandler){this.remoteHandler("stopImpersonation");return}console.log(`[impersonate] stopImpersonation: isActive ${this.state.isActive} -> false, listeners=${this.listeners.size}`),this.state={...this.state,isActive:!1,isPaused:!1,currentUser:null},this.syncWithListener(),this.notify(),await this.executeDataNuke(),await this.persist()}async pauseImpersonation(){if(this.remoteHandler){this.remoteHandler("pauseImpersonation");return}!this.state.isActive||this.state.isPaused||(this.state={...this.state,isPaused:!0},this.syncWithListener(),await this.persist(),this.notify())}async resumeImpersonation(){if(St(),this.remoteHandler){this.remoteHandler("resumeImpersonation");return}!this.state.isActive||!this.state.isPaused||(this.state={...this.state,isPaused:!1},this.syncWithListener(),await this.persist(),this.notify())}async quickSwitch(e){return this.startImpersonation(e)}async updateSettings(e){if(this.remoteHandler){this.remoteHandler("updateSettings",{settings:e});return}this.state={...this.state,headerKey:e.headerKey??this.state.headerKey,ignorePatterns:e.ignorePatterns??this.state.ignorePatterns,showBanner:e.showBanner??this.state.showBanner,dataNukeSettings:e.dataNukeSettings?{...this.state.dataNukeSettings,...e.dataNukeSettings}:this.state.dataNukeSettings},(e.headerKey||e.ignorePatterns)&&this.syncWithListener(),await this.persist(),this.notify()}async removeFromHistory(e){if(this.remoteHandler){this.remoteHandler("removeFromHistory",{userId:e});return}this.state={...this.state,history:this.state.history.filter(o=>o.user.id!==e)},await this.persist(),this.notify()}async clearHistory(){if(this.remoteHandler){this.remoteHandler("clearHistory");return}this.state={...this.state,history:[]},await this.persist(),this.notify()}async executeDataNuke(){if(!Ve){Ve=!0;try{let{dataNukeSettings:e}=this.state,o=[];e.reactQuery&&this.nukeCallbacks.reactQuery&&o.push(Promise.resolve(this.nukeCallbacks.reactQuery())),e.redux&&this.nukeCallbacks.redux&&o.push(Promise.resolve(this.nukeCallbacks.redux())),e.asyncStorage&&this.nukeCallbacks.asyncStorage&&o.push(Promise.resolve(this.nukeCallbacks.asyncStorage())),e.mmkv&&this.nukeCallbacks.mmkv&&o.push(Promise.resolve(this.nukeCallbacks.mmkv())),await Promise.allSettled(o)}finally{setTimeout(()=>{Ve=!1},100)}}}disposeAccountSession(){this.remoteHandler||!this.state.isActive||(this.state={...this.state,isActive:!1,isPaused:!1,currentUser:null},this.syncWithListener(),this.notify(),this.persist())}syncWithListener(){let e=this.state.isActive&&!this.state.isPaused;Ee({headerKey:this.state.headerKey,userId:e?this.state.currentUser?.id??null:null,ignorePatterns:this.state.ignorePatterns.map(o=>new RegExp(o)),gate:wr}),L().isListening||L().startListening()}async persist(){this.storageReadyPromise&&await this.storageReadyPromise;let e={headerKey:this.state.headerKey,ignorePatterns:this.state.ignorePatterns,dataNukeSettings:this.state.dataNukeSettings,showBanner:this.state.showBanner,history:this.state.history,isActive:this.state.isActive,isPaused:this.state.isPaused,currentUser:this.state.currentUser},o=JSON.stringify(e);try{this.asyncStorageRef?(await this.asyncStorageRef.setItem(ce,o),console.log(`[impersonate] persist -> AsyncStorage isActive=${e.isActive} userId=${e.currentUser?.id??"null"}`)):(bt.setItem(ce,o),console.log(`[impersonate] persist -> localStorage isActive=${e.isActive} userId=${e.currentUser?.id??"null"}`))}catch(n){console.warn("[impersonate] persist failed",n)}}notify(){this.listeners.forEach(e=>{try{e(this.state)}catch{}})}},l=new ze;function Oe(t={}){let[e,o]=xe(""),[n,r]=xe([]),[g,c]=xe(!1),[m,a]=xe(null),h=Tr(l.subscribe,l.getSnapshot,l.getSnapshot);xt(()=>{l.registerNukeCallbacks({reactQuery:t.onClearReactQuery,redux:t.onClearRedux,asyncStorage:t.onClearAsyncStorage,mmkv:t.onClearMMKV})},[t.onClearReactQuery,t.onClearRedux,t.onClearAsyncStorage,t.onClearMMKV]),xt(()=>{let b=!0;return(async()=>{try{let te=await import("@buoy-gg/shared-ui/web/asyncStorage").then(J=>J.default),oe={getItem:J=>te.getItem(J),setItem:(J,He)=>te.setItem(J,He)};l.setAsyncStorage(oe),b&&await l.initializeAsync(oe)}catch{}})(),L().isListening||L().startListening(),()=>{b=!1}},[]);let y=W(async b=>{if(o(b),a(null),!b.trim()){r([]);return}if(!t.onSearchUsers){a("Search not configured"),r([]);return}c(!0);try{let w=await t.onSearchUsers(b);r(w)}catch(w){a(w instanceof Error?w.message:"Search failed"),r([])}finally{c(!1)}},[t.onSearchUsers]),v=W(()=>{o(""),r([]),a(null)},[]),T=W(async b=>{await l.startImpersonation(b)},[]),D=W(async()=>{await l.stopImpersonation()},[]),N=W(async b=>{await l.quickSwitch(b)},[]),O=W(async b=>{await l.updateSettings({headerKey:b})},[]),Z=W(async b=>{await l.updateSettings({ignorePatterns:b})},[]),Q=W(async b=>{await l.updateSettings({dataNukeSettings:b})},[]),ee=W(async b=>{await l.updateSettings({showBanner:b})},[]),F=W(async b=>{await l.removeFromHistory(b)},[]),se=W(async()=>{await l.clearHistory()},[]);return{isActive:h.isActive,currentUser:h.currentUser,headerKey:h.headerKey,ignorePatterns:h.ignorePatterns,dataNukeSettings:h.dataNukeSettings,showBanner:h.showBanner,history:h.history,searchQuery:e,searchResults:n,isSearching:g,searchError:m,searchUsers:y,clearSearch:v,startImpersonation:T,stopImpersonation:D,quickSwitch:N,updateHeaderKey:O,updateIgnorePatterns:Z,updateDataNukeSettings:Q,updateShowBanner:ee,removeFromHistory:F,clearHistory:se}}import{useCallback as kr}from"react";import{dispatchToolAction as wt,getToolAdapters as Rr}from"@buoy-gg/shared-ui/web";function It(){let t=!!Rr().query,e=kr(async()=>{await wt("query","clearQueryCache"),await wt("query","clearMutationCache")},[]);return{isAvailable:t,error:t?null:"Connect React Query to Buoy or provide onClearReactQuery.",clearCache:t?e:null}}import{useCallback as Ar}from"react";import{dispatchToolAction as Hr,getToolAdapters as Pr}from"@buoy-gg/shared-ui/web";var Ur="@@RESET";function Ct({resetActionType:t=Ur}={}){let e=!!Pr().redux,o=Ar(async()=>{await Hr("redux","dispatch",{action:{type:t}})},[t]);return{isAvailable:e,error:e?null:"Connect Redux to Buoy or provide onClearRedux.",resetStore:e?o:null}}import{useCallback as Br,useMemo as Dr,useState as Tt,useEffect as Nr}from"react";var We=!1;function kt(){let[t,e]=Tt(null),[o,n]=Tt(null);Nr(()=>{let c=ve();c?(e(c),n(null)):n("@react-native-async-storage/async-storage is not installed")},[]);let r=Br(async()=>{if(!We){We=!0;try{if(t){let m=(await t.getAllKeys()).filter(a=>!a.startsWith("@buoy/")&&!a.startsWith("@buoy-"));m.length>0&&await t.multiRemove([...m])}}finally{setTimeout(()=>{We=!1},100)}}},[t]);return Dr(()=>!t||o?{isAvailable:!1,error:o||"@react-native-async-storage/async-storage is not available",clearStorage:null}:{isAvailable:!0,error:null,clearStorage:r},[t,o,r])}import{useCallback as Xr}from"react";import{SectionHeader as Ke,EmptyState as qr,night as U,Search as Qr,AlertTriangle as Ht,Users as jr}from"@buoy-gg/shared-ui/web";import{buoyColors as Fe,night as V,Play as Mr,X as Fr,PowerToggleButton as Kr,monoFont as _r}from"@buoy-gg/shared-ui/web";import{useMemo as Rt}from"react";import{buoyColors as Lr,night as Er}from"@buoy-gg/shared-ui/web";import{jsx as Me,jsxs as Wr}from"react/jsx-runtime";var At=["#6366F1","#8B5CF6","#EC4899","#F43F5E","#F97316","#EAB308","#22C55E","#14B8A6","#06B6D4","#3B82F6"],Vr={small:{container:24,font:10,indicator:8},medium:{container:36,font:14,indicator:10},large:{container:44,font:16,indicator:12}};function zr(t){if(!t)return"?";if(t.includes("@"))return t.charAt(0).toUpperCase();let e=t.trim().split(/\s+/);return e.length===1?e[0].charAt(0).toUpperCase():(e[0].charAt(0)+e[e.length-1].charAt(0)).toUpperCase()}function Or(t){let e=0;for(let o=0;o<t.length;o++)e=t.charCodeAt(o)+((e<<5)-e);return At[Math.abs(e)%At.length]}function ne({userId:t,name:e,size:o="medium",showActiveIndicator:n=!1,backgroundColor:r}){let g=Vr[o],c=Rt(()=>r??Or(t),[t,r]),m=Rt(()=>zr(e),[e]);return Wr(s,{style:we.wrapper,children:[Me(s,{style:[we.container,{width:g.container,height:g.container,borderRadius:g.container/2,backgroundColor:c}],children:Me(u,{style:[we.initials,{fontSize:g.font}],children:m})}),n&&Me(s,{style:[we.indicator,{width:g.indicator,height:g.indicator,borderRadius:g.indicator/2,right:-1,bottom:-1}]})]})}var we=H.create({wrapper:{position:"relative"},container:{alignItems:"center",justifyContent:"center"},initials:{color:"#FFFFFF",fontWeight:"600",letterSpacing:.5},indicator:{position:"absolute",backgroundColor:Lr.success,borderWidth:2,borderColor:Er.color.surface}});import{jsx as E,jsxs as le}from"react/jsx-runtime";function Ie({user:t,isActive:e=!1,onPress:o,onStop:n,onRemove:r,showRemoveButton:g=!1,lastUsedTime:c,variant:m="default"}){let a=t.displayName||t.email||t.id,h=t.email&&t.displayName,y=typeof t.metadata?.role=="string"?t.metadata.role:null;return le(C,{testID:`buoy-impersonate-user-${t.id}`,style:[P.container,e&&P.activeContainer,m==="compact"&&P.compactContainer],onPress:o,disabled:e,activeOpacity:.7,children:[E(s,{style:P.avatarSection,children:E(ne,{userId:t.id,name:a,size:m==="compact"?"small":"medium",showActiveIndicator:e})}),le(s,{style:P.content,children:[le(s,{style:P.nameRow,children:[E(u,{style:[P.name,e&&P.activeName],numberOfLines:1,children:a}),y?E(s,{style:P.roleBadge,children:E(u,{style:P.roleBadgeText,children:y.toUpperCase()})}):null]}),h&&E(u,{style:P.email,numberOfLines:1,children:t.email}),E(s,{style:P.metadataRow,children:le(u,{style:P.userId,children:["ID: ",t.id]})})]}),le(s,{style:P.actions,children:[e?E(Kr,{isEnabled:!0,onToggle:n||(()=>{}),accessibilityLabel:"Stop impersonation"}):E(C,{style:P.actionButton,onPress:o,activeOpacity:.7,children:E(Mr,{size:14,color:V.color.onAccent})}),g&&r&&!e&&E(C,{style:P.removeButton,onPress:r,activeOpacity:.7,children:E(Fr,{size:12,color:V.color.textTertiary})})]}),c?E(u,{style:P.lastUsed,children:c}):null]})}var P=H.create({container:{flexDirection:"row",alignItems:"center",backgroundColor:V.color.surface,borderRadius:10,borderWidth:1,borderColor:V.color.border,padding:12,gap:12},activeContainer:{backgroundColor:Fe.success+"10",borderColor:Fe.success+"40"},compactContainer:{padding:10,gap:10},avatarSection:{flexShrink:0},content:{flex:1,minWidth:0},nameRow:{flexDirection:"row",alignItems:"center",gap:8,marginBottom:2},name:{fontSize:15,fontWeight:"600",color:V.color.text,flexShrink:1},activeName:{color:Fe.success},roleBadge:{backgroundColor:V.color.surfaceElevated,paddingHorizontal:6,paddingVertical:2,borderRadius:4},roleBadgeText:{fontSize:9,fontWeight:"700",color:V.color.textTertiary,letterSpacing:.5},email:{fontSize:13,color:V.color.textSecondary,marginBottom:4},metadataRow:{flexDirection:"row",alignItems:"center",gap:4},userId:{fontSize:11,color:V.color.textTertiary,fontFamily:_r},lastUsed:{position:"absolute",bottom:8,right:10,fontSize:10,color:V.color.textTertiary},actions:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:0},actionButton:{width:36,height:36,borderRadius:8,backgroundColor:V.color.accent,alignItems:"center",justifyContent:"center"},removeButton:{width:28,height:28,borderRadius:6,backgroundColor:V.color.surfaceElevated,borderWidth:1,borderColor:V.color.border,alignItems:"center",justifyContent:"center"}});import{jsx as A,jsxs as K}from"react/jsx-runtime";function _e({currentUser:t,searchQuery:e,searchResults:o,isSearching:n,searchError:r,onSelectUser:g,onStopImpersonation:c,searchAvailable:m=!0}){let a=Xr(({item:h})=>{let y=t?.id===h.id;return A(Ie,{user:h,isActive:y,onPress:()=>!y&&g(h),onStop:y?c:void 0})},[t,g,c]);return K(s,{style:R.container,children:[!m&&A(s,{style:R.section,children:K(s,{style:R.warningCard,children:[A(Ht,{size:18,color:U.color.warning}),K(s,{style:R.warningContent,children:[A(u,{style:R.warningTitle,children:"Search Not Available"}),A(u,{style:R.warningText,children:"Configure the onSearchUsers callback to enable user search."})]})]})}),n&&K(s,{style:R.loadingContainer,children:[A(De,{size:"small",color:U.color.accent}),A(u,{style:R.loadingText,children:"Searching users..."})]}),r?A(s,{style:R.section,children:K(s,{style:R.errorCard,children:[A(Ht,{size:16,color:U.color.danger}),A(u,{style:R.errorText,children:r})]})}):null,o.length>0&&K(s,{style:R.resultsSection,children:[K(Ke,{children:[A(Ke.Title,{children:"Results"}),A(Ke.Badge,{count:o.length})]}),A(ae,{data:o,keyExtractor:h=>h.id,renderItem:a,ItemSeparatorComponent:()=>A(s,{style:R.separator}),contentContainerStyle:R.listContent,showsVerticalScrollIndicator:!1})]}),!!e&&!n&&o.length===0&&!r&&K(s,{style:R.emptyStateContainer,children:[A(s,{style:R.emptyStateIcon,children:A(jr,{size:28,color:U.color.textTertiary})}),A(u,{style:R.emptyStateTitle,children:"No users found"}),K(u,{style:R.emptyStateDescription,children:['No results for "',e,'"']}),A(u,{style:R.emptyStateHint,children:"Try a different search term"})]}),!e&&o.length===0&&!n&&m&&A(qr,{title:"Search for users",description:"Tap the search icon in the header to find users by email, name, or ID",icon:Qr,variant:"minimal"})]})}var R=H.create({container:{flex:1},section:{padding:16,paddingBottom:8},loadingContainer:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:10,paddingVertical:20},loadingText:{fontSize:13,color:U.color.textSecondary},resultsSection:{flex:1,paddingHorizontal:16},listContent:{paddingBottom:16},separator:{height:8},warningCard:{flexDirection:"row",alignItems:"flex-start",gap:12,backgroundColor:U.color.warningSoft,borderRadius:10,borderWidth:1,borderColor:U.color.warning+"25",padding:14},warningContent:{flex:1},warningTitle:{fontSize:14,fontWeight:"600",color:U.color.warning,marginBottom:4},warningText:{fontSize:13,color:U.color.textSecondary,lineHeight:18},errorCard:{flexDirection:"row",alignItems:"center",gap:10,backgroundColor:U.color.dangerSoft,borderRadius:10,borderWidth:1,borderColor:U.color.danger+"25",padding:12},errorText:{flex:1,fontSize:13,color:U.color.danger},emptyStateContainer:{flex:1,alignItems:"center",justifyContent:"center",paddingHorizontal:32,paddingVertical:48},emptyStateIcon:{width:56,height:56,borderRadius:28,backgroundColor:U.color.surfaceElevated,alignItems:"center",justifyContent:"center",marginBottom:16},emptyStateTitle:{fontSize:16,fontWeight:"600",color:U.color.text,marginBottom:6},emptyStateDescription:{fontSize:14,color:U.color.textSecondary,textAlign:"center",marginBottom:8},emptyStateHint:{fontSize:12,color:U.color.textTertiary}});import{useCallback as $r}from"react";import{night as j,Trash2 as Jr,useRelativeTime as Yr,ToolEmptyState as Gr}from"@buoy-gg/shared-ui/web";import{jsx as M,jsxs as Pt}from"react/jsx-runtime";function Zr({item:t,isActive:e,onSelect:o,onStop:n,onRemove:r,showRemoveButton:g}){let c=Yr(new Date(t.lastUsedAt));return M(Ie,{user:t.user,isActive:e,onPress:()=>!e&&o(t.user),onStop:e?n:void 0,onRemove:r,showRemoveButton:g,lastUsedTime:c})}function Xe({history:t,currentUserId:e,onSelectUser:o,onStopImpersonation:n,onRemoveFromHistory:r,onClearHistory:g}){let c=$r(({item:m})=>{let a=e===m.user.id;return M(Zr,{item:m,isActive:a,onSelect:o,onStop:n,onRemove:r?()=>r(m.user.id):void 0,showRemoveButton:!!r})},[e,o,n,r]);return t.length===0?M(Gr,{testID:"buoy-impersonate-history-empty",otto:"disguise",title:"No History",message:"Users you impersonate will appear here for quick access"}):Pt(s,{style:_.container,children:[Pt(s,{style:_.headerRow,children:[M(u,{style:_.headerTitle,children:"Recent"}),M(s,{style:_.headerBadge,children:M(u,{style:_.headerBadgeText,children:t.length})}),M(s,{style:_.headerSpacer}),g&&M(C,{style:_.clearButton,onPress:g,activeOpacity:.7,children:M(Jr,{size:12,color:j.color.textTertiary})})]}),M(ae,{data:t,keyExtractor:m=>m.user.id,renderItem:c,ItemSeparatorComponent:()=>M(s,{style:_.separator}),contentContainerStyle:_.listContent,showsVerticalScrollIndicator:!1})]})}var _=H.create({container:{flex:1,paddingHorizontal:16},headerRow:{flexDirection:"row",alignItems:"center",paddingVertical:10,gap:8},headerTitle:{fontSize:12,fontWeight:"600",color:j.color.textTertiary,textTransform:"uppercase",letterSpacing:.5},headerBadge:{backgroundColor:j.color.surfaceElevated,paddingHorizontal:6,paddingVertical:2,borderRadius:4},headerBadgeText:{fontSize:10,fontWeight:"600",color:j.color.textTertiary},headerSpacer:{flex:1},clearButton:{width:24,height:24,alignItems:"center",justifyContent:"center",backgroundColor:j.color.surfaceElevated,borderRadius:4},listContent:{paddingBottom:20},separator:{height:8},emptyContainer:{flex:1,alignItems:"center",justifyContent:"center",paddingHorizontal:32,paddingVertical:48},emptyIcon:{width:56,height:56,borderRadius:28,backgroundColor:j.color.surfaceElevated,alignItems:"center",justifyContent:"center",marginBottom:16},emptyTitle:{fontSize:16,fontWeight:"600",color:j.color.text,marginBottom:6},emptyDescription:{fontSize:14,color:j.color.textSecondary,textAlign:"center"}});import{useState as Ce,useEffect as qe,useMemo as Qe}from"react";import{CollapsibleSection as de,buoyColors as me,night as p,Settings as en,AlertTriangle as Ut,Info as tn,Zap as on,RefreshCw as rn,Check as Je,X as Dt,Copy as Bt,Eye as nn,copyToClipboard as sn,ToggleRow as an,monoFont as je}from"@buoy-gg/shared-ui/web";import{DataViewer as cn}from"@buoy-gg/shared-ui/web/dataViewer";import{Fragment as Ye,jsx as d,jsxs as x}from"react/jsx-runtime";var ue="x-impersonate-user-id",$e=!0,pe={reactQuery:!0,redux:!0,asyncStorage:!1,mmkv:!1};function ge({label:t,description:e,value:o,onChange:n,recommended:r,dangerous:g,detected:c}){let m=x(Ye,{children:[c!==void 0&&x(s,{style:[i.detectedBadge,c?i.detectedBadgeActive:i.detectedBadgeInactive],children:[c?d(Je,{size:10,color:me.success}):d(Dt,{size:10,color:p.color.textTertiary}),d(u,{style:[i.detectedText,c?i.detectedTextActive:i.detectedTextInactive],children:c?"Detected":"Not Detected"})]}),r&&c!==!1&&x(s,{style:i.recommendedBadge,children:[d(on,{size:10,color:p.color.accent}),d(u,{style:i.recommendedText,children:"Recommended"})]})]});return d(an,{variant:"plain",label:t,description:e,value:o,onValueChange:n,tone:g?"warning":"accent",emphasizeLabel:g,accessory:m})}function Ge({headerKey:t,settings:e,showBanner:o,onSave:n,onShowBannerChange:r,detectionStatus:g}){let[c,m]=Ce(t),[a,h]=Ce(e),[y,v]=Ce(o),[T,D]=Ce(!1);qe(()=>{m(t)},[t]),qe(()=>{h(e)},[e]),qe(()=>{v(o)},[o]);let N=Qe(()=>c!==t||a.reactQuery!==e.reactQuery||a.redux!==e.redux||a.asyncStorage!==e.asyncStorage||a.mmkv!==e.mmkv,[c,a,t,e]),O=Qe(()=>c===ue&&y===$e&&a.reactQuery===pe.reactQuery&&a.redux===pe.redux&&a.asyncStorage===pe.asyncStorage&&a.mmkv===pe.mmkv,[c,y,a]),Z=()=>{n(c.trim()||ue,a,y)},Q=()=>{m(t),h(e),v(o)},ee=()=>{m(ue),h(pe),v($e),r($e)},F=(w,te)=>{h(oe=>({...oe,[w]:te}))},se=Qe(()=>({defaults:{headerKey:c,showBanner:y,dataNukeSettings:{reactQuery:a.reactQuery,redux:a.redux,asyncStorage:a.asyncStorage,mmkv:a.mmkv}}}),[c,y,a]),b=async()=>{let w=`defaults: {
|
|
3
|
+
headerKey: '${c}',
|
|
4
|
+
showBanner: ${y},
|
|
5
|
+
dataNukeSettings: {
|
|
6
|
+
reactQuery: ${a.reactQuery},
|
|
7
|
+
redux: ${a.redux},
|
|
8
|
+
asyncStorage: ${a.asyncStorage},
|
|
9
|
+
mmkv: ${a.mmkv},
|
|
10
|
+
},
|
|
11
|
+
},`;try{await sn(w),D(!0),setTimeout(()=>D(!1),2e3)}catch{}};return x(Be,{style:i.container,contentContainerStyle:i.contentContainer,children:[N&&d(s,{style:i.actionBar,children:x(s,{style:i.actionBarContent,children:[d(u,{style:i.unsavedText,children:"Unsaved changes"}),x(s,{style:i.actionButtons,children:[x(C,{style:i.discardButton,onPress:Q,children:[d(Dt,{size:14,color:p.color.textSecondary}),d(u,{style:i.discardButtonText,children:"Discard"})]}),x(C,{style:i.saveButton,onPress:Z,children:[d(Je,{size:14,color:p.color.onAccent}),d(u,{style:i.saveButtonText,children:"Save"})]})]})]})}),d(de,{title:"Header Configuration",icon:en,defaultOpen:!0,variant:"bordered",children:x(s,{style:i.sectionContent,children:[d(u,{style:i.inputLabel,children:"Header Key"}),d(Ue,{style:i.input,value:c,onChangeText:m,placeholder:"x-impersonate-user-id",placeholderTextColor:p.color.placeholder,autoCapitalize:"none",autoCorrect:!1}),x(s,{style:i.inputFooter,children:[d(u,{style:i.helperText,children:"The HTTP header key used for impersonation. Value will be the user ID."}),c!==ue&&d(C,{onPress:()=>m(ue),style:i.resetLink,children:d(u,{style:i.resetLinkText,children:"Reset to default"})})]})]})}),d(de,{title:"Display",icon:nn,defaultOpen:!0,variant:"bordered",children:d(s,{style:i.sectionContent,children:d(s,{style:i.togglesCard,children:d(ge,{label:"Floating Banner",description:"Show a floating banner when impersonation is active",value:y,onChange:w=>{v(w),r(w)},recommended:!0})})})}),d(de,{title:"Data Clearing",icon:Ut,defaultOpen:!0,variant:"bordered",children:x(s,{style:i.sectionContent,children:[d(u,{style:i.sectionDescription,children:"Choose what data to clear when impersonation starts or stops. This ensures you see fresh data for the impersonated user."}),x(s,{style:i.togglesCard,children:[d(ge,{label:"React Query",description:"Clear query cache and cancel pending queries",value:a.reactQuery,onChange:w=>F("reactQuery",w),recommended:!0,detected:g?.reactQuery}),d(s,{style:i.divider}),d(ge,{label:"Redux",description:"Reset Redux store to initial state",value:a.redux,onChange:w=>F("redux",w),recommended:!0,detected:g?.redux})]}),x(s,{style:i.advancedSection,children:[d(u,{style:i.advancedLabel,children:"Storage Options"}),x(s,{style:[i.togglesCard,i.dangerousCard],children:[d(ge,{label:"AsyncStorage",description:"Clear app data (preserves @buoy/* keys)",value:a.asyncStorage,onChange:w=>F("asyncStorage",w),dangerous:!0,detected:g?.asyncStorage}),d(s,{style:i.divider}),d(ge,{label:"MMKV",description:"Clear MMKV storage (preserves @buoy/* keys)",value:a.mmkv,onChange:w=>F("mmkv",w),dangerous:!0,detected:g?.mmkv})]})]}),(a.asyncStorage||a.mmkv)&&x(s,{style:i.warningCard,children:[d(Ut,{size:16,color:p.color.warning}),x(s,{style:i.warningContent,children:[d(u,{style:i.warningTitle,children:"Storage Clearing Enabled"}),d(u,{style:i.warningText,children:"This will remove app data like settings and cached content. Auth tokens managed by @buoy/* are preserved."})]})]})]})}),!O&&x(C,{style:i.restoreButton,onPress:ee,children:[d(rn,{size:14,color:p.color.textSecondary}),d(u,{style:i.restoreButtonText,children:"Restore Defaults"})]}),d(de,{title:"How It Works",icon:tn,defaultOpen:!1,variant:"bordered",children:x(s,{style:i.sectionContent,children:[d(u,{style:i.infoText,children:"When impersonation is enabled, the configured header is automatically added to all outgoing fetch and XMLHttpRequest calls."}),d(u,{style:[i.infoText,i.infoTextSpaced],children:"Your backend should check for this header and return data for the specified user ID instead of the authenticated user."}),x(s,{style:i.codeBlock,children:[d(u,{style:i.codeComment,children:"// Example request header"}),x(u,{style:i.codeText,children:[c||"x-impersonate-user-id",": ",d(u,{style:i.codeValue,children:"user_123"})]})]})]})}),d(de,{title:"Export Configuration",icon:Bt,defaultOpen:!1,variant:"bordered",children:x(s,{style:i.sectionContent,children:[d(u,{style:i.infoText,children:"Copy current settings to use in createImpersonateTool()."}),d(s,{style:i.dataViewerContainer,children:d(cn,{title:"",data:se,showTypeFilter:!0,rawMode:!0,initialExpanded:!0})}),d(C,{style:i.copyButton,onPress:b,children:T?x(Ye,{children:[d(Je,{size:14,color:me.success}),d(u,{style:[i.copyButtonText,i.copySuccessText],children:"Copied!"})]}):x(Ye,{children:[d(Bt,{size:14,color:p.color.accent}),d(u,{style:i.copyButtonText,children:"Copy Config"})]})})]})})]})}var i=H.create({container:{flex:1},contentContainer:{padding:16,gap:12,paddingBottom:32},actionBar:{backgroundColor:p.color.accentSoft,borderRadius:10,borderWidth:1,borderColor:p.color.accentBorder,padding:12},actionBarContent:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},unsavedText:{fontSize:13,fontWeight:"500",color:p.color.accent},actionButtons:{flexDirection:"row",gap:8},saveButton:{flexDirection:"row",alignItems:"center",gap:6,backgroundColor:p.color.accent,paddingHorizontal:14,paddingVertical:8,borderRadius:6},saveButtonText:{fontSize:13,fontWeight:"600",color:p.color.onAccent},discardButton:{flexDirection:"row",alignItems:"center",gap:6,backgroundColor:p.color.surfaceElevated,paddingHorizontal:14,paddingVertical:8,borderRadius:6,borderWidth:1,borderColor:p.color.border},discardButtonText:{fontSize:13,fontWeight:"500",color:p.color.textSecondary},restoreButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,paddingVertical:12,borderRadius:8,borderWidth:1,borderColor:p.color.border,borderStyle:"dashed"},restoreButtonText:{fontSize:13,color:p.color.textSecondary},sectionContent:{paddingTop:8},sectionDescription:{fontSize:13,color:p.color.textSecondary,lineHeight:18,marginBottom:14},togglesCard:{backgroundColor:p.color.surface,borderRadius:10,borderWidth:1,borderColor:p.color.border,padding:4},dangerousCard:{borderColor:p.color.warning+"30"},advancedSection:{marginTop:16},advancedLabel:{fontSize:11,fontWeight:"600",color:p.color.textTertiary,textTransform:"uppercase",letterSpacing:.5,marginBottom:8,marginLeft:2},inputLabel:{fontSize:12,fontWeight:"600",color:p.color.textSecondary,marginBottom:8},input:{height:42,backgroundColor:p.color.surfaceElevated,borderRadius:8,borderWidth:1,borderColor:p.color.border,paddingHorizontal:14,fontSize:14,color:p.color.text,fontFamily:je},inputFooter:{flexDirection:"row",justifyContent:"space-between",alignItems:"flex-start",marginTop:8,gap:12},helperText:{flex:1,fontSize:12,color:p.color.textTertiary,lineHeight:16},resetLink:{paddingVertical:2},resetLinkText:{fontSize:12,color:p.color.accent,fontWeight:"500"},recommendedBadge:{flexDirection:"row",alignItems:"center",gap:4,backgroundColor:p.color.accentSoft,paddingHorizontal:8,paddingVertical:3,borderRadius:4},recommendedText:{fontSize:10,fontWeight:"600",color:p.color.accent},detectedBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4},detectedBadgeActive:{backgroundColor:me.success+"15"},detectedBadgeInactive:{backgroundColor:p.color.textTertiary+"15"},detectedText:{fontSize:10,fontWeight:"600"},detectedTextActive:{color:me.success},detectedTextInactive:{color:p.color.textTertiary},divider:{height:1,backgroundColor:p.color.separator,marginHorizontal:12},warningCard:{marginTop:14,flexDirection:"row",alignItems:"flex-start",gap:12,backgroundColor:p.color.warningSoft,borderRadius:10,borderWidth:1,borderColor:p.color.warning+"25",padding:14},warningContent:{flex:1},warningTitle:{fontSize:13,fontWeight:"600",color:p.color.warning,marginBottom:4},warningText:{fontSize:12,color:p.color.textSecondary,lineHeight:17},infoText:{fontSize:13,color:p.color.textSecondary,lineHeight:19},infoTextSpaced:{marginTop:10},codeBlock:{marginTop:14,backgroundColor:p.color.bg,borderRadius:8,padding:14},codeComment:{fontSize:12,color:p.color.textTertiary,fontFamily:je,marginBottom:6},codeText:{fontSize:13,color:p.color.text,fontFamily:je},codeValue:{color:p.color.accent},dataViewerContainer:{marginTop:12,borderRadius:8,overflow:"hidden",borderWidth:1,borderColor:p.color.border},copyButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,marginTop:14,backgroundColor:p.color.accentSoft,paddingVertical:10,paddingHorizontal:16,borderRadius:8,borderWidth:1,borderColor:p.color.accentBorder},copyButtonText:{fontSize:13,fontWeight:"600",color:p.color.accent},copySuccessText:{color:me.success}});import{jsx as B,jsxs as et}from"react/jsx-runtime";var mn=ln,hn=[{key:"search",label:"Search"},{key:"history",label:"History"},{key:"settings",label:"Settings"}],yn=[{key:"search",label:"Search"},{key:"history",label:"History"}];function ke({visible:t,onClose:e,onBack:o,onMinimize:n,onSearchUsers:r,onClearReactQuery:g,onClearRedux:c,onClearAsyncStorage:m,onClearMMKV:a,showSettingsTab:h=!0,inline:y=!1}){let v=h?hn:yn,[T,D]=Ze("search"),[N,O]=Ze(!1),Z=Nt(!1),[Q,ee]=Ze(""),F=Nt(null),{clearCache:se,isAvailable:b}=It(),{resetStore:w,isAvailable:te}=Ct(),{clearStorage:oe,isAvailable:J}=kt(),He=g??se??void 0,Qt=c??w??void 0,jt=m??oe??void 0,$t={reactQuery:!!g||b,redux:!!c||te,asyncStorage:!!m||J,mmkv:!!a},{isActive:Jt,currentUser:at,headerKey:Yt,dataNukeSettings:Gt,showBanner:Zt,searchQuery:eo,searchResults:to,isSearching:oo,searchError:ro,searchUsers:it,startImpersonation:ct,stopImpersonation:lt,updateHeaderKey:dt,updateDataNukeSettings:ut,updateShowBanner:Pe,history:no,removeFromHistory:so,clearHistory:ao}=Oe({onSearchUsers:r,onClearReactQuery:He,onClearRedux:Qt,onClearAsyncStorage:jt,onClearMMKV:a});Lt(()=>{N&&F.current&&setTimeout(()=>{F.current?.focus()},100)},[N]),Lt(()=>{!h&&T==="settings"&&D("search")},[h,T]);let io=he(Y=>{ee(Y)},[]),co=he(()=>{Q.trim()&&it(Q.trim()),O(!1)},[Q,it]),pt=he(async Y=>{await ct(Y)},[ct]),lo=he(async(Y,po,go)=>{await dt(Y),await ut(po),await Pe(go)},[dt,ut,Pe]),uo=he(Y=>{D(Y),O(!1)},[]),gt=()=>et(ye,{children:[o&&B(ye.Navigation,{onBack:o}),B(ye.Content,{title:"",children:N?B(ye.Search,{value:Q,onChangeText:io,onCancel:()=>{ee(""),O(!1)},onDismiss:()=>O(!1),dismissOnBlur:!0,placeholder:"Search by email, name, or ID...",iconSize:14,testID:"buoy-impersonate-search-input",inputProps:{onSubmitEditing:co}}):B(dn,{tabs:v,activeTab:T,onTabChange:uo})}),B(ye.Actions,{children:T==="search"&&!N&&B(C,{testID:"buoy-impersonate-search-toggle",onPress:()=>O(!0),style:Te.headerActionButton,children:B(pn,{size:14,color:Vt.color.textSecondary})})})]});if(!t)return null;let mt=et(s,{style:Te.container,children:[T==="search"&&B(_e,{currentUser:at,isActive:Jt,searchQuery:eo,searchResults:to,isSearching:oo,searchError:ro,onSelectUser:pt,onStopImpersonation:lt,searchAvailable:!!r}),T==="history"&&B(Xe,{history:no,currentUserId:at?.id??null,onSelectUser:pt,onStopImpersonation:lt,onRemoveFromHistory:so,onClearHistory:ao}),T==="settings"&&B(Ge,{headerKey:Yt,settings:Gt,showBanner:Zt,onSave:lo,onShowBannerChange:Pe,detectionStatus:$t})]});return y?B(Et,{children:et(s,{style:Te.inlineRoot,children:[B(s,{style:Te.inlineHeader,...gn,children:gt()}),mt]})}):B(Et,{children:B(mn,{visible:t,onClose:e,onMinimize:n,header:{showToggleButton:!0,customContent:gt()},enablePersistence:!0,initialMode:"bottomSheet",disableScrollWrapper:!0,children:mt})})}function fn(t){return B(ke,{...t,inline:!0,visible:!0,onClose:()=>{}})}var Te=H.create({inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:un.border,backgroundColor:"transparent"},container:{flex:1},headerActionButton:{width:28,height:28,borderRadius:6,backgroundColor:Vt.color.buttonSurface,justifyContent:"center",alignItems:"center"}});import{useSyncExternalStore as zt}from"react";import{buoyColors as Re,X as Sn,PowerToggleButton as bn}from"@buoy-gg/shared-ui/web";import{jsx as $,jsxs as tt}from"react/jsx-runtime";function fe({onPress:t,onStopPress:e,position:o="top",offset:n=50}){let r=zt(l.subscribe,l.getSnapshot,l.getSnapshot);if(!r.isActive||!r.currentUser||!r.showBanner)return null;let g=async()=>{console.log("[impersonate] banner pause/resume pressed"),r.isPaused?await l.resumeImpersonation():await l.pauseImpersonation()},c=r.currentUser.displayName||r.currentUser.email||r.currentUser.id,m=o==="top"?{top:n}:{bottom:n},a=async()=>{console.log("[impersonate] banner STOP pressed"),await l.stopImpersonation()};return $(s,{style:[X.container,m],children:tt(s,{style:X.banner,children:[tt(C,{style:X.userSection,onPress:t,activeOpacity:.7,children:[$(ne,{userId:r.currentUser.id,name:c,size:"small",showActiveIndicator:!1}),$(u,{style:[X.userName,r.isPaused&&X.userNamePaused],numberOfLines:1,children:c})]}),$(bn,{isEnabled:!r.isPaused,onToggle:g,size:"small",accessibilityLabel:"Toggle impersonation"}),$(C,{style:X.closeButton,onPress:a,activeOpacity:.7,children:$(Sn,{size:12,color:"rgba(255, 255, 255, 0.5)"})})]})})}function vn({onPress:t}){let e=zt(l.subscribe,l.getSnapshot,l.getSnapshot);return!e.isActive||!e.currentUser?null:tt(C,{style:X.minimalBanner,onPress:t,activeOpacity:.8,children:[$(s,{style:X.minimalDot}),$(u,{style:X.minimalText,children:"IMP"})]})}var X=H.create({container:{position:"absolute",left:0,right:0,alignItems:"center",zIndex:9999,pointerEvents:"box-none"},banner:{flexDirection:"row",alignItems:"center",backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:1,borderColor:Re.success+"40",borderRadius:22,paddingVertical:7,paddingLeft:7,paddingRight:10,gap:10,marginTop:3,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.3,shadowRadius:14,elevation:10},userSection:{flexDirection:"row",alignItems:"center",gap:10},userName:{fontSize:14,fontWeight:"600",color:"#fff",maxWidth:180},userNamePaused:{opacity:.6},closeButton:{width:22,height:22,borderRadius:11,backgroundColor:"rgba(128, 128, 128, 0.16)",alignItems:"center",justifyContent:"center",marginLeft:-4},minimalBanner:{position:"absolute",top:60,right:16,flexDirection:"row",alignItems:"center",backgroundColor:"rgba(26, 26, 26, 0.92)",borderWidth:1,borderColor:Re.success+"35",borderRadius:12,paddingVertical:5,paddingHorizontal:10,gap:5,zIndex:9999,shadowColor:"#000",shadowOffset:{width:0,height:2},shadowOpacity:.2,shadowRadius:6,elevation:4},minimalDot:{width:6,height:6,borderRadius:3,backgroundColor:Re.success},minimalText:{fontSize:10,fontWeight:"700",color:Re.success,letterSpacing:.5}});import{isOverWireBudget as xn}from"@buoy-gg/shared-ui/web";var rt=null;function Wt(t){rt=t}var ot=2*1024,wn=16*1024,Ot=Object.freeze({__buoyOmitted:"user-metadata",note:"User metadata stays on the device."});function In(t){if(!t)return t;if(t.startsWith("data:")){let e=t.indexOf(",");return`${e>=0?t.slice(0,Math.min(e+1,64)):"data:"}[${t.length} chars]`}return t.length<=ot?t:`${t.slice(0,ot)}\u2026 [${t.length-ot} more]`}function Cn(t){if(!t)return t;let e=typeof t.role=="string"?t.role:void 0;return xn(t,wn)?e?{role:e,...Ot}:{...Ot}:t}function nt(t){return{...t,avatarUrl:In(t.avatarUrl),metadata:Cn(t.metadata)}}function Mt(t){return{...t,currentUser:t.currentUser?nt(t.currentUser):null,history:t.history.map(e=>({...e,user:nt(e.user)}))}}var Ft=new Set;function Tn(t){for(let e of t)e&&typeof e=="object"&&e.id&&Ft.add(String(e.id))}function kn(t){if(!t||typeof t!="object"||!t.id)return!1;if(Ft.has(String(t.id)))return!0;let e=l.getState();return e.currentUser?.id===t.id?!0:e.history.some(o=>o.user.id===t.id)}function Kt(t){return{searchUsers:async e=>{let o=String(e?.query??""),n=await t(o);return Array.isArray(n)&&Tn(n),Array.isArray(n)?n.map(nt):n},startImpersonation:async e=>{let o=e?.user;if(!kn(o))throw new Error("That user isn't in this app's directory. Call searchUsers and impersonate one of its results \u2014 a user object that didn't come from search impersonates nobody.");return await l.startImpersonation(o),{ok:!0,userId:o.id}},stopImpersonation:()=>l.stopImpersonation(),pauseImpersonation:()=>l.pauseImpersonation(),resumeImpersonation:()=>l.resumeImpersonation(),updateSettings:e=>{let o=e??{},n=o.settings??(["headerKey","ignorePatterns","showBanner","dataNukeSettings"].some(r=>r in o)?o:void 0);if(!n)throw new Error("updateSettings needs { settings: { headerKey?, ignorePatterns?, showBanner?, dataNukeSettings? } }.");return l.updateSettings(n)},removeFromHistory:e=>l.removeFromHistory(e.userId),clearHistory:()=>l.clearHistory()}}function Rn({onSearchUsers:t}){return{version:1,getSnapshot:()=>Mt(l.getState()),subscribe:e=>l.subscribe(e),actions:Kt(t)}}var An={dispose:()=>l.disposeAccountSession(),version:1,getSnapshot:()=>Mt(l.getState()),subscribe:t=>l.subscribe(t),actions:Kt(t=>{if(!rt)throw new Error("No onSearchUsers configured \u2014 pass it to createImpersonateTool()");return rt(t)})};import{ImpersonateIcon as qt,IMPERSONATE_ICON_COLOR as Pn}from"@buoy-gg/shared-ui/web";import{jsx as Xt}from"react/jsx-runtime";var _t=!1;async function Hn(){if(!(typeof window>"u"||_t)){_t=!0,console.log("[impersonate] bootstrap: start"),L().isListening||L().startListening();try{let t=ve();if(!t||typeof t.getItem!="function"){console.warn("[impersonate] bootstrap: AsyncStorage shape unexpected",Object.keys(t??{}));return}let e={getItem:o=>t.getItem(o),setItem:(o,n)=>t.setItem(o,n)};l.setAsyncStorage(e),console.log("[impersonate] bootstrap: AsyncStorage adapter installed"),await l.initializeAsync(e),console.log("[impersonate] bootstrap: initializeAsync done")}catch(t){console.warn("[impersonate] bootstrap: failed",t)}}}function Un(t){let{id:e="impersonate",name:o="IMPERSONATE",description:n="User impersonation for admin testing",defaults:r,showSettingsTab:g=!0,onSearchUsers:c,onClearReactQuery:m,onClearRedux:a,onClearAsyncStorage:h,onClearMMKV:y}=t;return r&&l.setDeveloperDefaults(r),Wt(c??null),Hn(),{id:e,name:o,description:n,slot:"both",icon:({size:T,slot:D})=>Xt(qt,{size:D==="dial"?T*1.5:T,color:Pn}),component:T=>Xt(ke,{...T,onSearchUsers:c,onClearReactQuery:m,onClearRedux:a,onClearAsyncStorage:h,onClearMMKV:y,showSettingsTab:g}),props:{enableSharedModalDimensions:!1},Banner:fe}}import{jsx as Dn}from"react/jsx-runtime";function Bn(){return Dn(fe,{position:"top",offset:50})}import{buoyColors as Se,night as be,X as Nn}from"@buoy-gg/shared-ui/web";import{jsx as G,jsxs as Ae}from"react/jsx-runtime";function Ln({user:t,onStopImpersonation:e}){let o=t.displayName||t.email||t.id;return Ae(s,{style:q.container,children:[Ae(s,{style:q.userSection,children:[G(ne,{userId:t.id,name:o,size:"small",showActiveIndicator:!1}),G(s,{style:q.userInfo,children:G(u,{style:q.userName,numberOfLines:1,children:o})})]}),Ae(s,{style:q.statusPill,children:[G(s,{style:q.pulseDot}),G(u,{style:q.statusText,children:"Active"})]}),Ae(C,{style:q.stopButton,onPress:e,activeOpacity:.7,children:[G(Nn,{size:12,color:be.color.danger}),G(u,{style:q.stopButtonText,children:"Stop"})]})]})}var q=H.create({container:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingVertical:10,paddingHorizontal:16,backgroundColor:Se.success+"10",borderBottomWidth:1,borderBottomColor:Se.success+"25",gap:12},userSection:{flexDirection:"row",alignItems:"center",flex:1,gap:10,minWidth:0},userInfo:{flex:1,minWidth:0},userName:{fontSize:14,fontWeight:"600",color:be.color.text},statusPill:{flexDirection:"row",alignItems:"center",gap:6,backgroundColor:Se.success+"20",paddingHorizontal:10,paddingVertical:5,borderRadius:12},pulseDot:{width:6,height:6,borderRadius:3,backgroundColor:Se.success},statusText:{fontSize:11,fontWeight:"600",color:Se.success,textTransform:"uppercase",letterSpacing:.5},stopButton:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:12,paddingVertical:6,backgroundColor:be.color.dangerSoft,borderRadius:6,borderWidth:1,borderColor:be.color.danger+"30"},stopButtonText:{fontSize:12,fontWeight:"600",color:be.color.danger}});import{useCallback as st,useSyncExternalStore as En}from"react";function Vn(){let t=En(l.subscribe,l.getSnapshot,l.getSnapshot),e=st(async r=>{await l.quickSwitch(r)},[]),o=st(async r=>{await l.removeFromHistory(r)},[]),n=st(async()=>{await l.clearHistory()},[]);return{history:t.history,currentUserId:t.currentUser?.id??null,quickSwitch:e,removeFromHistory:o,clearHistory:n}}export{Ge as DataNukeSettingsComponent,fe as ImpersonateBanner,vn as ImpersonateBannerMinimal,Xe as ImpersonateHistoryList,qt as ImpersonateIcon,ke as ImpersonateModal,Bn as ImpersonateOverlay,Ln as ImpersonateStatusBar,fn as ImpersonateToolView,_e as UserSearchView,Rn as createImpersonateSyncAdapter,Un as createImpersonateTool,vr as getImpersonatedUserId,L as impersonateListener,l as impersonateStore,An as impersonateSyncAdapter,br as isImpersonating,Ee as setImpersonateConfig,fr as startImpersonateListener,Sr as stopImpersonateListener,Oe as useImpersonate,Vn as useImpersonateHistory};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/impersonate",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.41",
|
|
4
4
|
"description": "Configure impersonation headers for supported app requests. Your backend must authenticate and authorize user changes.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -10,27 +10,37 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"react-native": "./lib/module/index.js",
|
|
13
|
+
"browser": {
|
|
14
|
+
"types": "./lib/typescript/index.d.ts",
|
|
15
|
+
"default": "./lib/web/index.mjs"
|
|
16
|
+
},
|
|
13
17
|
"import": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
18
|
+
"types": "./lib/typescript/index.d.ts",
|
|
19
|
+
"default": "./lib/module/index.js"
|
|
16
20
|
},
|
|
17
21
|
"require": {
|
|
18
|
-
"
|
|
19
|
-
"
|
|
22
|
+
"types": "./lib/typescript/index.d.ts",
|
|
23
|
+
"default": "./lib/commonjs/index.js"
|
|
20
24
|
}
|
|
21
25
|
},
|
|
22
|
-
"./package.json": "./package.json"
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./web": {
|
|
28
|
+
"types": "./lib/typescript/index.d.ts",
|
|
29
|
+
"default": "./lib/web/index.mjs"
|
|
30
|
+
}
|
|
23
31
|
},
|
|
24
32
|
"files": [
|
|
25
33
|
"lib"
|
|
26
34
|
],
|
|
27
35
|
"sideEffects": false,
|
|
28
36
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
37
|
+
"@buoy-gg/shared-ui": "^7.0.41"
|
|
30
38
|
},
|
|
31
39
|
"peerDependencies": {
|
|
32
40
|
"react": "*",
|
|
33
|
-
"react-native": "*"
|
|
41
|
+
"react-native": "*",
|
|
42
|
+
"react-native-web": "^0.21.0",
|
|
43
|
+
"react-dom": ">=18"
|
|
34
44
|
},
|
|
35
45
|
"devDependencies": {
|
|
36
46
|
"@types/react": "^19.1.0",
|
|
@@ -85,10 +95,22 @@
|
|
|
85
95
|
"auth-testing",
|
|
86
96
|
"qa"
|
|
87
97
|
],
|
|
98
|
+
"peerDependenciesMeta": {
|
|
99
|
+
"react-native": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"react-native-web": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"react-dom": {
|
|
106
|
+
"optional": true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
88
109
|
"scripts": {
|
|
89
|
-
"build": "bob build",
|
|
110
|
+
"build": "bob build && pnpm run build:web",
|
|
90
111
|
"typecheck": "tsc --noEmit",
|
|
91
112
|
"clean": "rimraf lib",
|
|
92
|
-
"test": "pnpm run typecheck"
|
|
113
|
+
"test": "pnpm run typecheck",
|
|
114
|
+
"build:web": "node ../../scripts/build-web.mjs impersonate"
|
|
93
115
|
}
|
|
94
116
|
}
|