@buoy-gg/impersonate 1.0.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +58 -0
  2. package/lib/commonjs/impersonate/components/DataNukeSettings.js +715 -0
  3. package/lib/commonjs/impersonate/components/ImpersonateBanner.js +217 -0
  4. package/lib/commonjs/impersonate/components/ImpersonateHistoryList.js +173 -0
  5. package/lib/commonjs/impersonate/components/ImpersonateModal.js +304 -0
  6. package/lib/commonjs/impersonate/components/ImpersonateStatusBar.js +130 -0
  7. package/lib/commonjs/impersonate/components/UserAvatar.js +146 -0
  8. package/lib/commonjs/impersonate/components/UserCard.js +200 -0
  9. package/lib/commonjs/impersonate/components/UserSearchView.js +227 -0
  10. package/lib/commonjs/impersonate/components/index.js +85 -0
  11. package/lib/commonjs/impersonate/hooks/index.js +64 -0
  12. package/lib/commonjs/impersonate/hooks/useAutoClearAsyncStorage.js +144 -0
  13. package/lib/commonjs/impersonate/hooks/useAutoClearReactQuery.js +155 -0
  14. package/lib/commonjs/impersonate/hooks/useAutoClearRedux.js +188 -0
  15. package/lib/commonjs/impersonate/hooks/useImpersonate.js +215 -0
  16. package/lib/commonjs/impersonate/hooks/useImpersonateHistory.js +56 -0
  17. package/lib/commonjs/impersonate/index.js +49 -0
  18. package/lib/commonjs/impersonate/types/index.js +16 -0
  19. package/lib/commonjs/impersonate/types/types.js +1 -0
  20. package/lib/commonjs/impersonate/utils/impersonateListener.js +280 -0
  21. package/lib/commonjs/impersonate/utils/impersonateStore.js +607 -0
  22. package/lib/commonjs/impersonate/utils/index.js +49 -0
  23. package/lib/commonjs/index.js +118 -0
  24. package/lib/commonjs/package.json +1 -0
  25. package/lib/commonjs/preset.js +214 -0
  26. package/lib/module/impersonate/components/DataNukeSettings.js +710 -0
  27. package/lib/module/impersonate/components/ImpersonateBanner.js +211 -0
  28. package/lib/module/impersonate/components/ImpersonateHistoryList.js +168 -0
  29. package/lib/module/impersonate/components/ImpersonateModal.js +300 -0
  30. package/lib/module/impersonate/components/ImpersonateStatusBar.js +125 -0
  31. package/lib/module/impersonate/components/UserAvatar.js +140 -0
  32. package/lib/module/impersonate/components/UserCard.js +195 -0
  33. package/lib/module/impersonate/components/UserSearchView.js +222 -0
  34. package/lib/module/impersonate/components/index.js +11 -0
  35. package/lib/module/impersonate/hooks/index.js +7 -0
  36. package/lib/module/impersonate/hooks/useAutoClearAsyncStorage.js +140 -0
  37. package/lib/module/impersonate/hooks/useAutoClearReactQuery.js +151 -0
  38. package/lib/module/impersonate/hooks/useAutoClearRedux.js +183 -0
  39. package/lib/module/impersonate/hooks/useImpersonate.js +212 -0
  40. package/lib/module/impersonate/hooks/useImpersonateHistory.js +52 -0
  41. package/lib/module/impersonate/index.js +13 -0
  42. package/lib/module/impersonate/types/index.js +3 -0
  43. package/lib/module/impersonate/types/types.js +1 -0
  44. package/lib/module/impersonate/utils/impersonateListener.js +271 -0
  45. package/lib/module/impersonate/utils/impersonateStore.js +604 -0
  46. package/lib/module/impersonate/utils/index.js +4 -0
  47. package/lib/module/index.js +103 -0
  48. package/lib/module/preset.js +209 -0
  49. package/lib/typescript/impersonate/components/DataNukeSettings.d.ts +37 -0
  50. package/lib/typescript/impersonate/components/DataNukeSettings.d.ts.map +1 -0
  51. package/lib/typescript/impersonate/components/ImpersonateBanner.d.ts +40 -0
  52. package/lib/typescript/impersonate/components/ImpersonateBanner.d.ts.map +1 -0
  53. package/lib/typescript/impersonate/components/ImpersonateHistoryList.d.ts +24 -0
  54. package/lib/typescript/impersonate/components/ImpersonateHistoryList.d.ts.map +1 -0
  55. package/lib/typescript/impersonate/components/ImpersonateModal.d.ts +10 -0
  56. package/lib/typescript/impersonate/components/ImpersonateModal.d.ts.map +1 -0
  57. package/lib/typescript/impersonate/components/ImpersonateStatusBar.d.ts +15 -0
  58. package/lib/typescript/impersonate/components/ImpersonateStatusBar.d.ts.map +1 -0
  59. package/lib/typescript/impersonate/components/UserAvatar.d.ts +32 -0
  60. package/lib/typescript/impersonate/components/UserAvatar.d.ts.map +1 -0
  61. package/lib/typescript/impersonate/components/UserCard.d.ts +28 -0
  62. package/lib/typescript/impersonate/components/UserCard.d.ts.map +1 -0
  63. package/lib/typescript/impersonate/components/UserSearchView.d.ts +31 -0
  64. package/lib/typescript/impersonate/components/UserSearchView.d.ts.map +1 -0
  65. package/lib/typescript/impersonate/components/index.d.ts +16 -0
  66. package/lib/typescript/impersonate/components/index.d.ts.map +1 -0
  67. package/lib/typescript/impersonate/hooks/index.d.ts +11 -0
  68. package/lib/typescript/impersonate/hooks/index.d.ts.map +1 -0
  69. package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts +48 -0
  70. package/lib/typescript/impersonate/hooks/useAutoClearAsyncStorage.d.ts.map +1 -0
  71. package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.d.ts +48 -0
  72. package/lib/typescript/impersonate/hooks/useAutoClearReactQuery.d.ts.map +1 -0
  73. package/lib/typescript/impersonate/hooks/useAutoClearRedux.d.ts +78 -0
  74. package/lib/typescript/impersonate/hooks/useAutoClearRedux.d.ts.map +1 -0
  75. package/lib/typescript/impersonate/hooks/useImpersonate.d.ts +76 -0
  76. package/lib/typescript/impersonate/hooks/useImpersonate.d.ts.map +1 -0
  77. package/lib/typescript/impersonate/hooks/useImpersonateHistory.d.ts +43 -0
  78. package/lib/typescript/impersonate/hooks/useImpersonateHistory.d.ts.map +1 -0
  79. package/lib/typescript/impersonate/index.d.ts +5 -0
  80. package/lib/typescript/impersonate/index.d.ts.map +1 -0
  81. package/lib/typescript/impersonate/types/index.d.ts +2 -0
  82. package/lib/typescript/impersonate/types/index.d.ts.map +1 -0
  83. package/lib/typescript/impersonate/types/types.d.ts +177 -0
  84. package/lib/typescript/impersonate/types/types.d.ts.map +1 -0
  85. package/lib/typescript/impersonate/utils/impersonateListener.d.ts +115 -0
  86. package/lib/typescript/impersonate/utils/impersonateListener.d.ts.map +1 -0
  87. package/lib/typescript/impersonate/utils/impersonateStore.d.ts +151 -0
  88. package/lib/typescript/impersonate/utils/impersonateStore.d.ts.map +1 -0
  89. package/lib/typescript/impersonate/utils/index.d.ts +3 -0
  90. package/lib/typescript/impersonate/utils/index.d.ts.map +1 -0
  91. package/lib/typescript/index.d.ts +80 -0
  92. package/lib/typescript/index.d.ts.map +1 -0
  93. package/lib/typescript/preset.d.ts +71 -0
  94. package/lib/typescript/preset.d.ts.map +1 -0
  95. package/package.json +78 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * useAutoClearRedux Hook
