@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.
- package/README.md +56 -0
- package/dist/cjs/WebOxyProvider.js +287 -0
- package/dist/cjs/hooks/mutations/index.js +23 -0
- package/dist/cjs/hooks/mutations/mutationFactory.js +126 -0
- package/dist/cjs/hooks/mutations/useAccountMutations.js +275 -0
- package/dist/cjs/hooks/mutations/useServicesMutations.js +149 -0
- package/dist/cjs/hooks/queries/index.js +35 -0
- package/dist/cjs/hooks/queries/queryKeys.js +82 -0
- package/dist/cjs/hooks/queries/useAccountQueries.js +141 -0
- package/dist/cjs/hooks/queries/useSecurityQueries.js +45 -0
- package/dist/cjs/hooks/queries/useServicesQueries.js +113 -0
- package/dist/cjs/hooks/queryClient.js +110 -0
- package/dist/cjs/hooks/useAssets.js +225 -0
- package/dist/cjs/hooks/useFileDownloadUrl.js +91 -0
- package/dist/cjs/hooks/useFileFiltering.js +81 -0
- package/dist/cjs/hooks/useFollow.js +159 -0
- package/dist/cjs/hooks/useFollow.types.js +4 -0
- package/dist/cjs/hooks/useQueryClient.js +16 -0
- package/dist/cjs/hooks/useSessionSocket.js +215 -0
- package/dist/cjs/hooks/useWebSSO.js +146 -0
- package/dist/cjs/index.js +115 -0
- package/dist/cjs/stores/accountStore.js +226 -0
- package/dist/cjs/stores/assetStore.js +192 -0
- package/dist/cjs/stores/authStore.js +47 -0
- package/dist/cjs/stores/followStore.js +154 -0
- package/dist/cjs/utils/authHelpers.js +154 -0
- package/dist/cjs/utils/avatarUtils.js +77 -0
- package/dist/cjs/utils/errorHandlers.js +128 -0
- package/dist/cjs/utils/sessionHelpers.js +90 -0
- package/dist/cjs/utils/storageHelpers.js +147 -0
- package/dist/esm/WebOxyProvider.js +282 -0
- package/dist/esm/hooks/mutations/index.js +10 -0
- package/dist/esm/hooks/mutations/mutationFactory.js +122 -0
- package/dist/esm/hooks/mutations/useAccountMutations.js +267 -0
- package/dist/esm/hooks/mutations/useServicesMutations.js +141 -0
- package/dist/esm/hooks/queries/index.js +14 -0
- package/dist/esm/hooks/queries/queryKeys.js +76 -0
- package/dist/esm/hooks/queries/useAccountQueries.js +131 -0
- package/dist/esm/hooks/queries/useSecurityQueries.js +40 -0
- package/dist/esm/hooks/queries/useServicesQueries.js +105 -0
- package/dist/esm/hooks/queryClient.js +104 -0
- package/dist/esm/hooks/useAssets.js +220 -0
- package/dist/esm/hooks/useFileDownloadUrl.js +86 -0
- package/dist/esm/hooks/useFileFiltering.js +78 -0
- package/dist/esm/hooks/useFollow.js +154 -0
- package/dist/esm/hooks/useFollow.types.js +3 -0
- package/dist/esm/hooks/useQueryClient.js +12 -0
- package/dist/esm/hooks/useSessionSocket.js +209 -0
- package/dist/esm/hooks/useWebSSO.js +143 -0
- package/dist/esm/index.js +48 -0
- package/dist/esm/stores/accountStore.js +219 -0
- package/dist/esm/stores/assetStore.js +180 -0
- package/dist/esm/stores/authStore.js +44 -0
- package/dist/esm/stores/followStore.js +151 -0
- package/dist/esm/utils/authHelpers.js +145 -0
- package/dist/esm/utils/avatarUtils.js +72 -0
- package/dist/esm/utils/errorHandlers.js +121 -0
- package/dist/esm/utils/sessionHelpers.js +84 -0
- package/dist/esm/utils/storageHelpers.js +108 -0
- package/dist/types/WebOxyProvider.d.ts +97 -0
- package/dist/types/hooks/mutations/index.d.ts +8 -0
- package/dist/types/hooks/mutations/mutationFactory.d.ts +75 -0
- package/dist/types/hooks/mutations/useAccountMutations.d.ts +68 -0
- package/dist/types/hooks/mutations/useServicesMutations.d.ts +22 -0
- package/dist/types/hooks/queries/index.d.ts +10 -0
- package/dist/types/hooks/queries/queryKeys.d.ts +64 -0
- package/dist/types/hooks/queries/useAccountQueries.d.ts +42 -0
- package/dist/types/hooks/queries/useSecurityQueries.d.ts +14 -0
- package/dist/types/hooks/queries/useServicesQueries.d.ts +31 -0
- package/dist/types/hooks/queryClient.d.ts +18 -0
- package/dist/types/hooks/useAssets.d.ts +34 -0
- package/dist/types/hooks/useFileDownloadUrl.d.ts +18 -0
- package/dist/types/hooks/useFileFiltering.d.ts +28 -0
- package/dist/types/hooks/useFollow.d.ts +61 -0
- package/dist/types/hooks/useFollow.types.d.ts +32 -0
- package/dist/types/hooks/useQueryClient.d.ts +6 -0
- package/dist/types/hooks/useSessionSocket.d.ts +13 -0
- package/dist/types/hooks/useWebSSO.d.ts +57 -0
- package/dist/types/index.d.ts +46 -0
- package/dist/types/stores/accountStore.d.ts +33 -0
- package/dist/types/stores/assetStore.d.ts +53 -0
- package/dist/types/stores/authStore.d.ts +16 -0
- package/dist/types/stores/followStore.d.ts +24 -0
- package/dist/types/utils/authHelpers.d.ts +98 -0
- package/dist/types/utils/avatarUtils.d.ts +33 -0
- package/dist/types/utils/errorHandlers.d.ts +34 -0
- package/dist/types/utils/sessionHelpers.d.ts +63 -0
- package/dist/types/utils/storageHelpers.d.ts +27 -0
- package/package.json +71 -0
- package/src/WebOxyProvider.tsx +372 -0
- package/src/global.d.ts +1 -0
- package/src/hooks/mutations/index.ts +25 -0
- package/src/hooks/mutations/mutationFactory.ts +215 -0
- package/src/hooks/mutations/useAccountMutations.ts +344 -0
- package/src/hooks/mutations/useServicesMutations.ts +164 -0
- package/src/hooks/queries/index.ts +36 -0
- package/src/hooks/queries/queryKeys.ts +88 -0
- package/src/hooks/queries/useAccountQueries.ts +152 -0
- package/src/hooks/queries/useSecurityQueries.ts +64 -0
- package/src/hooks/queries/useServicesQueries.ts +126 -0
- package/src/hooks/queryClient.ts +112 -0
- package/src/hooks/useAssets.ts +291 -0
- package/src/hooks/useFileDownloadUrl.ts +118 -0
- package/src/hooks/useFileFiltering.ts +115 -0
- package/src/hooks/useFollow.ts +175 -0
- package/src/hooks/useFollow.types.ts +33 -0
- package/src/hooks/useQueryClient.ts +17 -0
- package/src/hooks/useSessionSocket.ts +233 -0
- package/src/hooks/useWebSSO.ts +187 -0
- package/src/index.ts +144 -0
- package/src/stores/accountStore.ts +296 -0
- package/src/stores/assetStore.ts +281 -0
- package/src/stores/authStore.ts +63 -0
- package/src/stores/followStore.ts +181 -0
- package/src/utils/authHelpers.ts +183 -0
- package/src/utils/avatarUtils.ts +103 -0
- package/src/utils/errorHandlers.ts +194 -0
- package/src/utils/sessionHelpers.ts +151 -0
- package/src/utils/storageHelpers.ts +130 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { ClientSession } from '@oxyhq/core';
|
|
2
|
+
|
|
3
|
+
interface DeviceSession {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
deviceId?: string;
|
|
6
|
+
deviceName?: string;
|
|
7
|
+
expiresAt?: string;
|
|
8
|
+
lastActive?: string;
|
|
9
|
+
user?: { id?: string; _id?: { toString(): string } };
|
|
10
|
+
userId?: string;
|
|
11
|
+
isCurrent?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Service type for session helpers.
|
|
16
|
+
* Uses 'any' to work around TypeScript mixin composition type inference issues.
|
|
17
|
+
* The OxyServices class has these methods but TypeScript can't see them due to the mixin pattern.
|
|
18
|
+
*/
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
type OxyServicesAny = any;
|
|
21
|
+
|
|
22
|
+
export interface FetchSessionsWithFallbackOptions {
|
|
23
|
+
fallbackDeviceId?: string;
|
|
24
|
+
fallbackUserId?: string;
|
|
25
|
+
logger?: (message: string, error?: unknown) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ValidateSessionBatchOptions {
|
|
29
|
+
useHeaderValidation?: boolean;
|
|
30
|
+
maxConcurrency?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface SessionValidationResult {
|
|
34
|
+
sessionId: string;
|
|
35
|
+
valid: boolean;
|
|
36
|
+
user?: unknown;
|
|
37
|
+
raw?: unknown;
|
|
38
|
+
error?: unknown;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Normalize backend session payloads into `ClientSession` objects.
|
|
43
|
+
*
|
|
44
|
+
* @param sessions - Raw session array returned from the API
|
|
45
|
+
* @param fallbackDeviceId - Device identifier to use when missing from payload
|
|
46
|
+
* @param fallbackUserId - User identifier to use when missing from payload
|
|
47
|
+
*/
|
|
48
|
+
export const mapSessionsToClient = (
|
|
49
|
+
sessions: DeviceSession[],
|
|
50
|
+
fallbackDeviceId?: string,
|
|
51
|
+
fallbackUserId?: string,
|
|
52
|
+
): ClientSession[] => {
|
|
53
|
+
const now = new Date();
|
|
54
|
+
|
|
55
|
+
return sessions.map((session) => ({
|
|
56
|
+
sessionId: session.sessionId,
|
|
57
|
+
deviceId: session.deviceId || fallbackDeviceId || '',
|
|
58
|
+
expiresAt: session.expiresAt || new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
59
|
+
lastActive: session.lastActive || now.toISOString(),
|
|
60
|
+
userId:
|
|
61
|
+
session.user?.id ||
|
|
62
|
+
session.userId ||
|
|
63
|
+
(session.user?._id ? session.user._id.toString() : undefined) ||
|
|
64
|
+
fallbackUserId ||
|
|
65
|
+
'',
|
|
66
|
+
isCurrent: Boolean(session.isCurrent),
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Fetch device sessions with fallback to the legacy session endpoint when needed.
|
|
72
|
+
*
|
|
73
|
+
* @param oxyServices - Oxy service instance
|
|
74
|
+
* @param sessionId - Session identifier to fetch
|
|
75
|
+
* @param options - Optional fallback options
|
|
76
|
+
*/
|
|
77
|
+
export const fetchSessionsWithFallback = async (
|
|
78
|
+
oxyServices: OxyServicesAny,
|
|
79
|
+
sessionId: string,
|
|
80
|
+
{
|
|
81
|
+
fallbackDeviceId,
|
|
82
|
+
fallbackUserId,
|
|
83
|
+
logger,
|
|
84
|
+
}: FetchSessionsWithFallbackOptions = {},
|
|
85
|
+
): Promise<ClientSession[]> => {
|
|
86
|
+
try {
|
|
87
|
+
const deviceSessions = await oxyServices.getDeviceSessions(sessionId);
|
|
88
|
+
return mapSessionsToClient(deviceSessions, fallbackDeviceId, fallbackUserId);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (__DEV__ && logger) {
|
|
91
|
+
logger('Failed to get device sessions, falling back to user sessions', error);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const userSessions = await oxyServices.getSessionsBySessionId(sessionId);
|
|
95
|
+
return mapSessionsToClient(userSessions, fallbackDeviceId, fallbackUserId);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Validate multiple sessions concurrently with configurable concurrency.
|
|
101
|
+
*
|
|
102
|
+
* @param oxyServices - Oxy service instance
|
|
103
|
+
* @param sessionIds - Session identifiers to validate
|
|
104
|
+
* @param options - Validation options
|
|
105
|
+
*/
|
|
106
|
+
export const validateSessionBatch = async (
|
|
107
|
+
oxyServices: OxyServicesAny,
|
|
108
|
+
sessionIds: string[],
|
|
109
|
+
{ useHeaderValidation = true, maxConcurrency = 5 }: ValidateSessionBatchOptions = {},
|
|
110
|
+
): Promise<SessionValidationResult[]> => {
|
|
111
|
+
if (!sessionIds.length) {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const uniqueSessionIds = Array.from(new Set(sessionIds));
|
|
116
|
+
const safeConcurrency = Math.max(1, Math.min(maxConcurrency, uniqueSessionIds.length));
|
|
117
|
+
const results: SessionValidationResult[] = [];
|
|
118
|
+
let index = 0;
|
|
119
|
+
|
|
120
|
+
const worker = async () => {
|
|
121
|
+
while (index < uniqueSessionIds.length) {
|
|
122
|
+
const currentIndex = index;
|
|
123
|
+
index += 1;
|
|
124
|
+
const sessionId = uniqueSessionIds[currentIndex];
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const validation = await oxyServices.validateSession(sessionId, { useHeaderValidation });
|
|
128
|
+
const valid = Boolean(validation?.valid);
|
|
129
|
+
|
|
130
|
+
results.push({
|
|
131
|
+
sessionId,
|
|
132
|
+
valid,
|
|
133
|
+
user: validation?.user,
|
|
134
|
+
raw: validation,
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
results.push({
|
|
138
|
+
sessionId,
|
|
139
|
+
valid: false,
|
|
140
|
+
error,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
await Promise.all(Array.from({ length: safeConcurrency }, worker));
|
|
147
|
+
|
|
148
|
+
return results;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
export interface StorageInterface {
|
|
2
|
+
getItem: (key: string) => Promise<string | null>;
|
|
3
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
4
|
+
removeItem: (key: string) => Promise<void>;
|
|
5
|
+
clear: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface SessionStorageKeys {
|
|
9
|
+
activeSessionId: string;
|
|
10
|
+
sessionIds: string;
|
|
11
|
+
language: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create an in-memory storage implementation used as a safe fallback.
|
|
16
|
+
*/
|
|
17
|
+
const MEMORY_STORAGE = (): StorageInterface => {
|
|
18
|
+
const store = new Map<string, string>();
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
async getItem(key: string) {
|
|
22
|
+
return store.has(key) ? store.get(key)! : null;
|
|
23
|
+
},
|
|
24
|
+
async setItem(key: string, value: string) {
|
|
25
|
+
store.set(key, value);
|
|
26
|
+
},
|
|
27
|
+
async removeItem(key: string) {
|
|
28
|
+
store.delete(key);
|
|
29
|
+
},
|
|
30
|
+
async clear() {
|
|
31
|
+
store.clear();
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a web storage implementation backed by `localStorage`.
|
|
38
|
+
* Falls back to in-memory storage when unavailable.
|
|
39
|
+
*/
|
|
40
|
+
const createWebStorage = (): StorageInterface => {
|
|
41
|
+
if (typeof window === 'undefined' || typeof window.localStorage === 'undefined') {
|
|
42
|
+
return MEMORY_STORAGE();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
async getItem(key: string) {
|
|
47
|
+
try {
|
|
48
|
+
return window.localStorage.getItem(key);
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
async setItem(key: string, value: string) {
|
|
54
|
+
try {
|
|
55
|
+
window.localStorage.setItem(key, value);
|
|
56
|
+
} catch {
|
|
57
|
+
// Ignore quota or access issues for now.
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async removeItem(key: string) {
|
|
61
|
+
try {
|
|
62
|
+
window.localStorage.removeItem(key);
|
|
63
|
+
} catch {
|
|
64
|
+
// Ignore failures.
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
async clear() {
|
|
68
|
+
try {
|
|
69
|
+
window.localStorage.clear();
|
|
70
|
+
} catch {
|
|
71
|
+
// Ignore failures.
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
let asyncStorageInstance: StorageInterface | null = null;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Lazily import React Native AsyncStorage implementation.
|
|
81
|
+
*/
|
|
82
|
+
const createNativeStorage = async (): Promise<StorageInterface> => {
|
|
83
|
+
if (asyncStorageInstance) {
|
|
84
|
+
return asyncStorageInstance;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const asyncStorageModule = await import('@react-native-async-storage/async-storage');
|
|
89
|
+
asyncStorageInstance = asyncStorageModule.default as unknown as StorageInterface;
|
|
90
|
+
return asyncStorageInstance;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (__DEV__) {
|
|
93
|
+
console.error('Failed to import AsyncStorage:', error);
|
|
94
|
+
}
|
|
95
|
+
throw new Error('AsyncStorage is required in React Native environment');
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Detect whether the current runtime is React Native.
|
|
101
|
+
*/
|
|
102
|
+
export const isReactNative = (): boolean =>
|
|
103
|
+
typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Create a platform-appropriate storage implementation.
|
|
107
|
+
* Defaults to in-memory storage when no platform storage is available.
|
|
108
|
+
*/
|
|
109
|
+
export const createPlatformStorage = async (): Promise<StorageInterface> => {
|
|
110
|
+
if (isReactNative()) {
|
|
111
|
+
return createNativeStorage();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return createWebStorage();
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const STORAGE_KEY_PREFIX = 'oxy_session';
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Produce strongly typed storage key names for the supplied prefix.
|
|
121
|
+
*
|
|
122
|
+
* @param prefix - Storage key prefix
|
|
123
|
+
*/
|
|
124
|
+
export const getStorageKeys = (prefix: string = STORAGE_KEY_PREFIX): SessionStorageKeys => ({
|
|
125
|
+
activeSessionId: `${prefix}_active_session_id`,
|
|
126
|
+
sessionIds: `${prefix}_session_ids`,
|
|
127
|
+
language: `${prefix}_language`,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
|