@buoy-gg/impersonate 7.0.26 → 7.0.28
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/lib/commonjs/impersonate/components/DataNukeSettings.js +55 -53
- package/lib/commonjs/impersonate/components/ImpersonateHistoryList.js +9 -9
- package/lib/commonjs/impersonate/components/ImpersonateModal.js +12 -10
- package/lib/commonjs/impersonate/components/ImpersonateStatusBar.js +5 -5
- package/lib/commonjs/impersonate/components/UserAvatar.js +1 -1
- package/lib/commonjs/impersonate/components/UserCard.js +13 -13
- package/lib/commonjs/impersonate/components/UserSearchView.js +16 -16
- package/lib/commonjs/impersonate/utils/impersonateListener.js +64 -9
- package/lib/module/impersonate/components/DataNukeSettings.js +56 -54
- package/lib/module/impersonate/components/ImpersonateHistoryList.js +10 -10
- package/lib/module/impersonate/components/ImpersonateModal.js +13 -11
- package/lib/module/impersonate/components/ImpersonateStatusBar.js +6 -6
- package/lib/module/impersonate/components/UserAvatar.js +2 -2
- package/lib/module/impersonate/components/UserCard.js +14 -14
- package/lib/module/impersonate/components/UserSearchView.js +17 -17
- package/lib/module/impersonate/utils/impersonateListener.js +64 -9
- package/lib/typescript/impersonate/components/DataNukeSettings.d.ts.map +1 -1
- package/lib/typescript/impersonate/utils/impersonateListener.d.ts +7 -27
- package/lib/typescript/impersonate/utils/impersonateListener.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React, { useCallback } from "react";
|
|
11
11
|
import { View, Text, TouchableOpacity, StyleSheet, FlatList } from "react-native";
|
|
12
|
-
import {
|
|
12
|
+
import { night, Clock, Trash2, useRelativeTime } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { UserCard } from "./UserCard";
|
|
14
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
15
|
/** Wrapper to use the useRelativeTime hook per history item */
|
|
@@ -60,7 +60,7 @@ export function ImpersonateHistoryList({
|
|
|
60
60
|
style: styles.emptyIcon,
|
|
61
61
|
children: /*#__PURE__*/_jsx(Clock, {
|
|
62
62
|
size: 28,
|
|
63
|
-
color:
|
|
63
|
+
color: night.color.textTertiary
|
|
64
64
|
})
|
|
65
65
|
}), /*#__PURE__*/_jsx(Text, {
|
|
66
66
|
style: styles.emptyTitle,
|
|
@@ -92,7 +92,7 @@ export function ImpersonateHistoryList({
|
|
|
92
92
|
activeOpacity: 0.7,
|
|
93
93
|
children: /*#__PURE__*/_jsx(Trash2, {
|
|
94
94
|
size: 12,
|
|
95
|
-
color:
|
|
95
|
+
color: night.color.textTertiary
|
|
96
96
|
})
|
|
97
97
|
})]
|
|
98
98
|
}), /*#__PURE__*/_jsx(FlatList, {
|
|
@@ -121,12 +121,12 @@ const styles = StyleSheet.create({
|
|
|
121
121
|
headerTitle: {
|
|
122
122
|
fontSize: 12,
|
|
123
123
|
fontWeight: "600",
|
|
124
|
-
color:
|
|
124
|
+
color: night.color.textTertiary,
|
|
125
125
|
textTransform: "uppercase",
|
|
126
126
|
letterSpacing: 0.5
|
|
127
127
|
},
|
|
128
128
|
headerBadge: {
|
|
129
|
-
backgroundColor:
|
|
129
|
+
backgroundColor: night.color.surfaceElevated,
|
|
130
130
|
paddingHorizontal: 6,
|
|
131
131
|
paddingVertical: 2,
|
|
132
132
|
borderRadius: 4
|
|
@@ -134,7 +134,7 @@ const styles = StyleSheet.create({
|
|
|
134
134
|
headerBadgeText: {
|
|
135
135
|
fontSize: 10,
|
|
136
136
|
fontWeight: "600",
|
|
137
|
-
color:
|
|
137
|
+
color: night.color.textTertiary
|
|
138
138
|
},
|
|
139
139
|
headerSpacer: {
|
|
140
140
|
flex: 1
|
|
@@ -144,7 +144,7 @@ const styles = StyleSheet.create({
|
|
|
144
144
|
height: 24,
|
|
145
145
|
alignItems: "center",
|
|
146
146
|
justifyContent: "center",
|
|
147
|
-
backgroundColor:
|
|
147
|
+
backgroundColor: night.color.surfaceElevated,
|
|
148
148
|
borderRadius: 4
|
|
149
149
|
},
|
|
150
150
|
listContent: {
|
|
@@ -164,7 +164,7 @@ const styles = StyleSheet.create({
|
|
|
164
164
|
width: 56,
|
|
165
165
|
height: 56,
|
|
166
166
|
borderRadius: 28,
|
|
167
|
-
backgroundColor:
|
|
167
|
+
backgroundColor: night.color.surfaceElevated,
|
|
168
168
|
alignItems: "center",
|
|
169
169
|
justifyContent: "center",
|
|
170
170
|
marginBottom: 16
|
|
@@ -172,12 +172,12 @@ const styles = StyleSheet.create({
|
|
|
172
172
|
emptyTitle: {
|
|
173
173
|
fontSize: 16,
|
|
174
174
|
fontWeight: "600",
|
|
175
|
-
color:
|
|
175
|
+
color: night.color.text,
|
|
176
176
|
marginBottom: 6
|
|
177
177
|
},
|
|
178
178
|
emptyDescription: {
|
|
179
179
|
fontSize: 14,
|
|
180
|
-
color:
|
|
180
|
+
color: night.color.textSecondary,
|
|
181
181
|
textAlign: "center"
|
|
182
182
|
}
|
|
183
183
|
});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React, { useState, useCallback, useRef, useEffect } from "react";
|
|
11
11
|
import { View, StyleSheet, TouchableOpacity, TextInput } from "react-native";
|
|
12
|
-
import { JsModal as JsModalBase, TabSelector, ModalHeader, buoyColors,
|
|
12
|
+
import { JsModal as JsModalBase, TabSelector, ModalHeader, buoyColors, night, Search, X, TickProvider } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { useImpersonate } from "../hooks/useImpersonate";
|
|
14
14
|
import { useAutoClearReactQuery } from "../hooks/useAutoClearReactQuery";
|
|
15
15
|
import { useAutoClearRedux } from "../hooks/useAutoClearRedux";
|
|
@@ -170,13 +170,13 @@ export function ImpersonateModal({
|
|
|
170
170
|
style: styles.headerSearchContainer,
|
|
171
171
|
children: [/*#__PURE__*/_jsx(Search, {
|
|
172
172
|
size: 14,
|
|
173
|
-
color:
|
|
173
|
+
color: night.color.textSecondary
|
|
174
174
|
}), /*#__PURE__*/_jsx(TextInput, {
|
|
175
175
|
ref: searchInputRef,
|
|
176
176
|
testID: "buoy-impersonate-search-input",
|
|
177
177
|
style: styles.headerSearchInput,
|
|
178
178
|
placeholder: "Search by email, name, or ID...",
|
|
179
|
-
placeholderTextColor:
|
|
179
|
+
placeholderTextColor: night.color.placeholder,
|
|
180
180
|
value: searchText,
|
|
181
181
|
onChangeText: handleSearchTextChange,
|
|
182
182
|
onSubmitEditing: handleSubmitSearch,
|
|
@@ -192,14 +192,14 @@ export function ImpersonateModal({
|
|
|
192
192
|
style: styles.headerSearchClear,
|
|
193
193
|
children: /*#__PURE__*/_jsx(X, {
|
|
194
194
|
size: 14,
|
|
195
|
-
color:
|
|
195
|
+
color: night.color.textSecondary
|
|
196
196
|
})
|
|
197
197
|
}) : /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
198
198
|
onPress: () => setIsSearchActive(false),
|
|
199
199
|
style: styles.headerSearchClear,
|
|
200
200
|
children: /*#__PURE__*/_jsx(X, {
|
|
201
201
|
size: 14,
|
|
202
|
-
color:
|
|
202
|
+
color: night.color.textTertiary
|
|
203
203
|
})
|
|
204
204
|
})]
|
|
205
205
|
}) : /*#__PURE__*/_jsx(TabSelector, {
|
|
@@ -214,7 +214,7 @@ export function ImpersonateModal({
|
|
|
214
214
|
style: styles.headerActionButton,
|
|
215
215
|
children: /*#__PURE__*/_jsx(Search, {
|
|
216
216
|
size: 14,
|
|
217
|
-
color:
|
|
217
|
+
color: night.color.textSecondary
|
|
218
218
|
})
|
|
219
219
|
})
|
|
220
220
|
})]
|
|
@@ -300,7 +300,9 @@ const styles = StyleSheet.create({
|
|
|
300
300
|
inlineRoot: {
|
|
301
301
|
flex: 1,
|
|
302
302
|
minHeight: 0,
|
|
303
|
-
|
|
303
|
+
// Transparent so the desktop workbench's hoisted sky (one field spanning
|
|
304
|
+
// sidebar + panel) shows through — the shell paints its base beneath it.
|
|
305
|
+
backgroundColor: "transparent"
|
|
304
306
|
},
|
|
305
307
|
inlineHeader: {
|
|
306
308
|
paddingHorizontal: 12,
|
|
@@ -315,10 +317,10 @@ const styles = StyleSheet.create({
|
|
|
315
317
|
headerSearchContainer: {
|
|
316
318
|
flexDirection: "row",
|
|
317
319
|
alignItems: "center",
|
|
318
|
-
backgroundColor:
|
|
320
|
+
backgroundColor: night.color.surfaceElevated,
|
|
319
321
|
borderRadius: 6,
|
|
320
322
|
borderWidth: 1,
|
|
321
|
-
borderColor:
|
|
323
|
+
borderColor: night.color.border,
|
|
322
324
|
paddingHorizontal: 12,
|
|
323
325
|
paddingVertical: 8,
|
|
324
326
|
marginTop: 8,
|
|
@@ -327,7 +329,7 @@ const styles = StyleSheet.create({
|
|
|
327
329
|
},
|
|
328
330
|
headerSearchInput: {
|
|
329
331
|
flex: 1,
|
|
330
|
-
color:
|
|
332
|
+
color: night.color.text,
|
|
331
333
|
fontSize: 13,
|
|
332
334
|
marginLeft: 6,
|
|
333
335
|
paddingVertical: 2
|
|
@@ -340,7 +342,7 @@ const styles = StyleSheet.create({
|
|
|
340
342
|
width: 28,
|
|
341
343
|
height: 28,
|
|
342
344
|
borderRadius: 6,
|
|
343
|
-
backgroundColor:
|
|
345
|
+
backgroundColor: night.color.buttonSurface,
|
|
344
346
|
justifyContent: "center",
|
|
345
347
|
alignItems: "center"
|
|
346
348
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React from "react";
|
|
11
11
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
12
|
-
import { buoyColors, X } from "@buoy-gg/shared-ui";
|
|
12
|
+
import { buoyColors, night, X } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { UserAvatar } from "./UserAvatar";
|
|
14
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
15
|
export function ImpersonateStatusBar({
|
|
@@ -48,7 +48,7 @@ export function ImpersonateStatusBar({
|
|
|
48
48
|
activeOpacity: 0.7,
|
|
49
49
|
children: [/*#__PURE__*/_jsx(X, {
|
|
50
50
|
size: 12,
|
|
51
|
-
color:
|
|
51
|
+
color: night.color.danger
|
|
52
52
|
}), /*#__PURE__*/_jsx(Text, {
|
|
53
53
|
style: styles.stopButtonText,
|
|
54
54
|
children: "Stop"
|
|
@@ -82,7 +82,7 @@ const styles = StyleSheet.create({
|
|
|
82
82
|
userName: {
|
|
83
83
|
fontSize: 14,
|
|
84
84
|
fontWeight: "600",
|
|
85
|
-
color:
|
|
85
|
+
color: night.color.text
|
|
86
86
|
},
|
|
87
87
|
statusPill: {
|
|
88
88
|
flexDirection: "row",
|
|
@@ -112,14 +112,14 @@ const styles = StyleSheet.create({
|
|
|
112
112
|
gap: 4,
|
|
113
113
|
paddingHorizontal: 12,
|
|
114
114
|
paddingVertical: 6,
|
|
115
|
-
backgroundColor:
|
|
115
|
+
backgroundColor: night.color.dangerSoft,
|
|
116
116
|
borderRadius: 6,
|
|
117
117
|
borderWidth: 1,
|
|
118
|
-
borderColor:
|
|
118
|
+
borderColor: night.color.danger + "30"
|
|
119
119
|
},
|
|
120
120
|
stopButtonText: {
|
|
121
121
|
fontSize: 12,
|
|
122
122
|
fontWeight: "600",
|
|
123
|
-
color:
|
|
123
|
+
color: night.color.danger
|
|
124
124
|
}
|
|
125
125
|
});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React, { useMemo } from "react";
|
|
11
11
|
import { View, Text, StyleSheet } from "react-native";
|
|
12
|
-
import { buoyColors } from "@buoy-gg/shared-ui";
|
|
12
|
+
import { buoyColors, night } from "@buoy-gg/shared-ui";
|
|
13
13
|
|
|
14
14
|
// Avatar background colors - deterministic based on user ID
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -132,7 +132,7 @@ const styles = StyleSheet.create({
|
|
|
132
132
|
position: "absolute",
|
|
133
133
|
backgroundColor: buoyColors.success,
|
|
134
134
|
borderWidth: 2,
|
|
135
|
-
borderColor:
|
|
135
|
+
borderColor: night.color.surface
|
|
136
136
|
}
|
|
137
137
|
});
|
|
138
138
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React from "react";
|
|
11
11
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
12
|
-
import { buoyColors, Play, X, PowerToggleButton } from "@buoy-gg/shared-ui";
|
|
12
|
+
import { buoyColors, night, Play, X, PowerToggleButton } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { UserAvatar } from "./UserAvatar";
|
|
14
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
15
|
export function UserCard({
|
|
@@ -77,7 +77,7 @@ export function UserCard({
|
|
|
77
77
|
activeOpacity: 0.7,
|
|
78
78
|
children: /*#__PURE__*/_jsx(Play, {
|
|
79
79
|
size: 14,
|
|
80
|
-
color:
|
|
80
|
+
color: night.color.onAccent
|
|
81
81
|
})
|
|
82
82
|
}), showRemoveButton && onRemove && !isActive && /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
83
83
|
style: styles.removeButton,
|
|
@@ -85,7 +85,7 @@ export function UserCard({
|
|
|
85
85
|
activeOpacity: 0.7,
|
|
86
86
|
children: /*#__PURE__*/_jsx(X, {
|
|
87
87
|
size: 12,
|
|
88
|
-
color:
|
|
88
|
+
color: night.color.textTertiary
|
|
89
89
|
})
|
|
90
90
|
})]
|
|
91
91
|
}), lastUsedTime && /*#__PURE__*/_jsx(Text, {
|
|
@@ -98,10 +98,10 @@ const styles = StyleSheet.create({
|
|
|
98
98
|
container: {
|
|
99
99
|
flexDirection: "row",
|
|
100
100
|
alignItems: "center",
|
|
101
|
-
backgroundColor:
|
|
101
|
+
backgroundColor: night.color.surface,
|
|
102
102
|
borderRadius: 10,
|
|
103
103
|
borderWidth: 1,
|
|
104
|
-
borderColor:
|
|
104
|
+
borderColor: night.color.border,
|
|
105
105
|
padding: 12,
|
|
106
106
|
gap: 12
|
|
107
107
|
},
|
|
@@ -129,14 +129,14 @@ const styles = StyleSheet.create({
|
|
|
129
129
|
name: {
|
|
130
130
|
fontSize: 15,
|
|
131
131
|
fontWeight: "600",
|
|
132
|
-
color:
|
|
132
|
+
color: night.color.text,
|
|
133
133
|
flexShrink: 1
|
|
134
134
|
},
|
|
135
135
|
activeName: {
|
|
136
136
|
color: buoyColors.success
|
|
137
137
|
},
|
|
138
138
|
roleBadge: {
|
|
139
|
-
backgroundColor:
|
|
139
|
+
backgroundColor: night.color.surfaceElevated,
|
|
140
140
|
paddingHorizontal: 6,
|
|
141
141
|
paddingVertical: 2,
|
|
142
142
|
borderRadius: 4
|
|
@@ -144,12 +144,12 @@ const styles = StyleSheet.create({
|
|
|
144
144
|
roleBadgeText: {
|
|
145
145
|
fontSize: 9,
|
|
146
146
|
fontWeight: "700",
|
|
147
|
-
color:
|
|
147
|
+
color: night.color.textTertiary,
|
|
148
148
|
letterSpacing: 0.5
|
|
149
149
|
},
|
|
150
150
|
email: {
|
|
151
151
|
fontSize: 13,
|
|
152
|
-
color:
|
|
152
|
+
color: night.color.textSecondary,
|
|
153
153
|
marginBottom: 4
|
|
154
154
|
},
|
|
155
155
|
metadataRow: {
|
|
@@ -159,7 +159,7 @@ const styles = StyleSheet.create({
|
|
|
159
159
|
},
|
|
160
160
|
userId: {
|
|
161
161
|
fontSize: 11,
|
|
162
|
-
color:
|
|
162
|
+
color: night.color.textTertiary,
|
|
163
163
|
fontFamily: "monospace"
|
|
164
164
|
},
|
|
165
165
|
lastUsed: {
|
|
@@ -167,7 +167,7 @@ const styles = StyleSheet.create({
|
|
|
167
167
|
bottom: 8,
|
|
168
168
|
right: 10,
|
|
169
169
|
fontSize: 10,
|
|
170
|
-
color:
|
|
170
|
+
color: night.color.textTertiary
|
|
171
171
|
},
|
|
172
172
|
actions: {
|
|
173
173
|
flexDirection: "row",
|
|
@@ -179,7 +179,7 @@ const styles = StyleSheet.create({
|
|
|
179
179
|
width: 36,
|
|
180
180
|
height: 36,
|
|
181
181
|
borderRadius: 8,
|
|
182
|
-
backgroundColor:
|
|
182
|
+
backgroundColor: night.color.accent,
|
|
183
183
|
alignItems: "center",
|
|
184
184
|
justifyContent: "center"
|
|
185
185
|
},
|
|
@@ -187,9 +187,9 @@ const styles = StyleSheet.create({
|
|
|
187
187
|
width: 28,
|
|
188
188
|
height: 28,
|
|
189
189
|
borderRadius: 6,
|
|
190
|
-
backgroundColor:
|
|
190
|
+
backgroundColor: night.color.surfaceElevated,
|
|
191
191
|
borderWidth: 1,
|
|
192
|
-
borderColor:
|
|
192
|
+
borderColor: night.color.border,
|
|
193
193
|
alignItems: "center",
|
|
194
194
|
justifyContent: "center"
|
|
195
195
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import React, { useCallback } from "react";
|
|
12
12
|
import { View, Text, StyleSheet, FlatList, ActivityIndicator } from "react-native";
|
|
13
|
-
import { SectionHeader, EmptyState,
|
|
13
|
+
import { SectionHeader, EmptyState, night, Search, AlertTriangle, Users } from "@buoy-gg/shared-ui";
|
|
14
14
|
import { UserCard } from "./UserCard";
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
export function UserSearchView({
|
|
@@ -42,7 +42,7 @@ export function UserSearchView({
|
|
|
42
42
|
style: styles.warningCard,
|
|
43
43
|
children: [/*#__PURE__*/_jsx(AlertTriangle, {
|
|
44
44
|
size: 18,
|
|
45
|
-
color:
|
|
45
|
+
color: night.color.warning
|
|
46
46
|
}), /*#__PURE__*/_jsxs(View, {
|
|
47
47
|
style: styles.warningContent,
|
|
48
48
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
@@ -58,7 +58,7 @@ export function UserSearchView({
|
|
|
58
58
|
style: styles.loadingContainer,
|
|
59
59
|
children: [/*#__PURE__*/_jsx(ActivityIndicator, {
|
|
60
60
|
size: "small",
|
|
61
|
-
color:
|
|
61
|
+
color: night.color.accent
|
|
62
62
|
}), /*#__PURE__*/_jsx(Text, {
|
|
63
63
|
style: styles.loadingText,
|
|
64
64
|
children: "Searching users..."
|
|
@@ -69,7 +69,7 @@ export function UserSearchView({
|
|
|
69
69
|
style: styles.errorCard,
|
|
70
70
|
children: [/*#__PURE__*/_jsx(AlertTriangle, {
|
|
71
71
|
size: 16,
|
|
72
|
-
color:
|
|
72
|
+
color: night.color.danger
|
|
73
73
|
}), /*#__PURE__*/_jsx(Text, {
|
|
74
74
|
style: styles.errorText,
|
|
75
75
|
children: searchError
|
|
@@ -99,7 +99,7 @@ export function UserSearchView({
|
|
|
99
99
|
style: styles.emptyStateIcon,
|
|
100
100
|
children: /*#__PURE__*/_jsx(Users, {
|
|
101
101
|
size: 28,
|
|
102
|
-
color:
|
|
102
|
+
color: night.color.textTertiary
|
|
103
103
|
})
|
|
104
104
|
}), /*#__PURE__*/_jsx(Text, {
|
|
105
105
|
style: styles.emptyStateTitle,
|
|
@@ -136,7 +136,7 @@ const styles = StyleSheet.create({
|
|
|
136
136
|
},
|
|
137
137
|
loadingText: {
|
|
138
138
|
fontSize: 13,
|
|
139
|
-
color:
|
|
139
|
+
color: night.color.textSecondary
|
|
140
140
|
},
|
|
141
141
|
resultsSection: {
|
|
142
142
|
flex: 1,
|
|
@@ -152,10 +152,10 @@ const styles = StyleSheet.create({
|
|
|
152
152
|
flexDirection: "row",
|
|
153
153
|
alignItems: "flex-start",
|
|
154
154
|
gap: 12,
|
|
155
|
-
backgroundColor:
|
|
155
|
+
backgroundColor: night.color.warningSoft,
|
|
156
156
|
borderRadius: 10,
|
|
157
157
|
borderWidth: 1,
|
|
158
|
-
borderColor:
|
|
158
|
+
borderColor: night.color.warning + "25",
|
|
159
159
|
padding: 14
|
|
160
160
|
},
|
|
161
161
|
warningContent: {
|
|
@@ -164,28 +164,28 @@ const styles = StyleSheet.create({
|
|
|
164
164
|
warningTitle: {
|
|
165
165
|
fontSize: 14,
|
|
166
166
|
fontWeight: "600",
|
|
167
|
-
color:
|
|
167
|
+
color: night.color.warning,
|
|
168
168
|
marginBottom: 4
|
|
169
169
|
},
|
|
170
170
|
warningText: {
|
|
171
171
|
fontSize: 13,
|
|
172
|
-
color:
|
|
172
|
+
color: night.color.textSecondary,
|
|
173
173
|
lineHeight: 18
|
|
174
174
|
},
|
|
175
175
|
errorCard: {
|
|
176
176
|
flexDirection: "row",
|
|
177
177
|
alignItems: "center",
|
|
178
178
|
gap: 10,
|
|
179
|
-
backgroundColor:
|
|
179
|
+
backgroundColor: night.color.dangerSoft,
|
|
180
180
|
borderRadius: 10,
|
|
181
181
|
borderWidth: 1,
|
|
182
|
-
borderColor:
|
|
182
|
+
borderColor: night.color.danger + "25",
|
|
183
183
|
padding: 12
|
|
184
184
|
},
|
|
185
185
|
errorText: {
|
|
186
186
|
flex: 1,
|
|
187
187
|
fontSize: 13,
|
|
188
|
-
color:
|
|
188
|
+
color: night.color.danger
|
|
189
189
|
},
|
|
190
190
|
emptyStateContainer: {
|
|
191
191
|
flex: 1,
|
|
@@ -198,7 +198,7 @@ const styles = StyleSheet.create({
|
|
|
198
198
|
width: 56,
|
|
199
199
|
height: 56,
|
|
200
200
|
borderRadius: 28,
|
|
201
|
-
backgroundColor:
|
|
201
|
+
backgroundColor: night.color.surfaceElevated,
|
|
202
202
|
alignItems: "center",
|
|
203
203
|
justifyContent: "center",
|
|
204
204
|
marginBottom: 16
|
|
@@ -206,17 +206,17 @@ const styles = StyleSheet.create({
|
|
|
206
206
|
emptyStateTitle: {
|
|
207
207
|
fontSize: 16,
|
|
208
208
|
fontWeight: "600",
|
|
209
|
-
color:
|
|
209
|
+
color: night.color.text,
|
|
210
210
|
marginBottom: 6
|
|
211
211
|
},
|
|
212
212
|
emptyStateDescription: {
|
|
213
213
|
fontSize: 14,
|
|
214
|
-
color:
|
|
214
|
+
color: night.color.textSecondary,
|
|
215
215
|
textAlign: "center",
|
|
216
216
|
marginBottom: 8
|
|
217
217
|
},
|
|
218
218
|
emptyStateHint: {
|
|
219
219
|
fontSize: 12,
|
|
220
|
-
color:
|
|
220
|
+
color: night.color.textTertiary
|
|
221
221
|
}
|
|
222
222
|
});
|
|
@@ -47,11 +47,33 @@ const DEFAULT_IGNORE_PATTERNS = [/\/symbolicate$/, /\/logs$/, /\/debugger-proxy/
|
|
|
47
47
|
* listener.stopListening();
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
+
/**
|
|
51
|
+
* Cooperating-interceptor protocol with @buoy-gg/network: its interceptors
|
|
52
|
+
* carry `__buoy*` marker properties, and it re-installs itself whenever the
|
|
53
|
+
* marker disappears from the live global (that's how it survives being
|
|
54
|
+
* clobbered by Expo/DevTools re-assigning fetch). We wrap its functions, so
|
|
55
|
+
* the markers must ride along on our wrappers — otherwise the network tool
|
|
56
|
+
* would conclude it lost interception and stack a fresh patch on every check.
|
|
57
|
+
*/
|
|
58
|
+
function carryBuoyMarkers(wrapper, wrapped) {
|
|
59
|
+
for (const key of Object.keys(wrapped)) {
|
|
60
|
+
if (key.startsWith("__buoy")) {
|
|
61
|
+
wrapper[key] = wrapped[key];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
50
65
|
class ImpersonateListener {
|
|
51
66
|
isListeningFlag = false;
|
|
52
67
|
|
|
53
68
|
// Store original methods - MUST be captured before other tools patch
|
|
54
69
|
|
|
70
|
+
/**
|
|
71
|
+
* The wrappers this instance installed, for identity checks — stopListening
|
|
72
|
+
* only restores globals that are still literally ours (see there).
|
|
73
|
+
*/
|
|
74
|
+
patchedFetch = null;
|
|
75
|
+
patchedXHROpen = null;
|
|
76
|
+
patchedXHRSend = null;
|
|
55
77
|
constructor() {
|
|
56
78
|
// Initialize with current fetch - will be re-captured in startListening
|
|
57
79
|
this.originalFetch = globalThis.fetch.bind(globalThis);
|
|
@@ -136,15 +158,24 @@ class ImpersonateListener {
|
|
|
136
158
|
// CRITICAL: Re-capture fetch/XHR NOW, not at construction time
|
|
137
159
|
// This ensures we patch OVER any existing interceptors (like @buoy-gg/network)
|
|
138
160
|
// so our modifications are visible to them
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
161
|
+
//
|
|
162
|
+
// Keep the UNBOUND functions too: @buoy-gg/network stamps `__buoy*` marker
|
|
163
|
+
// properties on its interceptors and re-installs when the marker vanishes
|
|
164
|
+
// from the live global — and `.bind()` drops own properties, so the
|
|
165
|
+
// markers must be read off the unbound originals and carried forward onto
|
|
166
|
+
// our wrappers (see below).
|
|
167
|
+
const wrappedFetch = globalThis.fetch;
|
|
168
|
+
const wrappedXHROpen = XMLHttpRequest.prototype.open;
|
|
169
|
+
const wrappedXHRSend = XMLHttpRequest.prototype.send;
|
|
170
|
+
this.originalFetch = wrappedFetch.bind(globalThis);
|
|
171
|
+
this.originalXHROpen = wrappedXHROpen;
|
|
172
|
+
this.originalXHRSend = wrappedXHRSend;
|
|
142
173
|
const self = this;
|
|
143
174
|
|
|
144
175
|
// =======================================================================
|
|
145
176
|
// PATCH FETCH
|
|
146
177
|
// =======================================================================
|
|
147
|
-
|
|
178
|
+
const patchedFetch = async function (input, init) {
|
|
148
179
|
const url = self.extractUrl(input);
|
|
149
180
|
if (self.shouldInjectHeader(url)) {
|
|
150
181
|
// Create new headers with impersonation header added
|
|
@@ -162,13 +193,16 @@ class ImpersonateListener {
|
|
|
162
193
|
// Not injecting - call original fetch as-is
|
|
163
194
|
return self.originalFetch(input, init);
|
|
164
195
|
};
|
|
196
|
+
carryBuoyMarkers(patchedFetch, wrappedFetch);
|
|
197
|
+
this.patchedFetch = patchedFetch;
|
|
198
|
+
globalThis.fetch = this.patchedFetch;
|
|
165
199
|
|
|
166
200
|
// =======================================================================
|
|
167
201
|
// PATCH XMLHttpRequest
|
|
168
202
|
// =======================================================================
|
|
169
203
|
|
|
170
204
|
// Patch open() to store the URL for later use in send()
|
|
171
|
-
|
|
205
|
+
const patchedOpen = function (method, url, async = true, username, password) {
|
|
172
206
|
const xhr = this;
|
|
173
207
|
xhr._impersonateUrl = typeof url === "string" ? url : url.href;
|
|
174
208
|
const urlStr = typeof url === "string" ? url : url.toString();
|
|
@@ -176,7 +210,7 @@ class ImpersonateListener {
|
|
|
176
210
|
};
|
|
177
211
|
|
|
178
212
|
// Patch send() to inject header before sending
|
|
179
|
-
|
|
213
|
+
const patchedSend = function (body) {
|
|
180
214
|
const xhr = this;
|
|
181
215
|
if (xhr._impersonateUrl && self.shouldInjectHeader(xhr._impersonateUrl)) {
|
|
182
216
|
// Inject the impersonation header
|
|
@@ -184,6 +218,12 @@ class ImpersonateListener {
|
|
|
184
218
|
}
|
|
185
219
|
return self.originalXHRSend.call(this, body);
|
|
186
220
|
};
|
|
221
|
+
carryBuoyMarkers(patchedOpen, wrappedXHROpen);
|
|
222
|
+
carryBuoyMarkers(patchedSend, wrappedXHRSend);
|
|
223
|
+
this.patchedXHROpen = patchedOpen;
|
|
224
|
+
this.patchedXHRSend = patchedSend;
|
|
225
|
+
XMLHttpRequest.prototype.open = this.patchedXHROpen;
|
|
226
|
+
XMLHttpRequest.prototype.send = this.patchedXHRSend;
|
|
187
227
|
this.isListeningFlag = true;
|
|
188
228
|
}
|
|
189
229
|
|
|
@@ -198,9 +238,24 @@ class ImpersonateListener {
|
|
|
198
238
|
if (!this.isListeningFlag) {
|
|
199
239
|
return;
|
|
200
240
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
241
|
+
|
|
242
|
+
// Restore ONLY what is still literally ours: if another interceptor
|
|
243
|
+
// patched after us (the network tool re-asserting itself, a debugger),
|
|
244
|
+
// assigning our saved originals would silently wipe its patch. Leaving our
|
|
245
|
+
// wrapper in a foreign chain is safe — with no userId configured it is a
|
|
246
|
+
// pure pass-through.
|
|
247
|
+
if (this.patchedFetch && globalThis.fetch === this.patchedFetch) {
|
|
248
|
+
globalThis.fetch = this.originalFetch;
|
|
249
|
+
}
|
|
250
|
+
if (this.patchedXHROpen && XMLHttpRequest.prototype.open === this.patchedXHROpen) {
|
|
251
|
+
XMLHttpRequest.prototype.open = this.originalXHROpen;
|
|
252
|
+
}
|
|
253
|
+
if (this.patchedXHRSend && XMLHttpRequest.prototype.send === this.patchedXHRSend) {
|
|
254
|
+
XMLHttpRequest.prototype.send = this.originalXHRSend;
|
|
255
|
+
}
|
|
256
|
+
this.patchedFetch = null;
|
|
257
|
+
this.patchedXHROpen = null;
|
|
258
|
+
this.patchedXHRSend = null;
|
|
204
259
|
this.isListeningFlag = false;
|
|
205
260
|
}
|
|
206
261
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataNukeSettings.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/components/DataNukeSettings.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DataNukeSettings.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/components/DataNukeSettings.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;AA0B5D,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAWzE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,8CAA8C;IAC9C,KAAK,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,YAAY,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,0CAA0C;IAC1C,UAAU,EAAE,OAAO,CAAC;IACpB,kCAAkC;IAClC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IACzF,2EAA2E;IAC3E,kBAAkB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,4CAA4C;IAC5C,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAgFD,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,QAAQ,EACR,UAAU,EACV,MAAM,EACN,kBAAkB,EAClB,eAAe,GAChB,EAAE,qBAAqB,qBAkVvB"}
|
|
@@ -6,39 +6,19 @@
|
|
|
6
6
|
* as @buoy-gg/network's networkListener.
|
|
7
7
|
*/
|
|
8
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
9
|
declare class ImpersonateListener {
|
|
37
10
|
private config;
|
|
38
11
|
private isListeningFlag;
|
|
39
12
|
private originalFetch;
|
|
40
13
|
private originalXHROpen;
|
|
41
14
|
private originalXHRSend;
|
|
15
|
+
/**
|
|
16
|
+
* The wrappers this instance installed, for identity checks — stopListening
|
|
17
|
+
* only restores globals that are still literally ours (see there).
|
|
18
|
+
*/
|
|
19
|
+
private patchedFetch;
|
|
20
|
+
private patchedXHROpen;
|
|
21
|
+
private patchedXHRSend;
|
|
42
22
|
constructor();
|
|
43
23
|
/**
|
|
44
24
|
* Update impersonation config without restarting listener
|
|
@@ -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;
|
|
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;IAU1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;;;;OAKG;IACH,cAAc,IAAI,IAAI;IAsGtB;;;;;;OAMG;IACH,aAAa,IAAI,IAAI;IAgCrB;;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"}
|