3
+ *
4
+ * Auto-detects Redux store and provides a reset function.
5
+ * Uses the same pattern as @buoy-gg/redux's useAutoInstrumentRedux.
6
+ *
7
+ * This hook:
8
+ * 1. Dynamically requires react-redux
9
+ * 2. Uses useStore() to get the store from context
10
+ * 3. Returns a resetStore function that dispatches a reset action
11
+ *
12
+ * IMPORTANT: Unlike React Query which has a universal .clear() method,
13
+ * Redux reset requires the app's reducer to handle the reset action.
14
+ * The default action type is '@@RESET' but can be customized.
15
+ *
16
+ * Example reducer handling:
17
+ * ```typescript
18
+ * const rootReducer = (state, action) => {
19
+ * if (action.type === '@@RESET') {
20
+ * return undefined; // Returns to initial state
21
+ * }
22
+ * return appReducer(state, action);
23
+ * };
24
+ * ```
25
+ */
26
+ /** The default action type dispatched to reset Redux state */
27
+ export declare const REDUX_RESET_ACTION_TYPE = "@@RESET";
28
+ export interface UseAutoClearReduxOptions {
29
+ /** Custom action type to dispatch for reset (default: '@@RESET') */
30
+ resetActionType?: string;
31
+ }
32
+ export interface UseAutoClearReduxResult {
33
+ /** Whether Redux is available and connected */
34
+ isAvailable: boolean;
35
+ /** Error message if not available */
36
+ error: string | null;
37
+ /** Function to dispatch reset action to Redux store */
38
+ resetStore: (() => void) | null;
39
+ }
40
+ /**
41
+ * Hook to auto-detect Redux store and provide state reset functionality.
42
+ *
43
+ * This dispatches a reset action (default: '@@RESET') to the store.
44
+ * Your app's root reducer must handle this action to actually reset state.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * // In your component:
49
+ * function MyComponent() {
50
+ * const { isAvailable, resetStore } = useAutoClearRedux();
51
+ *
52
+ * if (isAvailable && resetStore) {
53
+ * resetStore(); // Dispatches { type: '@@RESET' }
54
+ * }
55
+ * }
56
+ *
57
+ * // In your root reducer:
58
+ * const rootReducer = (state, action) => {
59
+ * if (action.type === '@@RESET') {
60
+ * // Return undefined to reset to initial state
61
+ * // Or return a specific "logged out" state
62
+ * return undefined;
63
+ * }
64
+ * return appReducer(state, action);
65
+ * };
66
+ * ```
67
+ */
68
+ export declare function useAutoClearRedux(options?: UseAutoClearReduxOptions): UseAutoClearReduxResult;
69
+ /**
70
+ * Lightweight hook to just check if Redux is available
71
+ * without getting the store
72
+ */
73
+ export declare function useReduxAvailability(): {
74
+ isInstalled: boolean;
75
+ isConnected: boolean;
76
+ error: string | null;
77
+ };
78
+ //# sourceMappingURL=useAutoClearRedux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutoClearRedux.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useAutoClearRedux.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAgBH,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAEjD,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,+CAA+C;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,qCAAqC;IACrC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uDAAuD;IACvD,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;CACjC;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,uBAAuB,CAiEzB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CA6BA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * useImpersonate Hook
3
+ *
4
+ * Main hook for managing impersonation state and actions.
5
+ * Provides all the controls needed to search users, start/stop
6
+ * impersonation, and manage settings.
7
+ */
8
+ import type { User, HistoryEntry, DataNukeSettings } from "../types";
9
+ export interface UseImpersonateOptions {
10
+ /** Callback to search users - provided by host app */
11
+ onSearchUsers?: (query: string) => Promise<User[]>;
12
+ /** Callback to clear React Query cache */
13
+ onClearReactQuery?: () => void | Promise<void>;
14
+ /** Callback to clear/reset Redux state */
15
+ onClearRedux?: () => void | Promise<void>;
16
+ /** Callback to clear AsyncStorage */
17
+ onClearAsyncStorage?: () => void | Promise<void>;
18
+ /** Callback to clear MMKV */
19
+ onClearMMKV?: () => void | Promise<void>;
20
+ }
21
+ export interface UseImpersonateReturn {
22
+ isActive: boolean;
23
+ currentUser: User | null;
24
+ headerKey: string;
25
+ ignorePatterns: string[];
26
+ dataNukeSettings: DataNukeSettings;
27
+ showBanner: boolean;
28
+ history: HistoryEntry[];
29
+ searchQuery: string;
30
+ searchResults: User[];
31
+ isSearching: boolean;
32
+ searchError: string | null;
33
+ searchUsers: (query: string) => Promise<void>;
34
+ clearSearch: () => void;
35
+ startImpersonation: (user: User) => Promise<void>;
36
+ stopImpersonation: () => Promise<void>;
37
+ quickSwitch: (user: User) => Promise<void>;
38
+ updateHeaderKey: (key: string) => Promise<void>;
39
+ updateIgnorePatterns: (patterns: string[]) => Promise<void>;
40
+ updateDataNukeSettings: (settings: Partial<DataNukeSettings>) => Promise<void>;
41
+ updateShowBanner: (show: boolean) => Promise<void>;
42
+ removeFromHistory: (userId: string) => Promise<void>;
43
+ clearHistory: () => Promise<void>;
44
+ }
45
+ /**
46
+ * Hook for managing impersonation
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * function ImpersonatePanel() {
51
+ * const {
52
+ * isActive,
53
+ * currentUser,
54
+ * searchUsers,
55
+ * searchResults,
56
+ * startImpersonation,
57
+ * stopImpersonation,
58
+ * } = useImpersonate({
59
+ * onSearchUsers: async (query) => api.searchUsers(query),
60
+ * onClearReactQuery: () => queryClient.clear(),
61
+ * });
62
+ *
63
+ * return (
64
+ * <View>
65
+ * {isActive ? (
66
+ * <Text>Impersonating: {currentUser?.email}</Text>
67
+ * ) : (
68
+ * <Text>Not impersonating</Text>
69
+ * )}
70
+ * </View>
71
+ * );
72
+ * }
73
+ * ```
74
+ */
75
+ export declare function useImpersonate(options?: UseImpersonateOptions): UseImpersonateReturn;
76
+ //# sourceMappingURL=useImpersonate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImpersonate.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useImpersonate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIrE,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,qCAAqC;IACrC,mBAAmB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IAEnC,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IAGxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,IAAI,EAAE,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,WAAW,EAAE,MAAM,IAAI,CAAC;IAGxB,kBAAkB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,sBAAsB,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGnD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA+LtB"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * useImpersonateHistory Hook
3
+ *
4
+ * Specialized hook for working with impersonation history.
5
+ * Use this when you only need history functionality.
6
+ */
7
+ import type { User, HistoryEntry } from "../types";
8
+ export interface UseImpersonateHistoryReturn {
9
+ /** List of recently impersonated users */
10
+ history: HistoryEntry[];
11
+ /** Currently impersonated user ID (null if not impersonating) */
12
+ currentUserId: string | null;
13
+ /** Quick switch to a user from history */
14
+ quickSwitch: (user: User) => Promise<void>;
15
+ /** Remove a user from history */
16
+ removeFromHistory: (userId: string) => Promise<void>;
17
+ /** Clear all history */
18
+ clearHistory: () => Promise<void>;
19
+ }
20
+ /**
21
+ * Hook for managing impersonation history
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * function HistoryList() {
26
+ * const { history, currentUserId, quickSwitch } = useImpersonateHistory();
27
+ *
28
+ * return (
29
+ * <FlatList
30
+ * data={history}
31
+ * renderItem={({ item }) => (
32
+ * <TouchableOpacity onPress={() => quickSwitch(item)}>
33
+ * <Text>{item.email}</Text>
34
+ * {currentUserId === item.id && <Badge>Active</Badge>}
35
+ * </TouchableOpacity>
36
+ * )}
37
+ * />
38
+ * );
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function useImpersonateHistory(): UseImpersonateHistoryReturn;
43
+ //# sourceMappingURL=useImpersonateHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImpersonateHistory.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/hooks/useImpersonateHistory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,WAAW,2BAA2B;IAC1C,0CAA0C;IAC1C,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,iEAAiE;IACjE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,iCAAiC;IACjC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,wBAAwB;IACxB,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CA0BnE"}
@@ -0,0 +1,5 @@
1
+ export * from "./types";
2
+ export * from "./utils";
3
+ export * from "./hooks";
4
+ export * from "./components";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/impersonate/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Type definitions for @buoy-gg/impersonate
3
+ */
4
+ /**
5
+ * Represents a user that can be impersonated
6
+ */
7
+ export interface User {
8
+ /** Unique user identifier - this value is sent in the impersonation header */
9
+ id: string;
10
+ /** Display name for UI (falls back to email, then id) */
11
+ displayName?: string;
12
+ /** User's email address */
13
+ email?: string;
14
+ /** URL to user's avatar image */
15
+ avatarUrl?: string;
16
+ /** Additional metadata to display in UserCard (key-value pairs) */
17
+ metadata?: Record<string, unknown>;
18
+ }
19
+ /**
20
+ * A history entry with timestamp
21
+ */
22
+ export interface HistoryEntry {
23
+ /** The user that was impersonated */
24
+ user: User;
25
+ /** When the impersonation started (ISO string) */
26
+ lastUsedAt: string;
27
+ }
28
+ /**
29
+ * Settings for which data stores to clear on impersonation change
30
+ */
31
+ export interface DataNukeSettings {
32
+ /** Clear React Query cache (queries + mutations) */
33
+ reactQuery: boolean;
34
+ /** Reset Redux state */
35
+ redux: boolean;
36
+ /** Clear AsyncStorage (app data only, preserves @buoy/* keys) */
37
+ asyncStorage: boolean;
38
+ /** Clear MMKV storage (app data only, preserves @buoy/* keys) */
39
+ mmkv: boolean;
40
+ }
41
+ /**
42
+ * Internal impersonation state managed by the store
43
+ */
44
+ export interface ImpersonationState {
45
+ /** Whether impersonation is currently active */
46
+ isActive: boolean;
47
+ /** Whether impersonation is paused (headers not injected) */
48
+ isPaused: boolean;
49
+ /** The currently impersonated user (null if not impersonating) */
50
+ currentUser: User | null;
51
+ /** HTTP header key to use for impersonation */
52
+ headerKey: string;
53
+ /** URL patterns to exclude from header injection (as regex strings) */
54
+ ignorePatterns: string[];
55
+ /** Settings for data clearing on impersonation change */
56
+ dataNukeSettings: DataNukeSettings;
57
+ /** Whether to show floating banner when impersonating */
58
+ showBanner: boolean;
59
+ /** History of recently impersonated users (max 10) */
60
+ history: HistoryEntry[];
61
+ }
62
+ /**
63
+ * Configuration for the impersonate listener
64
+ */
65
+ export interface ImpersonateListenerConfig {
66
+ /** Header key to inject (default: 'x-impersonate-user-id') */
67
+ headerKey: string;
68
+ /** Current impersonated user ID (null = not impersonating) */
69
+ userId: string | null;
70
+ /** URL patterns to ignore (won't inject header) */
71
+ ignorePatterns: RegExp[];
72
+ }
73
+ /**
74
+ * Developer-configurable defaults for the impersonate tool
75
+ */
76
+ export interface ImpersonateDefaults {
77
+ /** Default header key (default: 'x-impersonate-user-id') */
78
+ headerKey?: string;
79
+ /** Default data nuke settings */
80
+ dataNukeSettings?: Partial<DataNukeSettings>;
81
+ /** Show floating banner when impersonating (default: true) */
82
+ showBanner?: boolean;
83
+ }
84
+ /**
85
+ * Configuration for creating the impersonate tool
86
+ */
87
+ export interface ImpersonateToolConfig {
88
+ /** Tool ID (default: 'impersonate') */
89
+ id?: string;
90
+ /** Tool name displayed in DevTools (default: 'IMPERSONATE') */
91
+ name?: string;
92
+ /** Tool description shown in settings */
93
+ description?: string;
94
+ /**
95
+ * Developer-configurable defaults
96
+ * These override hardcoded defaults but are overridden by persisted user settings
97
+ */
98
+ defaults?: ImpersonateDefaults;
99
+ /**
100
+ * Show the settings tab in the modal (default: true)
101
+ * Set to false to hide settings when using for simple testing
102
+ */
103
+ showSettingsTab?: boolean;
104
+ /**
105
+ * Search users callback - REQUIRED for user search to work
106
+ * Return an array of User objects matching the query
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * onSearchUsers: async (query) => {
111
+ * const res = await api.get(`/admin/users?email=${query}`);
112
+ * return res.users.map(u => ({
113
+ * id: u.id,
114
+ * displayName: u.name,
115
+ * email: u.email,
116
+ * metadata: { role: u.role }
117
+ * }));
118
+ * }
119
+ * ```
120
+ */
121
+ onSearchUsers: (query: string) => Promise<User[]>;
122
+ /**
123
+ * Clear React Query cache
124
+ * @example `() => queryClient.clear()`
125
+ */
126
+ onClearReactQuery?: () => void | Promise<void>;
127
+ /**
128
+ * Reset Redux state
129
+ * @example `() => store.dispatch({ type: 'RESET' })`
130
+ */
131
+ onClearRedux?: () => void | Promise<void>;
132
+ /**
133
+ * Clear AsyncStorage (app data only)
134
+ * The callback should filter out @buoy/* keys
135
+ */
136
+ onClearAsyncStorage?: () => void | Promise<void>;
137
+ /**
138
+ * Clear MMKV storage (app data only)
139
+ * The callback should filter out @buoy/* keys
140
+ */
141
+ onClearMMKV?: () => void | Promise<void>;
142
+ }
143
+ /**
144
+ * Props passed to the ImpersonateModal component
145
+ */
146
+ export interface ImpersonateModalProps {
147
+ /** Controls the visibility of the modal */
148
+ visible: boolean;
149
+ /** Callback executed when the modal is dismissed */
150
+ onClose: () => void;
151
+ /** Optional handler fired when navigating back */
152
+ onBack?: () => void;
153
+ /** Optional handler fired when the modal is minimized */
154
+ onMinimize?: (modalState: unknown) => void;
155
+ /** Search users callback */
156
+ onSearchUsers?: (query: string) => Promise<User[]>;
157
+ /** Clear React Query callback */
158
+ onClearReactQuery?: () => void | Promise<void>;
159
+ /** Clear Redux callback */
160
+ onClearRedux?: () => void | Promise<void>;
161
+ /** Clear AsyncStorage callback */
162
+ onClearAsyncStorage?: () => void | Promise<void>;
163
+ /** Clear MMKV callback */
164
+ onClearMMKV?: () => void | Promise<void>;
165
+ /** Show the settings tab (default: true) */
166
+ showSettingsTab?: boolean;
167
+ }
168
+ /**
169
+ * Props for the ImpersonateBanner component
170
+ */
171
+ export interface ImpersonateBannerProps {
172
+ /** Called when the banner is tapped (typically opens modal) */
173
+ onPress?: () => void;
174
+ /** Called when impersonation is stopped via banner */
175
+ onStopPress?: () => void;
176
+ }
177
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/types/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Impersonate Listener - Header Injection via Fetch/XHR Monkey-Patching
3
+ *
4
+ * This module intercepts all network requests and injects the impersonation
5
+ * header when impersonation is active. It follows the same singleton pattern
6
+ * as @buoy-gg/network's networkListener.
7
+ */
8
+ import type { ImpersonateListenerConfig } from "../types";
9
+ /**
10
+ * Impersonation header injector for network requests
11
+ *
12
+ * This class monkey-patches fetch and XMLHttpRequest to inject the
13
+ * impersonation header on all outgoing requests when impersonation is active.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Get the singleton instance
18
+ * const listener = impersonateListener();
19
+ *
20
+ * // Configure impersonation
21
+ * listener.setConfig({
22
+ * headerKey: 'x-impersonate-user-id',
23
+ * userId: '12345',
24
+ * ignorePatterns: [/\/health/]
25
+ * });
26
+ *
27
+ * // Start injecting headers
28
+ * listener.startListening();
29
+ *
30
+ * // All fetch/XHR requests will now include the header
31
+ *
32
+ * // Stop injecting when done
33
+ * listener.stopListening();
34
+ * ```
35
+ */
36
+ declare class ImpersonateListener {
37
+ private config;
38
+ private isListeningFlag;
39
+ private originalFetch;
40
+ private originalXHROpen;
41
+ private originalXHRSend;
42
+ constructor();
43
+ /**
44
+ * Update impersonation config without restarting listener
45
+ *
46
+ * This is the primary way to activate/deactivate impersonation.
47
+ * Set userId to null to stop injecting headers.
48
+ */
49
+ setConfig(partial: Partial<ImpersonateListenerConfig>): void;
50
+ /**
51
+ * Get current configuration
52
+ */
53
+ getConfig(): ImpersonateListenerConfig;
54
+ /**
55
+ * Check if URL should have header injected
56
+ *
57
+ * Returns false if:
58
+ * - No userId is set (not impersonating)
59
+ * - URL matches any ignore pattern
60
+ */
61
+ private shouldInjectHeader;
62
+ /**
63
+ * Extract URL from various input types
64
+ */
65
+ private extractUrl;
66
+ /**
67
+ * Start intercepting and injecting headers
68
+ *
69
+ * This patches globalThis.fetch and XMLHttpRequest.prototype methods
70
+ * to inject the impersonation header on all requests.
71
+ */
72
+ startListening(): void;
73
+ /**
74
+ * Stop intercepting - restore original methods
75
+ *
76
+ * Note: This restores fetch/XHR to their state when ImpersonateListener
77
+ * was constructed. If other interceptors were installed after, this may
78
+ * break their functionality.
79
+ */
80
+ stopListening(): void;
81
+ /**
82
+ * Check if listener is currently active
83
+ */
84
+ get isListening(): boolean;
85
+ /**
86
+ * Check if impersonation is currently active (has userId set)
87
+ */
88
+ get isImpersonating(): boolean;
89
+ }
90
+ /**
91
+ * Get the singleton ImpersonateListener instance
92
+ */
93
+ export declare function impersonateListener(): ImpersonateListener;
94
+ /**
95
+ * Convenience function to start the listener
96
+ */
97
+ export declare function startImpersonateListener(): void;
98
+ /**
99
+ * Convenience function to stop the listener
100
+ */
101
+ export declare function stopImpersonateListener(): void;
102
+ /**
103
+ * Convenience function to update config
104
+ */
105
+ export declare function setImpersonateConfig(config: Partial<ImpersonateListenerConfig>): void;
106
+ /**
107
+ * Convenience function to check if impersonating
108
+ */
109
+ export declare function isImpersonating(): boolean;
110
+ /**
111
+ * Convenience function to get impersonated user ID
112
+ */
113
+ export declare function getImpersonatedUserId(): string | null;
114
+ export {};
115
+ //# sourceMappingURL=impersonateListener.d.ts.map
@@ -0,0 +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;AAwB1D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,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;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAY5D;;OAEG;IACH,SAAS,IAAI,yBAAyB;IAItC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;;;;OAKG;IACH,cAAc,IAAI,IAAI;IAkFtB;;;;;;OAMG;IACH,aAAa,IAAI,IAAI;IAYrB;;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"}