@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,146 @@
1
+ "use strict";
2
+ /**
3
+ * Web SSO Hook
4
+ *
5
+ * Handles cross-domain SSO for web apps using FedCM (Federated Credential Management).
6
+ *
7
+ * FedCM is the modern, privacy-preserving standard for cross-domain identity federation.
8
+ * It works across completely different TLDs (alia.onl, mention.earth, homiio.com, etc.)
9
+ * without relying on third-party cookies.
10
+ *
11
+ * For browsers without FedCM support, users will need to click a sign-in button
12
+ * which triggers a popup-based authentication flow.
13
+ *
14
+ * This is called automatically by OxyContext on web platforms.
15
+ *
16
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.useWebSSO = useWebSSO;
20
+ exports.isWebBrowser = isWebBrowser;
21
+ const react_1 = require("react");
22
+ /**
23
+ * Check if we're running in a web browser environment (not React Native)
24
+ */
25
+ function isWebBrowser() {
26
+ return typeof window !== 'undefined' &&
27
+ typeof document !== 'undefined' &&
28
+ typeof document.documentElement !== 'undefined';
29
+ }
30
+ /**
31
+ * Check if we're on the identity provider domain (where FedCM would authenticate against itself)
32
+ * Only auth.oxy.so is the IdP - accounts.oxy.so is a client app like any other
33
+ */
34
+ function isIdentityProvider() {
35
+ if (!isWebBrowser())
36
+ return false;
37
+ const hostname = window.location.hostname;
38
+ return hostname === 'auth.oxy.so';
39
+ }
40
+ /**
41
+ * Hook for automatic cross-domain web SSO
42
+ *
43
+ * Uses FedCM (Federated Credential Management) - the modern browser-native
44
+ * identity federation API. This is the same technology that powers
45
+ * Google's cross-domain SSO (YouTube, Gmail, Maps, etc.).
46
+ *
47
+ * Key benefits:
48
+ * - Works across different TLDs (alia.onl ↔ mention.earth ↔ homiio.com)
49
+ * - No third-party cookies required
50
+ * - Privacy-preserving (browser mediates identity, IdP can't track)
51
+ * - Automatic silent sign-in after initial authentication
52
+ *
53
+ * For browsers without FedCM (Firefox, older browsers), automatic SSO
54
+ * is not possible. Users will see a sign-in button instead.
55
+ */
56
+ function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, enabled = true, }) {
57
+ const isCheckingRef = (0, react_1.useRef)(false);
58
+ const hasCheckedRef = (0, react_1.useRef)(false);
59
+ // Check FedCM support once
60
+ const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported?.();
61
+ const checkSSO = (0, react_1.useCallback)(async () => {
62
+ if (!isWebBrowser() || isCheckingRef.current) {
63
+ return null;
64
+ }
65
+ // Don't use FedCM on the auth domain itself - it would authenticate against itself
66
+ if (isIdentityProvider()) {
67
+ onSSOUnavailable?.();
68
+ return null;
69
+ }
70
+ // FedCM is the only reliable cross-domain SSO mechanism
71
+ if (!fedCMSupported) {
72
+ onSSOUnavailable?.();
73
+ return null;
74
+ }
75
+ isCheckingRef.current = true;
76
+ try {
77
+ const session = await oxyServices.silentSignInWithFedCM?.();
78
+ if (session) {
79
+ await onSessionFound(session);
80
+ return session;
81
+ }
82
+ onSSOUnavailable?.();
83
+ return null;
84
+ }
85
+ catch (error) {
86
+ onSSOUnavailable?.();
87
+ onError?.(error instanceof Error ? error : new Error(String(error)));
88
+ return null;
89
+ }
90
+ finally {
91
+ isCheckingRef.current = false;
92
+ }
93
+ }, [oxyServices, onSessionFound, onSSOUnavailable, onError, fedCMSupported]);
94
+ /**
95
+ * Trigger interactive FedCM sign-in
96
+ * This shows the browser's native "Sign in with Oxy" prompt.
97
+ * Use this when silent mediation fails (user hasn't previously consented).
98
+ */
99
+ const signInWithFedCM = (0, react_1.useCallback)(async () => {
100
+ if (!isWebBrowser() || isCheckingRef.current) {
101
+ return null;
102
+ }
103
+ if (!fedCMSupported) {
104
+ onError?.(new Error('FedCM is not supported in this browser'));
105
+ return null;
106
+ }
107
+ isCheckingRef.current = true;
108
+ try {
109
+ const session = await oxyServices.signInWithFedCM?.();
110
+ if (session) {
111
+ await onSessionFound(session);
112
+ return session;
113
+ }
114
+ return null;
115
+ }
116
+ catch (error) {
117
+ onError?.(error instanceof Error ? error : new Error(String(error)));
118
+ return null;
119
+ }
120
+ finally {
121
+ isCheckingRef.current = false;
122
+ }
123
+ }, [oxyServices, onSessionFound, onError, fedCMSupported]);
124
+ // Auto-check SSO on mount (web only, FedCM only, not on auth domain)
125
+ (0, react_1.useEffect)(() => {
126
+ if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider()) {
127
+ if (isIdentityProvider()) {
128
+ onSSOUnavailable?.();
129
+ }
130
+ return;
131
+ }
132
+ hasCheckedRef.current = true;
133
+ if (fedCMSupported) {
134
+ checkSSO();
135
+ }
136
+ else {
137
+ onSSOUnavailable?.();
138
+ }
139
+ }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable]);
140
+ return {
141
+ checkSSO,
142
+ signInWithFedCM,
143
+ isChecking: isCheckingRef.current,
144
+ isFedCMSupported: fedCMSupported,
145
+ };
146
+ }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ /**
3
+ * @oxyhq/auth — OxyHQ Web Authentication SDK
4
+ *
5
+ * Headless authentication for React web apps (Next.js, Vite, CRA).
6
+ * Zero React Native / Expo dependencies.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * import { WebOxyProvider, useAuth } from '@oxyhq/auth';
11
+ *
12
+ * function App() {
13
+ * return (
14
+ * <WebOxyProvider baseURL="https://api.oxy.so">
15
+ * <YourApp />
16
+ * </WebOxyProvider>
17
+ * );
18
+ * }
19
+ *
20
+ * function YourApp() {
21
+ * const { user, isAuthenticated, signIn, signOut } = useAuth();
22
+ * // ...
23
+ * }
24
+ * ```
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.withAuthErrorHandling = exports.ensureValidToken = exports.useFileFiltering = exports.useFollowerCounts = exports.useFollow = exports.setOxyFileUrlInstance = exports.useFileDownloadUrl = exports.setOxyAssetInstance = exports.useAssets = exports.useSessionSocket = exports.createGenericMutation = exports.createProfileMutation = exports.useRemoveDevice = exports.useUpdateDeviceName = exports.useLogoutAll = exports.useLogoutSession = exports.useSwitchSession = exports.useUploadFile = exports.useUpdatePrivacySettings = exports.useUpdateAccountSettings = exports.useUploadAvatar = exports.useUpdateProfile = 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 = exports.useIsAssetLinked = exports.useAssetUsageCount = exports.useAssetsByEntity = exports.useAssetsByApp = exports.useAssetErrors = exports.useAssetLoading = exports.useUploadProgress = exports.useAsset = exports.useAssetsStore = exports.useAssetStore = exports.useAuthStore = exports.useAuth = exports.useWebOxy = exports.WebOxyProvider = void 0;
28
+ exports.createCrossDomainAuth = exports.createAuthManager = exports.AuthManager = exports.CrossDomainAuth = exports.OxyServices = exports.extractErrorMessage = exports.isTimeoutOrNetworkError = exports.isInvalidSessionError = exports.handleAuthError = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.isAuthenticationError = exports.authenticatedApiCall = void 0;
29
+ // --- Provider & Hooks ---
30
+ var WebOxyProvider_1 = require("./WebOxyProvider");
31
+ Object.defineProperty(exports, "WebOxyProvider", { enumerable: true, get: function () { return WebOxyProvider_1.WebOxyProvider; } });
32
+ Object.defineProperty(exports, "useWebOxy", { enumerable: true, get: function () { return WebOxyProvider_1.useWebOxy; } });
33
+ Object.defineProperty(exports, "useAuth", { enumerable: true, get: function () { return WebOxyProvider_1.useAuth; } });
34
+ // --- Stores ---
35
+ var authStore_1 = require("./stores/authStore");
36
+ Object.defineProperty(exports, "useAuthStore", { enumerable: true, get: function () { return authStore_1.useAuthStore; } });
37
+ var assetStore_1 = require("./stores/assetStore");
38
+ Object.defineProperty(exports, "useAssetStore", { enumerable: true, get: function () { return assetStore_1.useAssetStore; } });
39
+ Object.defineProperty(exports, "useAssetsStore", { enumerable: true, get: function () { return assetStore_1.useAssets; } });
40
+ Object.defineProperty(exports, "useAsset", { enumerable: true, get: function () { return assetStore_1.useAsset; } });
41
+ Object.defineProperty(exports, "useUploadProgress", { enumerable: true, get: function () { return assetStore_1.useUploadProgress; } });
42
+ Object.defineProperty(exports, "useAssetLoading", { enumerable: true, get: function () { return assetStore_1.useAssetLoading; } });
43
+ Object.defineProperty(exports, "useAssetErrors", { enumerable: true, get: function () { return assetStore_1.useAssetErrors; } });
44
+ Object.defineProperty(exports, "useAssetsByApp", { enumerable: true, get: function () { return assetStore_1.useAssetsByApp; } });
45
+ Object.defineProperty(exports, "useAssetsByEntity", { enumerable: true, get: function () { return assetStore_1.useAssetsByEntity; } });
46
+ Object.defineProperty(exports, "useAssetUsageCount", { enumerable: true, get: function () { return assetStore_1.useAssetUsageCount; } });
47
+ Object.defineProperty(exports, "useIsAssetLinked", { enumerable: true, get: function () { return assetStore_1.useIsAssetLinked; } });
48
+ // --- Query Hooks ---
49
+ var queries_1 = require("./hooks/queries");
50
+ Object.defineProperty(exports, "useUserProfile", { enumerable: true, get: function () { return queries_1.useUserProfile; } });
51
+ Object.defineProperty(exports, "useUserProfiles", { enumerable: true, get: function () { return queries_1.useUserProfiles; } });
52
+ Object.defineProperty(exports, "useCurrentUser", { enumerable: true, get: function () { return queries_1.useCurrentUser; } });
53
+ Object.defineProperty(exports, "useUserById", { enumerable: true, get: function () { return queries_1.useUserById; } });
54
+ Object.defineProperty(exports, "useUserByUsername", { enumerable: true, get: function () { return queries_1.useUserByUsername; } });
55
+ Object.defineProperty(exports, "useUsersBySessions", { enumerable: true, get: function () { return queries_1.useUsersBySessions; } });
56
+ Object.defineProperty(exports, "usePrivacySettings", { enumerable: true, get: function () { return queries_1.usePrivacySettings; } });
57
+ Object.defineProperty(exports, "useSessions", { enumerable: true, get: function () { return queries_1.useSessions; } });
58
+ Object.defineProperty(exports, "useSession", { enumerable: true, get: function () { return queries_1.useSession; } });
59
+ Object.defineProperty(exports, "useDeviceSessions", { enumerable: true, get: function () { return queries_1.useDeviceSessions; } });
60
+ Object.defineProperty(exports, "useUserDevices", { enumerable: true, get: function () { return queries_1.useUserDevices; } });
61
+ Object.defineProperty(exports, "useSecurityInfo", { enumerable: true, get: function () { return queries_1.useSecurityInfo; } });
62
+ Object.defineProperty(exports, "useSecurityActivity", { enumerable: true, get: function () { return queries_1.useSecurityActivity; } });
63
+ Object.defineProperty(exports, "useRecentSecurityActivity", { enumerable: true, get: function () { return queries_1.useRecentSecurityActivity; } });
64
+ // --- Mutation Hooks ---
65
+ var mutations_1 = require("./hooks/mutations");
66
+ Object.defineProperty(exports, "useUpdateProfile", { enumerable: true, get: function () { return mutations_1.useUpdateProfile; } });
67
+ Object.defineProperty(exports, "useUploadAvatar", { enumerable: true, get: function () { return mutations_1.useUploadAvatar; } });
68
+ Object.defineProperty(exports, "useUpdateAccountSettings", { enumerable: true, get: function () { return mutations_1.useUpdateAccountSettings; } });
69
+ Object.defineProperty(exports, "useUpdatePrivacySettings", { enumerable: true, get: function () { return mutations_1.useUpdatePrivacySettings; } });
70
+ Object.defineProperty(exports, "useUploadFile", { enumerable: true, get: function () { return mutations_1.useUploadFile; } });
71
+ Object.defineProperty(exports, "useSwitchSession", { enumerable: true, get: function () { return mutations_1.useSwitchSession; } });
72
+ Object.defineProperty(exports, "useLogoutSession", { enumerable: true, get: function () { return mutations_1.useLogoutSession; } });
73
+ Object.defineProperty(exports, "useLogoutAll", { enumerable: true, get: function () { return mutations_1.useLogoutAll; } });
74
+ Object.defineProperty(exports, "useUpdateDeviceName", { enumerable: true, get: function () { return mutations_1.useUpdateDeviceName; } });
75
+ Object.defineProperty(exports, "useRemoveDevice", { enumerable: true, get: function () { return mutations_1.useRemoveDevice; } });
76
+ var mutationFactory_1 = require("./hooks/mutations/mutationFactory");
77
+ Object.defineProperty(exports, "createProfileMutation", { enumerable: true, get: function () { return mutationFactory_1.createProfileMutation; } });
78
+ Object.defineProperty(exports, "createGenericMutation", { enumerable: true, get: function () { return mutationFactory_1.createGenericMutation; } });
79
+ // --- Custom Hooks ---
80
+ var useSessionSocket_1 = require("./hooks/useSessionSocket");
81
+ Object.defineProperty(exports, "useSessionSocket", { enumerable: true, get: function () { return useSessionSocket_1.useSessionSocket; } });
82
+ var useAssets_1 = require("./hooks/useAssets");
83
+ Object.defineProperty(exports, "useAssets", { enumerable: true, get: function () { return useAssets_1.useAssets; } });
84
+ Object.defineProperty(exports, "setOxyAssetInstance", { enumerable: true, get: function () { return useAssets_1.setOxyAssetInstance; } });
85
+ var useFileDownloadUrl_1 = require("./hooks/useFileDownloadUrl");
86
+ Object.defineProperty(exports, "useFileDownloadUrl", { enumerable: true, get: function () { return useFileDownloadUrl_1.useFileDownloadUrl; } });
87
+ Object.defineProperty(exports, "setOxyFileUrlInstance", { enumerable: true, get: function () { return useFileDownloadUrl_1.setOxyFileUrlInstance; } });
88
+ var useFollow_1 = require("./hooks/useFollow");
89
+ Object.defineProperty(exports, "useFollow", { enumerable: true, get: function () { return useFollow_1.useFollow; } });
90
+ Object.defineProperty(exports, "useFollowerCounts", { enumerable: true, get: function () { return useFollow_1.useFollowerCounts; } });
91
+ var useFileFiltering_1 = require("./hooks/useFileFiltering");
92
+ Object.defineProperty(exports, "useFileFiltering", { enumerable: true, get: function () { return useFileFiltering_1.useFileFiltering; } });
93
+ // --- Auth Helpers ---
94
+ var authHelpers_1 = require("./utils/authHelpers");
95
+ Object.defineProperty(exports, "ensureValidToken", { enumerable: true, get: function () { return authHelpers_1.ensureValidToken; } });
96
+ Object.defineProperty(exports, "withAuthErrorHandling", { enumerable: true, get: function () { return authHelpers_1.withAuthErrorHandling; } });
97
+ Object.defineProperty(exports, "authenticatedApiCall", { enumerable: true, get: function () { return authHelpers_1.authenticatedApiCall; } });
98
+ Object.defineProperty(exports, "isAuthenticationError", { enumerable: true, get: function () { return authHelpers_1.isAuthenticationError; } });
99
+ Object.defineProperty(exports, "SessionSyncRequiredError", { enumerable: true, get: function () { return authHelpers_1.SessionSyncRequiredError; } });
100
+ Object.defineProperty(exports, "AuthenticationFailedError", { enumerable: true, get: function () { return authHelpers_1.AuthenticationFailedError; } });
101
+ // --- Error Handlers ---
102
+ var errorHandlers_1 = require("./utils/errorHandlers");
103
+ Object.defineProperty(exports, "handleAuthError", { enumerable: true, get: function () { return errorHandlers_1.handleAuthError; } });
104
+ Object.defineProperty(exports, "isInvalidSessionError", { enumerable: true, get: function () { return errorHandlers_1.isInvalidSessionError; } });
105
+ Object.defineProperty(exports, "isTimeoutOrNetworkError", { enumerable: true, get: function () { return errorHandlers_1.isTimeoutOrNetworkError; } });
106
+ Object.defineProperty(exports, "extractErrorMessage", { enumerable: true, get: function () { return errorHandlers_1.extractErrorMessage; } });
107
+ // Re-export core for convenience
108
+ var core_1 = require("@oxyhq/core");
109
+ Object.defineProperty(exports, "OxyServices", { enumerable: true, get: function () { return core_1.OxyServices; } });
110
+ Object.defineProperty(exports, "CrossDomainAuth", { enumerable: true, get: function () { return core_1.CrossDomainAuth; } });
111
+ Object.defineProperty(exports, "AuthManager", { enumerable: true, get: function () { return core_1.AuthManager; } });
112
+ Object.defineProperty(exports, "createAuthManager", { enumerable: true, get: function () { return core_1.createAuthManager; } });
113
+ Object.defineProperty(exports, "createCrossDomainAuth", { enumerable: true, get: function () { return core_1.createCrossDomainAuth; } });
114
+ const WebOxyProvider_2 = require("./WebOxyProvider");
115
+ exports.default = WebOxyProvider_2.WebOxyProvider;
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAccountLoadingSession = exports.useAccountError = exports.useAccountLoading = exports.useAccounts = exports.useAccountStore = void 0;
4
+ const zustand_1 = require("zustand");
5
+ const initialState = {
6
+ accounts: {},
7
+ accountOrder: [],
8
+ accountsArray: [],
9
+ loading: false,
10
+ loadingSessionIds: new Set(),
11
+ error: null,
12
+ };
13
+ // Helper: Build accounts array from accounts map and order
14
+ const buildAccountsArray = (accounts, order) => {
15
+ const result = [];
16
+ for (const id of order) {
17
+ const account = accounts[id];
18
+ if (account)
19
+ result.push(account);
20
+ }
21
+ return result;
22
+ };
23
+ // Helper: Create QuickAccount from user data
24
+ const createQuickAccount = (sessionId, userData, existingAccount, oxyServices) => {
25
+ const displayName = userData.name?.full || userData.name?.first || userData.username || 'Account';
26
+ const userId = userData.id || userData._id?.toString();
27
+ // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
28
+ let avatarUrl;
29
+ if (existingAccount && existingAccount.avatar === userData.avatar && existingAccount.avatarUrl) {
30
+ avatarUrl = existingAccount.avatarUrl; // Reuse existing URL
31
+ }
32
+ else if (userData.avatar && oxyServices) {
33
+ avatarUrl = oxyServices.getFileDownloadUrl(userData.avatar, 'thumb');
34
+ }
35
+ return {
36
+ sessionId,
37
+ userId,
38
+ username: userData.username || '',
39
+ displayName,
40
+ avatar: userData.avatar,
41
+ avatarUrl,
42
+ };
43
+ };
44
+ exports.useAccountStore = (0, zustand_1.create)((set, get) => ({
45
+ ...initialState,
46
+ setAccounts: (accounts) => set((state) => {
47
+ const accountMap = {};
48
+ const order = [];
49
+ const seenSessionIds = new Set();
50
+ for (const account of accounts) {
51
+ if (seenSessionIds.has(account.sessionId))
52
+ continue;
53
+ seenSessionIds.add(account.sessionId);
54
+ accountMap[account.sessionId] = account;
55
+ order.push(account.sessionId);
56
+ }
57
+ const accountsArray = buildAccountsArray(accountMap, order);
58
+ const sameOrder = order.length === state.accountOrder.length &&
59
+ order.every((id, i) => id === state.accountOrder[i]);
60
+ const sameAccounts = sameOrder &&
61
+ order.every(id => {
62
+ const existing = state.accounts[id];
63
+ const newAccount = accountMap[id];
64
+ return existing &&
65
+ existing.sessionId === newAccount.sessionId &&
66
+ existing.userId === newAccount.userId &&
67
+ existing.avatar === newAccount.avatar &&
68
+ existing.avatarUrl === newAccount.avatarUrl;
69
+ });
70
+ if (sameAccounts)
71
+ return {};
72
+ return { accounts: accountMap, accountOrder: order, accountsArray };
73
+ }),
74
+ addAccount: (account) => set((state) => {
75
+ // Check if account with same sessionId exists
76
+ if (state.accounts[account.sessionId]) {
77
+ // Update existing
78
+ const existing = state.accounts[account.sessionId];
79
+ if (existing.avatar === account.avatar && existing.avatarUrl === account.avatarUrl) {
80
+ return {}; // No change
81
+ }
82
+ const newAccounts = { ...state.accounts, [account.sessionId]: account };
83
+ return {
84
+ accounts: newAccounts,
85
+ accountsArray: buildAccountsArray(newAccounts, state.accountOrder),
86
+ };
87
+ }
88
+ const newAccounts = { ...state.accounts, [account.sessionId]: account };
89
+ const newOrder = [account.sessionId, ...state.accountOrder];
90
+ return {
91
+ accounts: newAccounts,
92
+ accountOrder: newOrder,
93
+ accountsArray: buildAccountsArray(newAccounts, newOrder),
94
+ };
95
+ }),
96
+ updateAccount: (sessionId, updates) => set((state) => {
97
+ const existing = state.accounts[sessionId];
98
+ if (!existing)
99
+ return {};
100
+ const updated = { ...existing, ...updates };
101
+ if (existing.avatar === updated.avatar && existing.avatarUrl === updated.avatarUrl) {
102
+ return {}; // No change
103
+ }
104
+ const newAccounts = { ...state.accounts, [sessionId]: updated };
105
+ return {
106
+ accounts: newAccounts,
107
+ accountsArray: buildAccountsArray(newAccounts, state.accountOrder),
108
+ };
109
+ }),
110
+ removeAccount: (sessionId) => set((state) => {
111
+ if (!state.accounts[sessionId])
112
+ return {};
113
+ const { [sessionId]: _removed, ...rest } = state.accounts;
114
+ const newOrder = state.accountOrder.filter(id => id !== sessionId);
115
+ return {
116
+ accounts: rest,
117
+ accountOrder: newOrder,
118
+ accountsArray: buildAccountsArray(rest, newOrder),
119
+ };
120
+ }),
121
+ moveAccountToTop: (sessionId) => set((state) => {
122
+ if (!state.accounts[sessionId])
123
+ return {};
124
+ const filtered = state.accountOrder.filter(id => id !== sessionId);
125
+ const newOrder = [sessionId, ...filtered];
126
+ return {
127
+ accountOrder: newOrder,
128
+ accountsArray: buildAccountsArray(state.accounts, newOrder),
129
+ };
130
+ }),
131
+ setLoading: (loading) => set({ loading }),
132
+ setLoadingSession: (sessionId, loading) => set((state) => {
133
+ const newSet = new Set(state.loadingSessionIds);
134
+ if (loading) {
135
+ newSet.add(sessionId);
136
+ }
137
+ else {
138
+ newSet.delete(sessionId);
139
+ }
140
+ return { loadingSessionIds: newSet };
141
+ }),
142
+ setError: (error) => set({ error }),
143
+ loadAccounts: async (sessionIds, oxyServices, existingAccounts = [], preserveOrder = true) => {
144
+ const state = get();
145
+ const uniqueSessionIds = Array.from(new Set(sessionIds));
146
+ if (uniqueSessionIds.length === 0) {
147
+ get().setAccounts([]);
148
+ return;
149
+ }
150
+ // Try to get data from TanStack Query cache first
151
+ try {
152
+ // This will be called from a component, so we need to access queryClient differently
153
+ // For now, we'll keep the API call but optimize it
154
+ const existingMap = new Map(existingAccounts.map(a => [a.sessionId, a]));
155
+ for (const account of Object.values(state.accounts)) {
156
+ existingMap.set(account.sessionId, account);
157
+ }
158
+ const missingSessionIds = uniqueSessionIds.filter(id => !existingMap.has(id));
159
+ if (missingSessionIds.length === 0) {
160
+ const ordered = uniqueSessionIds
161
+ .map(id => existingMap.get(id))
162
+ .filter((acc) => acc !== undefined);
163
+ get().setAccounts(ordered);
164
+ return;
165
+ }
166
+ if (state.loading) {
167
+ return;
168
+ }
169
+ set({ loading: true, error: null });
170
+ try {
171
+ const batchResults = await oxyServices.getUsersBySessions(missingSessionIds);
172
+ const accountMap = new Map();
173
+ for (const { sessionId, user: userData } of batchResults) {
174
+ if (userData && !accountMap.has(sessionId)) {
175
+ const existing = existingMap.get(sessionId);
176
+ accountMap.set(sessionId, createQuickAccount(sessionId, userData, existing, oxyServices));
177
+ }
178
+ }
179
+ for (const [sessionId, account] of accountMap) {
180
+ existingMap.set(sessionId, account);
181
+ }
182
+ const orderToUse = preserveOrder ? uniqueSessionIds : [...uniqueSessionIds, ...state.accountOrder];
183
+ const seen = new Set();
184
+ const ordered = [];
185
+ for (const sessionId of orderToUse) {
186
+ if (seen.has(sessionId))
187
+ continue;
188
+ seen.add(sessionId);
189
+ const account = existingMap.get(sessionId);
190
+ if (account)
191
+ ordered.push(account);
192
+ }
193
+ get().setAccounts(ordered);
194
+ }
195
+ catch (error) {
196
+ const errorMessage = error instanceof Error ? error.message : 'Failed to load accounts';
197
+ if (__DEV__) {
198
+ console.error('AccountStore: Failed to load accounts:', error);
199
+ }
200
+ set({ error: errorMessage });
201
+ }
202
+ finally {
203
+ set({ loading: false });
204
+ }
205
+ }
206
+ catch (error) {
207
+ const errorMessage = error instanceof Error ? error.message : 'Failed to load accounts';
208
+ if (__DEV__) {
209
+ console.error('AccountStore: Failed to load accounts:', error);
210
+ }
211
+ set({ error: errorMessage, loading: false });
212
+ }
213
+ },
214
+ reset: () => set(initialState),
215
+ }));
216
+ // Selectors for performance - return cached array to prevent infinite loops
217
+ const useAccounts = () => {
218
+ return (0, exports.useAccountStore)(state => state.accountsArray);
219
+ };
220
+ exports.useAccounts = useAccounts;
221
+ const useAccountLoading = () => (0, exports.useAccountStore)(s => s.loading);
222
+ exports.useAccountLoading = useAccountLoading;
223
+ const useAccountError = () => (0, exports.useAccountStore)(s => s.error);
224
+ exports.useAccountError = useAccountError;
225
+ const useAccountLoadingSession = (sessionId) => (0, exports.useAccountStore)(s => s.loadingSessionIds.has(sessionId));
226
+ exports.useAccountLoadingSession = useAccountLoadingSession;
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useIsAssetLinked = exports.useAssetUsageCount = exports.useAssetsByEntity = exports.useAssetsByApp = exports.useAssetErrors = exports.useAssetLoading = exports.useUploadProgress = exports.useAsset = exports.useAssets = exports.useAssetStore = void 0;
4
+ const zustand_1 = require("zustand");
5
+ const initialState = {
6
+ assets: {},
7
+ uploadProgress: {},
8
+ loading: {
9
+ uploading: false,
10
+ linking: false,
11
+ deleting: false,
12
+ },
13
+ errors: {},
14
+ };
15
+ exports.useAssetStore = (0, zustand_1.create)((set, get) => ({
16
+ ...initialState,
17
+ // Asset management
18
+ setAsset: (asset) => {
19
+ set((state) => ({
20
+ assets: {
21
+ ...state.assets,
22
+ [asset.id]: asset,
23
+ },
24
+ }));
25
+ },
26
+ setAssets: (assets) => {
27
+ set((state) => {
28
+ const assetMap = assets.reduce((acc, asset) => {
29
+ acc[asset.id] = asset;
30
+ return acc;
31
+ }, {});
32
+ return {
33
+ assets: {
34
+ ...state.assets,
35
+ ...assetMap,
36
+ },
37
+ };
38
+ });
39
+ },
40
+ removeAsset: (assetId) => {
41
+ set((state) => {
42
+ const { [assetId]: removed, ...rest } = state.assets;
43
+ return { assets: rest };
44
+ });
45
+ },
46
+ // Upload progress
47
+ setUploadProgress: (fileId, progress) => {
48
+ set((state) => ({
49
+ uploadProgress: {
50
+ ...state.uploadProgress,
51
+ [fileId]: progress,
52
+ },
53
+ }));
54
+ },
55
+ removeUploadProgress: (fileId) => {
56
+ set((state) => {
57
+ const { [fileId]: removed, ...rest } = state.uploadProgress;
58
+ return { uploadProgress: rest };
59
+ });
60
+ },
61
+ // Link management
62
+ addLink: (assetId, link) => {
63
+ set((state) => {
64
+ const asset = state.assets[assetId];
65
+ if (!asset)
66
+ return state;
67
+ // Check if link already exists
68
+ const existingLink = asset.links.find((l) => l.app === link.app &&
69
+ l.entityType === link.entityType &&
70
+ l.entityId === link.entityId);
71
+ if (existingLink)
72
+ return state;
73
+ const updatedAsset = {
74
+ ...asset,
75
+ links: [...asset.links, link],
76
+ usageCount: asset.links.length + 1,
77
+ };
78
+ return {
79
+ assets: {
80
+ ...state.assets,
81
+ [assetId]: updatedAsset,
82
+ },
83
+ };
84
+ });
85
+ },
86
+ removeLink: (assetId, app, entityType, entityId) => {
87
+ set((state) => {
88
+ const asset = state.assets[assetId];
89
+ if (!asset)
90
+ return state;
91
+ const filteredLinks = asset.links.filter((link) => !(link.app === app &&
92
+ link.entityType === entityType &&
93
+ link.entityId === entityId));
94
+ const updatedAsset = {
95
+ ...asset,
96
+ links: filteredLinks,
97
+ usageCount: filteredLinks.length,
98
+ status: filteredLinks.length === 0 ? 'trash' : asset.status,
99
+ };
100
+ return {
101
+ assets: {
102
+ ...state.assets,
103
+ [assetId]: updatedAsset,
104
+ },
105
+ };
106
+ });
107
+ },
108
+ // Loading states
109
+ setUploading: (uploading) => {
110
+ set((state) => ({
111
+ loading: { ...state.loading, uploading },
112
+ }));
113
+ },
114
+ setLinking: (linking) => {
115
+ set((state) => ({
116
+ loading: { ...state.loading, linking },
117
+ }));
118
+ },
119
+ setDeleting: (deleting) => {
120
+ set((state) => ({
121
+ loading: { ...state.loading, deleting },
122
+ }));
123
+ },
124
+ // Error management
125
+ setUploadError: (error) => {
126
+ set((state) => ({
127
+ errors: { ...state.errors, upload: error },
128
+ }));
129
+ },
130
+ setLinkError: (error) => {
131
+ set((state) => ({
132
+ errors: { ...state.errors, link: error },
133
+ }));
134
+ },
135
+ setDeleteError: (error) => {
136
+ set((state) => ({
137
+ errors: { ...state.errors, delete: error },
138
+ }));
139
+ },
140
+ clearErrors: () => {
141
+ set({ errors: {} });
142
+ },
143
+ // Utility methods
144
+ getAssetsByApp: (app) => {
145
+ const { assets } = get();
146
+ return Object.values(assets).filter((asset) => asset.links.some((link) => link.app === app));
147
+ },
148
+ getAssetsByEntity: (app, entityType, entityId) => {
149
+ const { assets } = get();
150
+ return Object.values(assets).filter((asset) => asset.links.some((link) => link.app === app &&
151
+ link.entityType === entityType &&
152
+ link.entityId === entityId));
153
+ },
154
+ getAssetUsageCount: (assetId) => {
155
+ const { assets } = get();
156
+ const asset = assets[assetId];
157
+ return asset ? asset.usageCount : 0;
158
+ },
159
+ isAssetLinked: (assetId, app, entityType, entityId) => {
160
+ const { assets } = get();
161
+ const asset = assets[assetId];
162
+ if (!asset)
163
+ return false;
164
+ return asset.links.some((link) => link.app === app &&
165
+ link.entityType === entityType &&
166
+ link.entityId === entityId);
167
+ },
168
+ // Reset store
169
+ reset: () => {
170
+ set(initialState);
171
+ },
172
+ }));
173
+ // Selector hooks for convenience
174
+ const useAssets = () => (0, exports.useAssetStore)((state) => Object.values(state.assets));
175
+ exports.useAssets = useAssets;
176
+ const useAsset = (assetId) => (0, exports.useAssetStore)((state) => state.assets[assetId]);
177
+ exports.useAsset = useAsset;
178
+ const useUploadProgress = () => (0, exports.useAssetStore)((state) => state.uploadProgress);
179
+ exports.useUploadProgress = useUploadProgress;
180
+ const useAssetLoading = () => (0, exports.useAssetStore)((state) => state.loading);
181
+ exports.useAssetLoading = useAssetLoading;
182
+ const useAssetErrors = () => (0, exports.useAssetStore)((state) => state.errors);
183
+ exports.useAssetErrors = useAssetErrors;
184
+ // Typed selectors for specific use cases
185
+ const useAssetsByApp = (app) => (0, exports.useAssetStore)((state) => state.getAssetsByApp(app));
186
+ exports.useAssetsByApp = useAssetsByApp;
187
+ const useAssetsByEntity = (app, entityType, entityId) => (0, exports.useAssetStore)((state) => state.getAssetsByEntity(app, entityType, entityId));
188
+ exports.useAssetsByEntity = useAssetsByEntity;
189
+ const useAssetUsageCount = (assetId) => (0, exports.useAssetStore)((state) => state.getAssetUsageCount(assetId));
190
+ exports.useAssetUsageCount = useAssetUsageCount;
191
+ const useIsAssetLinked = (assetId, app, entityType, entityId) => (0, exports.useAssetStore)((state) => state.isAssetLinked(assetId, app, entityType, entityId));
192
+ exports.useIsAssetLinked = useIsAssetLinked;