@oxyhq/services 6.10.3 → 6.10.5
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 +27 -1
- package/lib/commonjs/index.js +32 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +10 -27
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/index.js +31 -0
- package/lib/commonjs/ui/hooks/queries/index.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/paymentTypes.js +2 -0
- package/lib/commonjs/ui/hooks/queries/paymentTypes.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/queryKeys.js +13 -0
- package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js +140 -0
- package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +26 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queryClient.js +1 -1
- package/lib/commonjs/ui/hooks/queryClient.js.map +1 -1
- package/lib/commonjs/ui/hooks/useWebSSO.js +7 -45
- package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +10 -27
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/hooks/queries/index.js +7 -2
- package/lib/module/ui/hooks/queries/index.js.map +1 -1
- package/lib/module/ui/hooks/queries/paymentTypes.js +2 -0
- package/lib/module/ui/hooks/queries/paymentTypes.js.map +1 -0
- package/lib/module/ui/hooks/queries/queryKeys.js +13 -0
- package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/module/ui/hooks/queries/usePaymentQueries.js +132 -0
- package/lib/module/ui/hooks/queries/usePaymentQueries.js.map +1 -0
- package/lib/module/ui/hooks/queries/useServicesQueries.js +24 -0
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/queryClient.js +1 -1
- package/lib/module/ui/hooks/queryClient.js.map +1 -1
- package/lib/module/ui/hooks/useWebSSO.js +7 -45
- package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts +3 -1
- package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/paymentTypes.d.ts +137 -0
- package/lib/typescript/commonjs/ui/hooks/queries/paymentTypes.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +11 -0
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/usePaymentQueries.d.ts +63 -0
- package/lib/typescript/commonjs/ui/hooks/queries/usePaymentQueries.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts +11 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/index.d.ts +3 -1
- package/lib/typescript/module/ui/hooks/queries/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/paymentTypes.d.ts +137 -0
- package/lib/typescript/module/ui/hooks/queries/paymentTypes.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +11 -0
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/usePaymentQueries.d.ts +63 -0
- package/lib/typescript/module/ui/hooks/queries/usePaymentQueries.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts +11 -1
- package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +9 -0
- package/src/ui/context/hooks/useAuthOperations.ts +10 -27
- package/src/ui/hooks/queries/index.ts +25 -1
- package/src/ui/hooks/queries/paymentTypes.ts +141 -0
- package/src/ui/hooks/queries/queryKeys.ts +26 -0
- package/src/ui/hooks/queries/usePaymentQueries.ts +136 -0
- package/src/ui/hooks/queries/useServicesQueries.ts +26 -1
- package/src/ui/hooks/queryClient.ts +1 -0
- package/src/ui/hooks/useWebSSO.ts +7 -46
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { authenticatedApiCall } from '@oxyhq/core';
|
|
3
|
+
import { queryKeys } from './queryKeys';
|
|
4
|
+
import { useOxy } from '../../context/OxyContext';
|
|
5
|
+
import type {
|
|
6
|
+
Subscription,
|
|
7
|
+
Payment,
|
|
8
|
+
Wallet,
|
|
9
|
+
WalletTransactionsResponse,
|
|
10
|
+
} from './paymentTypes';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Payment / wallet / subscription query hooks.
|
|
14
|
+
*
|
|
15
|
+
* These replace the imperative `oxyServices.*` + `Promise.allSettled` +
|
|
16
|
+
* `useEffect` pattern used in app screens. Each hook:
|
|
17
|
+
* - is gated on `isAuthenticated` (the underlying SDK methods read the
|
|
18
|
+
* current user id off the access token and throw when unauthenticated),
|
|
19
|
+
* - routes through `authenticatedApiCall` so a stale token is refreshed and
|
|
20
|
+
* auth errors are handled consistently (matches `useUserDevices` /
|
|
21
|
+
* `usePrivacySettings`),
|
|
22
|
+
* - keeps its `queryFn` pure — no store writes, no side effects.
|
|
23
|
+
*
|
|
24
|
+
* The wrapped SDK methods (`@oxyhq/core` payment mixin) return `any`; the
|
|
25
|
+
* generic on `authenticatedApiCall<T>` pins the resolved value to the
|
|
26
|
+
* precise domain type so consumers get full typing.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the current user's subscription.
|
|
31
|
+
*
|
|
32
|
+
* Wraps `oxyServices.getCurrentUserSubscription()`
|
|
33
|
+
* (`GET /subscription/:userId`). Returns the persisted subscription or the
|
|
34
|
+
* API's `{ plan: 'basic' }` fallback when the user has never subscribed.
|
|
35
|
+
*/
|
|
36
|
+
export const useUserSubscription = (options?: { enabled?: boolean }) => {
|
|
37
|
+
const { oxyServices, isAuthenticated, activeSessionId } = useOxy();
|
|
38
|
+
|
|
39
|
+
return useQuery({
|
|
40
|
+
queryKey: queryKeys.payments.subscription(),
|
|
41
|
+
queryFn: async () => {
|
|
42
|
+
return authenticatedApiCall<Subscription>(
|
|
43
|
+
oxyServices,
|
|
44
|
+
activeSessionId,
|
|
45
|
+
() => oxyServices.getCurrentUserSubscription(),
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
enabled: (options?.enabled !== false) && isAuthenticated,
|
|
49
|
+
// Subscription state changes rarely; tolerate a longer fresh window.
|
|
50
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
51
|
+
gcTime: 30 * 60 * 1000, // 30 minutes
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the current user's payment / billing history.
|
|
57
|
+
*
|
|
58
|
+
* Wraps `oxyServices.getUserPayments()` (`GET /payments/user`), which
|
|
59
|
+
* returns the user's `deposit` and `purchase` transactions newest-first.
|
|
60
|
+
*/
|
|
61
|
+
export const useUserPayments = (options?: { enabled?: boolean }) => {
|
|
62
|
+
const { oxyServices, isAuthenticated, activeSessionId } = useOxy();
|
|
63
|
+
|
|
64
|
+
return useQuery({
|
|
65
|
+
queryKey: queryKeys.payments.history(),
|
|
66
|
+
queryFn: async () => {
|
|
67
|
+
return authenticatedApiCall<Payment[]>(
|
|
68
|
+
oxyServices,
|
|
69
|
+
activeSessionId,
|
|
70
|
+
() => oxyServices.getUserPayments(),
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
enabled: (options?.enabled !== false) && isAuthenticated,
|
|
74
|
+
// Billing history is append-mostly; a short fresh window is fine.
|
|
75
|
+
staleTime: 2 * 60 * 1000, // 2 minutes
|
|
76
|
+
gcTime: 30 * 60 * 1000, // 30 minutes
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the current user's FairCoin wallet balance.
|
|
82
|
+
*
|
|
83
|
+
* Wraps `oxyServices.getCurrentUserWallet()` (`GET /wallet/:userId`).
|
|
84
|
+
* Balance changes frequently, so the fresh window is intentionally short.
|
|
85
|
+
*/
|
|
86
|
+
export const useUserWallet = (options?: { enabled?: boolean }) => {
|
|
87
|
+
const { oxyServices, isAuthenticated, activeSessionId } = useOxy();
|
|
88
|
+
|
|
89
|
+
return useQuery({
|
|
90
|
+
queryKey: queryKeys.payments.wallet(),
|
|
91
|
+
queryFn: async () => {
|
|
92
|
+
return authenticatedApiCall<Wallet>(
|
|
93
|
+
oxyServices,
|
|
94
|
+
activeSessionId,
|
|
95
|
+
() => oxyServices.getCurrentUserWallet(),
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
enabled: (options?.enabled !== false) && isAuthenticated,
|
|
99
|
+
staleTime: 60 * 1000, // 1 minute (balance moves often)
|
|
100
|
+
gcTime: 10 * 60 * 1000, // 10 minutes
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the current user's wallet transaction history (paginated).
|
|
106
|
+
*
|
|
107
|
+
* Wraps `oxyServices.getCurrentUserWalletTransactions(options)`
|
|
108
|
+
* (`GET /wallet/transactions/:userId`). The API responds with a
|
|
109
|
+
* `{ data, pagination }` envelope, preserved here as
|
|
110
|
+
* `WalletTransactionsResponse`.
|
|
111
|
+
*
|
|
112
|
+
* @param params - Optional `limit` / `offset` pagination controls. These are
|
|
113
|
+
* part of the query key, so distinct pages cache independently.
|
|
114
|
+
*/
|
|
115
|
+
export const useUserWalletTransactions = (
|
|
116
|
+
params?: { limit?: number; offset?: number },
|
|
117
|
+
options?: { enabled?: boolean },
|
|
118
|
+
) => {
|
|
119
|
+
const { oxyServices, isAuthenticated, activeSessionId } = useOxy();
|
|
120
|
+
const limit = params?.limit;
|
|
121
|
+
const offset = params?.offset;
|
|
122
|
+
|
|
123
|
+
return useQuery({
|
|
124
|
+
queryKey: queryKeys.payments.walletTransactions(limit, offset),
|
|
125
|
+
queryFn: async () => {
|
|
126
|
+
return authenticatedApiCall<WalletTransactionsResponse>(
|
|
127
|
+
oxyServices,
|
|
128
|
+
activeSessionId,
|
|
129
|
+
() => oxyServices.getCurrentUserWalletTransactions({ limit, offset }),
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
enabled: (options?.enabled !== false) && isAuthenticated,
|
|
133
|
+
staleTime: 60 * 1000, // 1 minute (ledger updates frequently)
|
|
134
|
+
gcTime: 10 * 60 * 1000, // 10 minutes
|
|
135
|
+
});
|
|
136
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query';
|
|
2
2
|
import { authenticatedApiCall } from '@oxyhq/core';
|
|
3
|
-
import type { ClientSession } from '@oxyhq/core';
|
|
3
|
+
import type { AccountStorageUsageResponse, ClientSession } from '@oxyhq/core';
|
|
4
4
|
import { queryKeys } from './queryKeys';
|
|
5
5
|
import { useOxy } from '../../context/OxyContext';
|
|
6
6
|
import { fetchSessionsWithFallback, mapSessionsToClient } from '../../utils/sessionHelpers';
|
|
@@ -124,3 +124,28 @@ export const useSecurityInfo = (options?: { enabled?: boolean }) => {
|
|
|
124
124
|
});
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Get account storage usage (server-aggregated usage across assets, mail,
|
|
129
|
+
* recordings, etc.). Wraps `oxyServices.getAccountStorageUsage()` in a
|
|
130
|
+
* TanStack query so consumers get caching, background refetch, and a
|
|
131
|
+
* consistent `isLoading` / `refetch` surface instead of hand-rolled
|
|
132
|
+
* `useEffect` fetches.
|
|
133
|
+
*/
|
|
134
|
+
export const useAccountStorageUsage = (options?: { enabled?: boolean }) => {
|
|
135
|
+
const { oxyServices, isAuthenticated, activeSessionId } = useOxy();
|
|
136
|
+
|
|
137
|
+
return useQuery<AccountStorageUsageResponse>({
|
|
138
|
+
queryKey: queryKeys.storage.usage(),
|
|
139
|
+
queryFn: async () => {
|
|
140
|
+
return authenticatedApiCall(
|
|
141
|
+
oxyServices,
|
|
142
|
+
activeSessionId,
|
|
143
|
+
() => oxyServices.getAccountStorageUsage()
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
enabled: (options?.enabled !== false) && isAuthenticated,
|
|
147
|
+
staleTime: 5 * 60 * 1000,
|
|
148
|
+
gcTime: 30 * 60 * 1000,
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
@@ -38,36 +38,6 @@ interface UseWebSSOResult {
|
|
|
38
38
|
isFedCMSupported: boolean;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/**
|
|
42
|
-
* Module-level guard tracking which (origin + API) signatures have already
|
|
43
|
-
* had a silent SSO attempt this page load.
|
|
44
|
-
*
|
|
45
|
-
* A per-component `useRef` guard resets whenever the provider remounts (route
|
|
46
|
-
* churn, StrictMode double-invoke, error-boundary recovery), which previously
|
|
47
|
-
* allowed silent SSO to re-fire and — combined with a routing redirect loop —
|
|
48
|
-
* produced an accelerating `navigator.credentials.get` retry storm. Keying the
|
|
49
|
-
* guard on a stable signature instead of the component instance makes silent
|
|
50
|
-
* SSO fire EXACTLY ONCE per page load regardless of how many times the
|
|
51
|
-
* provider mounts. The set is intentionally never cleared: a fresh page load
|
|
52
|
-
* (the only thing that can change the answer) starts a fresh module scope.
|
|
53
|
-
*/
|
|
54
|
-
const silentSSOAttempted = new Set<string>();
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Build a stable signature for the silent-SSO run-once guard. Two providers
|
|
58
|
-
* pointed at the same API from the same origin share one attempt.
|
|
59
|
-
*/
|
|
60
|
-
function ssoSignature(oxyServices: OxyServices): string {
|
|
61
|
-
const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
|
|
62
|
-
let baseURL = '';
|
|
63
|
-
try {
|
|
64
|
-
baseURL = oxyServices.getBaseURL?.() ?? '';
|
|
65
|
-
} catch {
|
|
66
|
-
baseURL = '';
|
|
67
|
-
}
|
|
68
|
-
return `${origin}|${baseURL}`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
41
|
/**
|
|
72
42
|
* Check if we're running in a web browser environment (not React Native)
|
|
73
43
|
*/
|
|
@@ -195,12 +165,12 @@ export function useWebSSO({
|
|
|
195
165
|
|
|
196
166
|
// Auto-check SSO on mount (web only, FedCM only, not on auth domain).
|
|
197
167
|
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
168
|
+
// `hasCheckedRef` is a cheap per-instance fast-path so effect re-runs (from
|
|
169
|
+
// changing deps) within one mount never re-fire. The page-load run-once
|
|
170
|
+
// guarantee — silent SSO invoking `navigator.credentials.get` AT MOST ONCE
|
|
171
|
+
// per page load across remounts / StrictMode / multiple consumers — lives in
|
|
172
|
+
// `@oxyhq/core`'s `silentSignInWithFedCM`, which memoizes the first silent
|
|
173
|
+
// attempt's result for this origin + API. The hook therefore calls it freely.
|
|
204
174
|
useEffect(() => {
|
|
205
175
|
if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider(authWebUrl)) {
|
|
206
176
|
if (isIdentityProvider(authWebUrl)) {
|
|
@@ -209,23 +179,14 @@ export function useWebSSO({
|
|
|
209
179
|
return;
|
|
210
180
|
}
|
|
211
181
|
|
|
212
|
-
const signature = ssoSignature(oxyServices);
|
|
213
|
-
if (silentSSOAttempted.has(signature)) {
|
|
214
|
-
// Already attempted this page load (e.g. before a remount) — do not
|
|
215
|
-
// re-fire. Mark the local fast-path too so subsequent re-renders skip.
|
|
216
|
-
hasCheckedRef.current = true;
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
182
|
hasCheckedRef.current = true;
|
|
221
|
-
silentSSOAttempted.add(signature);
|
|
222
183
|
|
|
223
184
|
if (fedCMSupported) {
|
|
224
185
|
checkSSO();
|
|
225
186
|
} else {
|
|
226
187
|
onSSOUnavailable?.();
|
|
227
188
|
}
|
|
228
|
-
}, [enabled, checkSSO, fedCMSupported, onSSOUnavailable,
|
|
189
|
+
}, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, authWebUrl]);
|
|
229
190
|
|
|
230
191
|
return {
|
|
231
192
|
checkSSO,
|