@oxyhq/auth 1.0.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 (119) hide show
  1. package/README.md +56 -0
  2. package/dist/cjs/WebOxyProvider.js +287 -0
  3. package/dist/cjs/hooks/mutations/index.js +23 -0
  4. package/dist/cjs/hooks/mutations/mutationFactory.js +126 -0
  5. package/dist/cjs/hooks/mutations/useAccountMutations.js +275 -0
  6. package/dist/cjs/hooks/mutations/useServicesMutations.js +149 -0
  7. package/dist/cjs/hooks/queries/index.js +35 -0
  8. package/dist/cjs/hooks/queries/queryKeys.js +82 -0
  9. package/dist/cjs/hooks/queries/useAccountQueries.js +141 -0
  10. package/dist/cjs/hooks/queries/useSecurityQueries.js +45 -0
  11. package/dist/cjs/hooks/queries/useServicesQueries.js +113 -0
  12. package/dist/cjs/hooks/queryClient.js +110 -0
  13. package/dist/cjs/hooks/useAssets.js +225 -0
  14. package/dist/cjs/hooks/useFileDownloadUrl.js +91 -0
  15. package/dist/cjs/hooks/useFileFiltering.js +81 -0
  16. package/dist/cjs/hooks/useFollow.js +159 -0
  17. package/dist/cjs/hooks/useFollow.types.js +4 -0
  18. package/dist/cjs/hooks/useQueryClient.js +16 -0
  19. package/dist/cjs/hooks/useSessionSocket.js +215 -0
  20. package/dist/cjs/hooks/useWebSSO.js +146 -0
  21. package/dist/cjs/index.js +115 -0
  22. package/dist/cjs/stores/accountStore.js +226 -0
  23. package/dist/cjs/stores/assetStore.js +192 -0
  24. package/dist/cjs/stores/authStore.js +47 -0
  25. package/dist/cjs/stores/followStore.js +154 -0
  26. package/dist/cjs/utils/authHelpers.js +154 -0
  27. package/dist/cjs/utils/avatarUtils.js +77 -0
  28. package/dist/cjs/utils/errorHandlers.js +128 -0
  29. package/dist/cjs/utils/sessionHelpers.js +90 -0
  30. package/dist/cjs/utils/storageHelpers.js +147 -0
  31. package/dist/esm/WebOxyProvider.js +282 -0
  32. package/dist/esm/hooks/mutations/index.js +10 -0
  33. package/dist/esm/hooks/mutations/mutationFactory.js +122 -0
  34. package/dist/esm/hooks/mutations/useAccountMutations.js +267 -0
  35. package/dist/esm/hooks/mutations/useServicesMutations.js +141 -0
  36. package/dist/esm/hooks/queries/index.js +14 -0
  37. package/dist/esm/hooks/queries/queryKeys.js +76 -0
  38. package/dist/esm/hooks/queries/useAccountQueries.js +131 -0
  39. package/dist/esm/hooks/queries/useSecurityQueries.js +40 -0
  40. package/dist/esm/hooks/queries/useServicesQueries.js +105 -0
  41. package/dist/esm/hooks/queryClient.js +104 -0
  42. package/dist/esm/hooks/useAssets.js +220 -0
  43. package/dist/esm/hooks/useFileDownloadUrl.js +86 -0
  44. package/dist/esm/hooks/useFileFiltering.js +78 -0
  45. package/dist/esm/hooks/useFollow.js +154 -0
  46. package/dist/esm/hooks/useFollow.types.js +3 -0
  47. package/dist/esm/hooks/useQueryClient.js +12 -0
  48. package/dist/esm/hooks/useSessionSocket.js +209 -0
  49. package/dist/esm/hooks/useWebSSO.js +143 -0
  50. package/dist/esm/index.js +48 -0
  51. package/dist/esm/stores/accountStore.js +219 -0
  52. package/dist/esm/stores/assetStore.js +180 -0
  53. package/dist/esm/stores/authStore.js +44 -0
  54. package/dist/esm/stores/followStore.js +151 -0
  55. package/dist/esm/utils/authHelpers.js +145 -0
  56. package/dist/esm/utils/avatarUtils.js +72 -0
  57. package/dist/esm/utils/errorHandlers.js +121 -0
  58. package/dist/esm/utils/sessionHelpers.js +84 -0
  59. package/dist/esm/utils/storageHelpers.js +108 -0
  60. package/dist/types/WebOxyProvider.d.ts +97 -0
  61. package/dist/types/hooks/mutations/index.d.ts +8 -0
  62. package/dist/types/hooks/mutations/mutationFactory.d.ts +75 -0
  63. package/dist/types/hooks/mutations/useAccountMutations.d.ts +68 -0
  64. package/dist/types/hooks/mutations/useServicesMutations.d.ts +22 -0
  65. package/dist/types/hooks/queries/index.d.ts +10 -0
  66. package/dist/types/hooks/queries/queryKeys.d.ts +64 -0
  67. package/dist/types/hooks/queries/useAccountQueries.d.ts +42 -0
  68. package/dist/types/hooks/queries/useSecurityQueries.d.ts +14 -0
  69. package/dist/types/hooks/queries/useServicesQueries.d.ts +31 -0
  70. package/dist/types/hooks/queryClient.d.ts +18 -0
  71. package/dist/types/hooks/useAssets.d.ts +34 -0
  72. package/dist/types/hooks/useFileDownloadUrl.d.ts +18 -0
  73. package/dist/types/hooks/useFileFiltering.d.ts +28 -0
  74. package/dist/types/hooks/useFollow.d.ts +61 -0
  75. package/dist/types/hooks/useFollow.types.d.ts +32 -0
  76. package/dist/types/hooks/useQueryClient.d.ts +6 -0
  77. package/dist/types/hooks/useSessionSocket.d.ts +13 -0
  78. package/dist/types/hooks/useWebSSO.d.ts +57 -0
  79. package/dist/types/index.d.ts +46 -0
  80. package/dist/types/stores/accountStore.d.ts +33 -0
  81. package/dist/types/stores/assetStore.d.ts +53 -0
  82. package/dist/types/stores/authStore.d.ts +16 -0
  83. package/dist/types/stores/followStore.d.ts +24 -0
  84. package/dist/types/utils/authHelpers.d.ts +98 -0
  85. package/dist/types/utils/avatarUtils.d.ts +33 -0
  86. package/dist/types/utils/errorHandlers.d.ts +34 -0
  87. package/dist/types/utils/sessionHelpers.d.ts +63 -0
  88. package/dist/types/utils/storageHelpers.d.ts +27 -0
  89. package/package.json +71 -0
  90. package/src/WebOxyProvider.tsx +372 -0
  91. package/src/global.d.ts +1 -0
  92. package/src/hooks/mutations/index.ts +25 -0
  93. package/src/hooks/mutations/mutationFactory.ts +215 -0
  94. package/src/hooks/mutations/useAccountMutations.ts +344 -0
  95. package/src/hooks/mutations/useServicesMutations.ts +164 -0
  96. package/src/hooks/queries/index.ts +36 -0
  97. package/src/hooks/queries/queryKeys.ts +88 -0
  98. package/src/hooks/queries/useAccountQueries.ts +152 -0
  99. package/src/hooks/queries/useSecurityQueries.ts +64 -0
  100. package/src/hooks/queries/useServicesQueries.ts +126 -0
  101. package/src/hooks/queryClient.ts +112 -0
  102. package/src/hooks/useAssets.ts +291 -0
  103. package/src/hooks/useFileDownloadUrl.ts +118 -0
  104. package/src/hooks/useFileFiltering.ts +115 -0
  105. package/src/hooks/useFollow.ts +175 -0
  106. package/src/hooks/useFollow.types.ts +33 -0
  107. package/src/hooks/useQueryClient.ts +17 -0
  108. package/src/hooks/useSessionSocket.ts +233 -0
  109. package/src/hooks/useWebSSO.ts +187 -0
  110. package/src/index.ts +144 -0
  111. package/src/stores/accountStore.ts +296 -0
  112. package/src/stores/assetStore.ts +281 -0
  113. package/src/stores/authStore.ts +63 -0
  114. package/src/stores/followStore.ts +181 -0
  115. package/src/utils/authHelpers.ts +183 -0
  116. package/src/utils/avatarUtils.ts +103 -0
  117. package/src/utils/errorHandlers.ts +194 -0
  118. package/src/utils/sessionHelpers.ts +151 -0
  119. package/src/utils/storageHelpers.ts +130 -0
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useUploadFile = exports.useUpdatePrivacySettings = exports.useUpdateAccountSettings = exports.useUploadAvatar = exports.useUpdateProfile = void 0;
4
+ const react_query_1 = require("@tanstack/react-query");
5
+ const queryKeys_1 = require("../queries/queryKeys");
6
+ const WebOxyProvider_1 = require("../../WebOxyProvider");
7
+ const sonner_1 = require("sonner");
8
+ const avatarUtils_1 = require("../../utils/avatarUtils");
9
+ const authStore_1 = require("../../stores/authStore");
10
+ const authHelpers_1 = require("../../utils/authHelpers");
11
+ /**
12
+ * Update user profile with optimistic updates and offline queue support
13
+ */
14
+ const useUpdateProfile = () => {
15
+ const { oxyServices, activeSessionId, user } = (0, WebOxyProvider_1.useWebOxy)();
16
+ const queryClient = (0, react_query_1.useQueryClient)();
17
+ return (0, react_query_1.useMutation)({
18
+ mutationFn: async (updates) => {
19
+ return (0, authHelpers_1.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.updateProfile(updates));
20
+ },
21
+ // Optimistic update
22
+ onMutate: async (updates) => {
23
+ // Cancel outgoing refetches
24
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.accounts.current() });
25
+ // Snapshot previous value
26
+ const previousUser = queryClient.getQueryData(queryKeys_1.queryKeys.accounts.current());
27
+ // Optimistically update
28
+ if (previousUser) {
29
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), {
30
+ ...previousUser,
31
+ ...updates,
32
+ });
33
+ // Also update profile query if sessionId is available
34
+ if (activeSessionId) {
35
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), {
36
+ ...previousUser,
37
+ ...updates,
38
+ });
39
+ }
40
+ }
41
+ return { previousUser };
42
+ },
43
+ // On error, rollback
44
+ onError: (error, updates, context) => {
45
+ if (context?.previousUser) {
46
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), context.previousUser);
47
+ if (activeSessionId) {
48
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), context.previousUser);
49
+ }
50
+ }
51
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to update profile');
52
+ },
53
+ // On success, invalidate and refetch
54
+ onSuccess: (data, updates) => {
55
+ // Update cache with server response
56
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), data);
57
+ if (activeSessionId) {
58
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), data);
59
+ }
60
+ // Update authStore so frontend components see the changes immediately
61
+ authStore_1.useAuthStore.getState().setUser(data);
62
+ // If avatar was updated, refresh accountStore with cache-busted URL
63
+ if (updates.avatar && activeSessionId && oxyServices) {
64
+ (0, avatarUtils_1.refreshAvatarInStore)(activeSessionId, updates.avatar, oxyServices);
65
+ }
66
+ // Invalidate all related queries to refresh everywhere
67
+ (0, queryKeys_1.invalidateUserQueries)(queryClient);
68
+ (0, queryKeys_1.invalidateAccountQueries)(queryClient);
69
+ },
70
+ });
71
+ };
72
+ exports.useUpdateProfile = useUpdateProfile;
73
+ /**
74
+ * Upload avatar with progress tracking and offline queue support
75
+ */
76
+ const useUploadAvatar = () => {
77
+ const { oxyServices, activeSessionId } = (0, WebOxyProvider_1.useWebOxy)();
78
+ const queryClient = (0, react_query_1.useQueryClient)();
79
+ return (0, react_query_1.useMutation)({
80
+ mutationFn: async (file) => {
81
+ return (0, authHelpers_1.authenticatedApiCall)(oxyServices, activeSessionId, async () => {
82
+ // Upload file first
83
+ const uploadResult = await oxyServices.assetUpload(file, 'public');
84
+ const fileId = uploadResult?.file?.id || uploadResult?.id || uploadResult;
85
+ if (!fileId || typeof fileId !== 'string') {
86
+ throw new Error('Failed to get file ID from upload result');
87
+ }
88
+ // Update profile with file ID
89
+ return await oxyServices.updateProfile({ avatar: fileId });
90
+ });
91
+ },
92
+ onMutate: async (file) => {
93
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.accounts.current() });
94
+ const previousUser = queryClient.getQueryData(queryKeys_1.queryKeys.accounts.current());
95
+ // Optimistically set a temporary avatar (using file URI as placeholder)
96
+ if (previousUser) {
97
+ const optimisticUser = {
98
+ ...previousUser,
99
+ avatar: file.uri, // Temporary, will be replaced with fileId
100
+ };
101
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), optimisticUser);
102
+ if (activeSessionId) {
103
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), optimisticUser);
104
+ }
105
+ }
106
+ return { previousUser };
107
+ },
108
+ onError: (error, file, context) => {
109
+ if (context?.previousUser) {
110
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), context.previousUser);
111
+ if (activeSessionId) {
112
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), context.previousUser);
113
+ }
114
+ }
115
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to upload avatar');
116
+ },
117
+ onSuccess: (data) => {
118
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), data);
119
+ if (activeSessionId) {
120
+ queryClient.setQueryData(queryKeys_1.queryKeys.users.profile(activeSessionId), data);
121
+ }
122
+ // Update authStore so frontend components see the changes immediately
123
+ authStore_1.useAuthStore.getState().setUser(data);
124
+ // Refresh accountStore with cache-busted URL if avatar was updated
125
+ if (data?.avatar && activeSessionId && oxyServices) {
126
+ (0, avatarUtils_1.refreshAvatarInStore)(activeSessionId, data.avatar, oxyServices);
127
+ }
128
+ // Invalidate all related queries to refresh everywhere
129
+ (0, queryKeys_1.invalidateUserQueries)(queryClient);
130
+ (0, queryKeys_1.invalidateAccountQueries)(queryClient);
131
+ sonner_1.toast.success('Avatar updated successfully');
132
+ },
133
+ });
134
+ };
135
+ exports.useUploadAvatar = useUploadAvatar;
136
+ /**
137
+ * Update account settings
138
+ */
139
+ const useUpdateAccountSettings = () => {
140
+ const { oxyServices, activeSessionId } = (0, WebOxyProvider_1.useWebOxy)();
141
+ const queryClient = (0, react_query_1.useQueryClient)();
142
+ return (0, react_query_1.useMutation)({
143
+ mutationFn: async (settings) => {
144
+ return await oxyServices.updateProfile({ privacySettings: settings });
145
+ },
146
+ onMutate: async (settings) => {
147
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.accounts.settings() });
148
+ const previousUser = queryClient.getQueryData(queryKeys_1.queryKeys.accounts.current());
149
+ if (previousUser) {
150
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), {
151
+ ...previousUser,
152
+ privacySettings: {
153
+ ...previousUser.privacySettings,
154
+ ...settings,
155
+ },
156
+ });
157
+ }
158
+ return { previousUser };
159
+ },
160
+ onError: (error, settings, context) => {
161
+ if (context?.previousUser) {
162
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), context.previousUser);
163
+ }
164
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to update settings');
165
+ },
166
+ onSuccess: (data) => {
167
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), data);
168
+ // Update authStore so frontend components see the changes immediately
169
+ authStore_1.useAuthStore.getState().setUser(data);
170
+ (0, queryKeys_1.invalidateAccountQueries)(queryClient);
171
+ sonner_1.toast.success('Settings updated successfully');
172
+ },
173
+ onSettled: () => {
174
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.accounts.settings() });
175
+ },
176
+ });
177
+ };
178
+ exports.useUpdateAccountSettings = useUpdateAccountSettings;
179
+ /**
180
+ * Update privacy settings with optimistic updates and authentication handling
181
+ */
182
+ const useUpdatePrivacySettings = () => {
183
+ const { oxyServices, activeSessionId, user } = (0, WebOxyProvider_1.useWebOxy)();
184
+ const queryClient = (0, react_query_1.useQueryClient)();
185
+ return (0, react_query_1.useMutation)({
186
+ mutationFn: async ({ settings, userId }) => {
187
+ const targetUserId = userId || user?.id;
188
+ if (!targetUserId) {
189
+ throw new Error('User ID is required');
190
+ }
191
+ return (0, authHelpers_1.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.updatePrivacySettings(settings, targetUserId));
192
+ },
193
+ // Optimistic update
194
+ onMutate: async ({ settings, userId }) => {
195
+ const targetUserId = userId || user?.id;
196
+ if (!targetUserId)
197
+ return;
198
+ // Cancel outgoing refetches
199
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.privacy.settings(targetUserId) });
200
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.accounts.current() });
201
+ // Snapshot previous values
202
+ const previousPrivacySettings = queryClient.getQueryData(queryKeys_1.queryKeys.privacy.settings(targetUserId));
203
+ const previousUser = queryClient.getQueryData(queryKeys_1.queryKeys.accounts.current());
204
+ // Optimistically update privacy settings
205
+ if (previousPrivacySettings) {
206
+ queryClient.setQueryData(queryKeys_1.queryKeys.privacy.settings(targetUserId), {
207
+ ...previousPrivacySettings,
208
+ ...settings,
209
+ });
210
+ }
211
+ // Also update user query if available
212
+ if (previousUser) {
213
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), {
214
+ ...previousUser,
215
+ privacySettings: {
216
+ ...previousUser.privacySettings,
217
+ ...settings,
218
+ },
219
+ });
220
+ }
221
+ return { previousPrivacySettings, previousUser };
222
+ },
223
+ // On error, rollback
224
+ onError: (error, { userId }, context) => {
225
+ const targetUserId = userId || user?.id;
226
+ if (context?.previousPrivacySettings && targetUserId) {
227
+ queryClient.setQueryData(queryKeys_1.queryKeys.privacy.settings(targetUserId), context.previousPrivacySettings);
228
+ }
229
+ if (context?.previousUser) {
230
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), context.previousUser);
231
+ }
232
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to update privacy settings');
233
+ },
234
+ // On success, invalidate and refetch
235
+ onSuccess: (data, { userId }) => {
236
+ const targetUserId = userId || user?.id;
237
+ if (targetUserId) {
238
+ queryClient.setQueryData(queryKeys_1.queryKeys.privacy.settings(targetUserId), data);
239
+ }
240
+ // Also update account query if it contains privacy settings
241
+ const currentUser = queryClient.getQueryData(queryKeys_1.queryKeys.accounts.current());
242
+ if (currentUser) {
243
+ const updatedUser = {
244
+ ...currentUser,
245
+ privacySettings: data,
246
+ };
247
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), updatedUser);
248
+ // Update authStore so frontend components see the changes immediately
249
+ authStore_1.useAuthStore.getState().setUser(updatedUser);
250
+ }
251
+ (0, queryKeys_1.invalidateAccountQueries)(queryClient);
252
+ },
253
+ // Always refetch after error or success
254
+ onSettled: (data, error, { userId }) => {
255
+ const targetUserId = userId || user?.id;
256
+ if (targetUserId) {
257
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.privacy.settings(targetUserId) });
258
+ }
259
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.accounts.current() });
260
+ },
261
+ });
262
+ };
263
+ exports.useUpdatePrivacySettings = useUpdatePrivacySettings;
264
+ /**
265
+ * Upload file with authentication handling and progress tracking
266
+ */
267
+ const useUploadFile = () => {
268
+ const { oxyServices, activeSessionId } = (0, WebOxyProvider_1.useWebOxy)();
269
+ return (0, react_query_1.useMutation)({
270
+ mutationFn: async ({ file, visibility, metadata, onProgress }) => {
271
+ return (0, authHelpers_1.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.assetUpload(file, visibility, metadata, onProgress));
272
+ },
273
+ });
274
+ };
275
+ exports.useUploadFile = useUploadFile;
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRemoveDevice = exports.useUpdateDeviceName = exports.useLogoutAll = exports.useLogoutSession = exports.useSwitchSession = void 0;
4
+ const react_query_1 = require("@tanstack/react-query");
5
+ const queryKeys_1 = require("../queries/queryKeys");
6
+ const WebOxyProvider_1 = require("../../WebOxyProvider");
7
+ const sonner_1 = require("sonner");
8
+ /**
9
+ * Switch active session
10
+ */
11
+ const useSwitchSession = () => {
12
+ const { switchSession, activeSessionId } = (0, WebOxyProvider_1.useWebOxy)();
13
+ const queryClient = (0, react_query_1.useQueryClient)();
14
+ return (0, react_query_1.useMutation)({
15
+ mutationFn: async (sessionId) => {
16
+ return await switchSession(sessionId);
17
+ },
18
+ onSuccess: (user) => {
19
+ // Invalidate all session queries
20
+ (0, queryKeys_1.invalidateSessionQueries)(queryClient);
21
+ // Update current user query
22
+ queryClient.setQueryData(queryKeys_1.queryKeys.accounts.current(), user);
23
+ // Invalidate account queries
24
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.accounts.all });
25
+ },
26
+ onError: (error) => {
27
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to switch session');
28
+ },
29
+ });
30
+ };
31
+ exports.useSwitchSession = useSwitchSession;
32
+ /**
33
+ * Logout from a session
34
+ */
35
+ const useLogoutSession = () => {
36
+ const { oxyServices, activeSessionId, sessions } = (0, WebOxyProvider_1.useWebOxy)();
37
+ const queryClient = (0, react_query_1.useQueryClient)();
38
+ return (0, react_query_1.useMutation)({
39
+ mutationFn: async (targetSessionId) => {
40
+ if (!activeSessionId) {
41
+ throw new Error('No active session');
42
+ }
43
+ const sessionToLogout = targetSessionId || activeSessionId;
44
+ await oxyServices.logoutSession(activeSessionId, sessionToLogout);
45
+ return sessionToLogout;
46
+ },
47
+ onMutate: async (targetSessionId) => {
48
+ // Cancel outgoing queries
49
+ await queryClient.cancelQueries({ queryKey: queryKeys_1.queryKeys.sessions.all });
50
+ // Snapshot previous sessions
51
+ const previousSessions = queryClient.getQueryData(queryKeys_1.queryKeys.sessions.list());
52
+ // Optimistically remove session
53
+ if (previousSessions) {
54
+ const sessionToLogout = targetSessionId || activeSessionId;
55
+ const updatedSessions = previousSessions.filter((s) => s.sessionId !== sessionToLogout);
56
+ queryClient.setQueryData(queryKeys_1.queryKeys.sessions.list(), updatedSessions);
57
+ }
58
+ return { previousSessions };
59
+ },
60
+ onError: (error, targetSessionId, context) => {
61
+ // Rollback on error
62
+ if (context?.previousSessions) {
63
+ queryClient.setQueryData(queryKeys_1.queryKeys.sessions.list(), context.previousSessions);
64
+ }
65
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to logout');
66
+ },
67
+ onSuccess: () => {
68
+ // Invalidate all session queries
69
+ (0, queryKeys_1.invalidateSessionQueries)(queryClient);
70
+ },
71
+ onSettled: () => {
72
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.sessions.all });
73
+ },
74
+ });
75
+ };
76
+ exports.useLogoutSession = useLogoutSession;
77
+ /**
78
+ * Logout from all sessions
79
+ */
80
+ const useLogoutAll = () => {
81
+ const { oxyServices, activeSessionId, clearSessionState } = (0, WebOxyProvider_1.useWebOxy)();
82
+ const queryClient = (0, react_query_1.useQueryClient)();
83
+ return (0, react_query_1.useMutation)({
84
+ mutationFn: async () => {
85
+ if (!activeSessionId) {
86
+ throw new Error('No active session');
87
+ }
88
+ await oxyServices.logoutAllSessions(activeSessionId);
89
+ await clearSessionState();
90
+ },
91
+ onSuccess: () => {
92
+ // Clear all queries
93
+ queryClient.clear();
94
+ sonner_1.toast.success('Logged out from all sessions');
95
+ },
96
+ onError: (error) => {
97
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to logout from all sessions');
98
+ },
99
+ });
100
+ };
101
+ exports.useLogoutAll = useLogoutAll;
102
+ /**
103
+ * Update device name
104
+ */
105
+ const useUpdateDeviceName = () => {
106
+ const { oxyServices, activeSessionId } = (0, WebOxyProvider_1.useWebOxy)();
107
+ const queryClient = (0, react_query_1.useQueryClient)();
108
+ return (0, react_query_1.useMutation)({
109
+ mutationFn: async (deviceName) => {
110
+ if (!activeSessionId) {
111
+ throw new Error('No active session');
112
+ }
113
+ return await oxyServices.updateDeviceName(activeSessionId, deviceName);
114
+ },
115
+ onSuccess: () => {
116
+ // Invalidate device and session queries
117
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.devices.all });
118
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.sessions.all });
119
+ sonner_1.toast.success('Device name updated');
120
+ },
121
+ onError: (error) => {
122
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to update device name');
123
+ },
124
+ });
125
+ };
126
+ exports.useUpdateDeviceName = useUpdateDeviceName;
127
+ /**
128
+ * Remove a device
129
+ */
130
+ const useRemoveDevice = () => {
131
+ const { oxyServices } = (0, WebOxyProvider_1.useWebOxy)();
132
+ const queryClient = (0, react_query_1.useQueryClient)();
133
+ return (0, react_query_1.useMutation)({
134
+ mutationFn: async (deviceId) => {
135
+ await oxyServices.removeDevice(deviceId);
136
+ return deviceId;
137
+ },
138
+ onSuccess: () => {
139
+ // Invalidate device queries
140
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.devices.all });
141
+ queryClient.invalidateQueries({ queryKey: queryKeys_1.queryKeys.sessions.all });
142
+ sonner_1.toast.success('Device removed');
143
+ },
144
+ onError: (error) => {
145
+ sonner_1.toast.error(error instanceof Error ? error.message : 'Failed to remove device');
146
+ },
147
+ });
148
+ };
149
+ exports.useRemoveDevice = useRemoveDevice;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Query Hooks
4
+ *
5
+ * TanStack Query hooks for fetching Oxy services data.
6
+ * All hooks follow the same pattern with optional `enabled` parameter.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.invalidateSessionQueries = exports.invalidateUserQueries = exports.invalidateAccountQueries = exports.queryKeys = exports.useRecentSecurityActivity = exports.useSecurityActivity = exports.useSecurityInfo = exports.useUserDevices = exports.useDeviceSessions = exports.useSession = exports.useSessions = exports.usePrivacySettings = exports.useUsersBySessions = exports.useUserByUsername = exports.useUserById = exports.useCurrentUser = exports.useUserProfiles = exports.useUserProfile = void 0;
10
+ // Account and user query hooks
11
+ var useAccountQueries_1 = require("./useAccountQueries");
12
+ Object.defineProperty(exports, "useUserProfile", { enumerable: true, get: function () { return useAccountQueries_1.useUserProfile; } });
13
+ Object.defineProperty(exports, "useUserProfiles", { enumerable: true, get: function () { return useAccountQueries_1.useUserProfiles; } });
14
+ Object.defineProperty(exports, "useCurrentUser", { enumerable: true, get: function () { return useAccountQueries_1.useCurrentUser; } });
15
+ Object.defineProperty(exports, "useUserById", { enumerable: true, get: function () { return useAccountQueries_1.useUserById; } });
16
+ Object.defineProperty(exports, "useUserByUsername", { enumerable: true, get: function () { return useAccountQueries_1.useUserByUsername; } });
17
+ Object.defineProperty(exports, "useUsersBySessions", { enumerable: true, get: function () { return useAccountQueries_1.useUsersBySessions; } });
18
+ Object.defineProperty(exports, "usePrivacySettings", { enumerable: true, get: function () { return useAccountQueries_1.usePrivacySettings; } });
19
+ // Service query hooks (sessions, devices, security)
20
+ var useServicesQueries_1 = require("./useServicesQueries");
21
+ Object.defineProperty(exports, "useSessions", { enumerable: true, get: function () { return useServicesQueries_1.useSessions; } });
22
+ Object.defineProperty(exports, "useSession", { enumerable: true, get: function () { return useServicesQueries_1.useSession; } });
23
+ Object.defineProperty(exports, "useDeviceSessions", { enumerable: true, get: function () { return useServicesQueries_1.useDeviceSessions; } });
24
+ Object.defineProperty(exports, "useUserDevices", { enumerable: true, get: function () { return useServicesQueries_1.useUserDevices; } });
25
+ Object.defineProperty(exports, "useSecurityInfo", { enumerable: true, get: function () { return useServicesQueries_1.useSecurityInfo; } });
26
+ // Security activity query hooks
27
+ var useSecurityQueries_1 = require("./useSecurityQueries");
28
+ Object.defineProperty(exports, "useSecurityActivity", { enumerable: true, get: function () { return useSecurityQueries_1.useSecurityActivity; } });
29
+ Object.defineProperty(exports, "useRecentSecurityActivity", { enumerable: true, get: function () { return useSecurityQueries_1.useRecentSecurityActivity; } });
30
+ // Query keys and invalidation helpers (for advanced usage)
31
+ var queryKeys_1 = require("./queryKeys");
32
+ Object.defineProperty(exports, "queryKeys", { enumerable: true, get: function () { return queryKeys_1.queryKeys; } });
33
+ Object.defineProperty(exports, "invalidateAccountQueries", { enumerable: true, get: function () { return queryKeys_1.invalidateAccountQueries; } });
34
+ Object.defineProperty(exports, "invalidateUserQueries", { enumerable: true, get: function () { return queryKeys_1.invalidateUserQueries; } });
35
+ Object.defineProperty(exports, "invalidateSessionQueries", { enumerable: true, get: function () { return queryKeys_1.invalidateSessionQueries; } });
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized query keys for TanStack Query
4
+ *
5
+ * Following best practices:
6
+ * - Use arrays for hierarchical keys
7
+ * - Include all parameters in the key
8
+ * - Use consistent naming conventions
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.invalidateSessionQueries = exports.invalidateUserQueries = exports.invalidateAccountQueries = exports.queryKeys = void 0;
12
+ exports.queryKeys = {
13
+ // Account queries
14
+ accounts: {
15
+ all: ['accounts'],
16
+ lists: () => [...exports.queryKeys.accounts.all, 'list'],
17
+ list: (sessionIds) => [...exports.queryKeys.accounts.lists(), sessionIds],
18
+ details: () => [...exports.queryKeys.accounts.all, 'detail'],
19
+ detail: (sessionId) => [...exports.queryKeys.accounts.details(), sessionId],
20
+ current: () => [...exports.queryKeys.accounts.all, 'current'],
21
+ settings: () => [...exports.queryKeys.accounts.all, 'settings'],
22
+ },
23
+ // User queries
24
+ users: {
25
+ all: ['users'],
26
+ lists: () => [...exports.queryKeys.users.all, 'list'],
27
+ list: (userIds) => [...exports.queryKeys.users.lists(), userIds],
28
+ details: () => [...exports.queryKeys.users.all, 'detail'],
29
+ detail: (userId) => [...exports.queryKeys.users.details(), userId],
30
+ profile: (sessionId) => [...exports.queryKeys.users.details(), sessionId, 'profile'],
31
+ },
32
+ // Session queries
33
+ sessions: {
34
+ all: ['sessions'],
35
+ lists: () => [...exports.queryKeys.sessions.all, 'list'],
36
+ list: (userId) => [...exports.queryKeys.sessions.lists(), userId],
37
+ details: () => [...exports.queryKeys.sessions.all, 'detail'],
38
+ detail: (sessionId) => [...exports.queryKeys.sessions.details(), sessionId],
39
+ active: () => [...exports.queryKeys.sessions.all, 'active'],
40
+ device: (deviceId) => [...exports.queryKeys.sessions.all, 'device', deviceId],
41
+ },
42
+ // Device queries
43
+ devices: {
44
+ all: ['devices'],
45
+ lists: () => [...exports.queryKeys.devices.all, 'list'],
46
+ list: (userId) => [...exports.queryKeys.devices.lists(), userId],
47
+ details: () => [...exports.queryKeys.devices.all, 'detail'],
48
+ detail: (deviceId) => [...exports.queryKeys.devices.details(), deviceId],
49
+ },
50
+ // Privacy settings queries
51
+ privacy: {
52
+ all: ['privacy'],
53
+ settings: (userId) => [...exports.queryKeys.privacy.all, 'settings', userId || 'current'],
54
+ },
55
+ // Security activity queries
56
+ security: {
57
+ all: ['security'],
58
+ activity: (limit, offset, eventType) => [...exports.queryKeys.security.all, 'activity', limit, offset, eventType],
59
+ recent: (limit) => [...exports.queryKeys.security.all, 'recent', limit],
60
+ },
61
+ };
62
+ /**
63
+ * Helper to invalidate all account-related queries
64
+ */
65
+ const invalidateAccountQueries = (queryClient) => {
66
+ queryClient.invalidateQueries({ queryKey: exports.queryKeys.accounts.all });
67
+ };
68
+ exports.invalidateAccountQueries = invalidateAccountQueries;
69
+ /**
70
+ * Helper to invalidate all user-related queries
71
+ */
72
+ const invalidateUserQueries = (queryClient) => {
73
+ queryClient.invalidateQueries({ queryKey: exports.queryKeys.users.all });
74
+ };
75
+ exports.invalidateUserQueries = invalidateUserQueries;
76
+ /**
77
+ * Helper to invalidate all session-related queries
78
+ */
79
+ const invalidateSessionQueries = (queryClient) => {
80
+ queryClient.invalidateQueries({ queryKey: exports.queryKeys.sessions.all });
81
+ };
82
+ exports.invalidateSessionQueries = invalidateSessionQueries;