@elevasis/ui 1.2.1 → 1.3.1
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/dist/CoreAuthKitInner-3J4RVQO6.js +43 -0
- package/dist/api/index.d.ts +32 -18
- package/dist/api/index.js +4 -2
- package/dist/auth/context.d.ts +23 -5
- package/dist/auth/index.d.ts +119 -30
- package/dist/auth/index.js +6 -3
- package/dist/chunk-2JBWPFHF.js +108 -0
- package/dist/chunk-4VGWQ5AN.js +91 -0
- package/dist/chunk-72HOBFMP.js +87 -0
- package/dist/{chunk-WNWKOCGJ.js → chunk-A3MCANC6.js} +296 -2
- package/dist/{chunk-JKERRYVS.js → chunk-BLO4SISK.js} +7 -3
- package/dist/chunk-DD3CCMCZ.js +15 -0
- package/dist/chunk-FWZJH3TL.js +13 -0
- package/dist/{chunk-GEFB5YIR.js → chunk-JBFFCZI4.js} +1 -1
- package/dist/chunk-JGJSZ3UE.js +47 -0
- package/dist/{chunk-7AI5ZYJ4.js → chunk-JVAZHVNV.js} +2 -94
- package/dist/{chunk-ZGHDPDTF.js → chunk-JYSYHVLU.js} +3 -3
- package/dist/{chunk-5UWFGBFM.js → chunk-L2CM2CUA.js} +16 -4
- package/dist/chunk-NEK6JKPW.js +75 -0
- package/dist/{chunk-J3FALDQE.js → chunk-NXHL23JW.js} +7 -13
- package/dist/{chunk-OUHGHTE7.js → chunk-O3PY6B6E.js} +3 -2
- package/dist/{chunk-YULUKCS6.js → chunk-PVVQTENF.js} +1 -1
- package/dist/chunk-TIRMFDM4.js +33 -0
- package/dist/{chunk-PYL4XW6H.js → chunk-TMFCNFLW.js} +1 -1
- package/dist/{chunk-S66I2PYB.js → chunk-TN3PU2WK.js} +1 -1
- package/dist/chunk-TYV5NJV2.js +1 -0
- package/dist/{chunk-B64YDSAY.js → chunk-TZPAA4RC.js} +54 -97
- package/dist/chunk-UMXDDEAG.js +148 -0
- package/dist/chunk-XLV6LYN2.js +157 -0
- package/dist/components/command-queue/index.js +6 -4
- package/dist/components/index.js +9 -7
- package/dist/components/notifications/index.js +4 -3
- package/dist/display/index.js +3 -2
- package/dist/hooks/index.d.ts +2630 -3
- package/dist/hooks/index.js +9 -5
- package/dist/hooks/published.d.ts +2630 -3
- package/dist/hooks/published.js +7 -3
- package/dist/index.d.ts +759 -164
- package/dist/index.js +24 -18
- package/dist/initialization/index.d.ts +49 -1
- package/dist/initialization/index.js +5 -2
- package/dist/organization/index.d.ts +61 -2
- package/dist/organization/index.js +5 -2
- package/dist/profile/index.d.ts +30 -2
- package/dist/profile/index.js +2 -1
- package/dist/provider/index.d.ts +116 -43
- package/dist/provider/index.js +10 -6
- package/dist/provider/published.d.ts +88 -28
- package/dist/provider/published.js +9 -4
- package/dist/supabase/index.js +2 -47
- package/dist/utils/index.js +2 -1
- package/package.json +15 -2
- package/dist/CoreAuthKitInner-KM72EYJS.js +0 -19
- package/dist/chunk-GDV44UWF.js +0 -138
- package/dist/chunk-HBRMWW6V.js +0 -43
- package/dist/chunk-NIAVTSMB.js +0 -21
- package/dist/chunk-QSVZP2NU.js +0 -214
- package/dist/chunk-ZQVPUAGR.js +0 -89
- /package/dist/{chunk-Q47SPRY7.js → chunk-RNP5R5I3.js} +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AuthProvider } from './chunk-7PLEQFHO.js';
|
|
2
|
+
import { AuthKitProvider, useAuth } from '@workos-inc/authkit-react';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function CoreAuthKitInner({ auth, children }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
AuthKitProvider,
|
|
9
|
+
{
|
|
10
|
+
clientId: auth.clientId,
|
|
11
|
+
apiHostname: auth.apiHostname ?? "api.workos.com",
|
|
12
|
+
redirectUri: auth.redirectUri,
|
|
13
|
+
devMode: auth.devMode ?? false,
|
|
14
|
+
children: /* @__PURE__ */ jsx(WorkOSAuthAdapter, { children })
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
var WORKOS_REFRESH_TOKEN_KEY = "workos:refresh-token";
|
|
19
|
+
function hasWorkOSRefreshToken() {
|
|
20
|
+
try {
|
|
21
|
+
return !!localStorage.getItem(WORKOS_REFRESH_TOKEN_KEY);
|
|
22
|
+
} catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function WorkOSAuthAdapter({ children }) {
|
|
27
|
+
const { user, isLoading, getAccessToken, organizationId, signIn } = useAuth();
|
|
28
|
+
const adaptedUser = useMemo(() => user ? { id: user.id } : null, [user?.id]);
|
|
29
|
+
const value = useMemo(
|
|
30
|
+
() => ({
|
|
31
|
+
user: adaptedUser,
|
|
32
|
+
isLoading,
|
|
33
|
+
getAccessToken,
|
|
34
|
+
organizationId: organizationId ?? null,
|
|
35
|
+
signIn,
|
|
36
|
+
canRecover: hasWorkOSRefreshToken
|
|
37
|
+
}),
|
|
38
|
+
[adaptedUser, isLoading, getAccessToken, organizationId, signIn]
|
|
39
|
+
);
|
|
40
|
+
return /* @__PURE__ */ jsx(AuthProvider, { value, children });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { CoreAuthKitInner };
|
package/dist/api/index.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
5
5
|
*/
|
|
6
6
|
interface ApiClientContextValue {
|
|
7
7
|
getAccessToken: () => Promise<string | undefined>;
|
|
8
|
+
/** @deprecated Read via getOrganizationId() instead. Kept for downstream context consumers during migration. */
|
|
8
9
|
organizationId: string | null;
|
|
9
10
|
isOrganizationReady: boolean;
|
|
11
|
+
getOrganizationId: () => string | null;
|
|
10
12
|
onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
|
|
11
13
|
}
|
|
12
14
|
interface ApiErrorDetails {
|
|
@@ -17,7 +19,19 @@ interface ApiErrorDetails {
|
|
|
17
19
|
interface ApiClientProviderProps {
|
|
18
20
|
children: React.ReactNode;
|
|
19
21
|
getAccessToken: () => Promise<string | undefined>;
|
|
20
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Static org ID. Used when org ID is stable at render time.
|
|
24
|
+
* Cannot reflect org switches without re-rendering the provider.
|
|
25
|
+
* Prefer getOrganizationId for dynamic org context.
|
|
26
|
+
* @deprecated Pass getOrganizationId instead for dynamic org resolution.
|
|
27
|
+
*/
|
|
28
|
+
organizationId?: string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Callback invoked on every request to read the current org ID.
|
|
31
|
+
* Takes precedence over organizationId when provided.
|
|
32
|
+
* Allows org switching without re-rendering the provider tree.
|
|
33
|
+
*/
|
|
34
|
+
getOrganizationId?: () => string | null;
|
|
21
35
|
isOrganizationReady: boolean;
|
|
22
36
|
onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
|
|
23
37
|
}
|
|
@@ -52,36 +66,36 @@ declare function useApiClientContext(): ApiClientContextValue;
|
|
|
52
66
|
* }
|
|
53
67
|
* ```
|
|
54
68
|
*/
|
|
55
|
-
declare function ApiClientProvider({ children, getAccessToken, organizationId, isOrganizationReady, onError }: ApiClientProviderProps): react_jsx_runtime.JSX.Element;
|
|
69
|
+
declare function ApiClientProvider({ children, getAccessToken, organizationId, getOrganizationId: getOrganizationIdProp, isOrganizationReady, onError }: ApiClientProviderProps): react_jsx_runtime.JSX.Element;
|
|
56
70
|
|
|
57
71
|
/**
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
isInitializing: boolean;
|
|
62
|
-
isOrgRefreshing: boolean;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Factory function to create a useApiClient hook for your app.
|
|
72
|
+
* Hook that returns apiRequest and deferredApiRequest bound to the current
|
|
73
|
+
* ApiClientContext. apiUrl is the only parameter because org ID is resolved
|
|
74
|
+
* at call time via getOrganizationId() from context.
|
|
66
75
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
76
|
+
* When OrganizationProvider is present in the tree, isOrganizationReady and
|
|
77
|
+
* isInitializing reflect the live org state (currentWorkOSOrganizationId,
|
|
78
|
+
* isInitializing, isOrgRefreshing). When OrganizationProvider is absent
|
|
79
|
+
* (e.g. theme-only mode, testing), the hook falls back to the values from
|
|
80
|
+
* ApiClientContext.
|
|
69
81
|
*
|
|
70
|
-
* Usage
|
|
82
|
+
* Usage:
|
|
71
83
|
* ```typescript
|
|
72
|
-
* import {
|
|
73
|
-
* import { useOrganizations } from './organization/hooks/useOrganizations'
|
|
84
|
+
* import { useApiClient } from '@repo/ui/api'
|
|
74
85
|
*
|
|
75
86
|
* const API_URL = import.meta.env.VITE_API_SERVER || 'http://localhost:5170'
|
|
76
|
-
*
|
|
87
|
+
*
|
|
88
|
+
* function useMyClient() {
|
|
89
|
+
* return useApiClient(API_URL)
|
|
90
|
+
* }
|
|
77
91
|
* ```
|
|
78
92
|
*/
|
|
79
|
-
declare function
|
|
93
|
+
declare function useApiClient(apiUrl: string): {
|
|
80
94
|
apiRequest: <T>(endpoint: string, options?: RequestInit) => Promise<T>;
|
|
81
95
|
deferredApiRequest: <T>(endpoint: string, options?: RequestInit) => Promise<T>;
|
|
82
96
|
isOrganizationReady: boolean;
|
|
83
97
|
isInitializing: boolean;
|
|
84
98
|
};
|
|
85
99
|
|
|
86
|
-
export { ApiClientProvider,
|
|
100
|
+
export { ApiClientProvider, useApiClient, useApiClientContext };
|
|
87
101
|
export type { ApiClientContextValue, ApiClientProviderProps, ApiErrorDetails };
|
package/dist/api/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import '../chunk-XCYKC6OZ.js';
|
|
2
|
-
export { ApiClientProvider,
|
|
3
|
-
import '../chunk-
|
|
2
|
+
export { ApiClientProvider, useApiClient, useApiClientContext } from '../chunk-XLV6LYN2.js';
|
|
3
|
+
import '../chunk-JVAZHVNV.js';
|
|
4
|
+
import '../chunk-4VGWQ5AN.js';
|
|
5
|
+
import '../chunk-DD3CCMCZ.js';
|
package/dist/auth/context.d.ts
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
interface
|
|
4
|
+
interface AuthContextValue {
|
|
5
5
|
user: {
|
|
6
6
|
id: string;
|
|
7
7
|
} | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
getAccessToken: () => Promise<string>;
|
|
10
10
|
organizationId?: string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Trigger WorkOS AuthKit's sign-in flow (redirect to WorkOS hosted auth page).
|
|
13
|
+
* Used by ProtectedRoute for auto-recovery when `canRecover()` returns true.
|
|
14
|
+
*/
|
|
15
|
+
signIn: (options?: {
|
|
16
|
+
state?: {
|
|
17
|
+
returnTo?: string;
|
|
18
|
+
};
|
|
19
|
+
}) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Returns true when a previous session can be recovered (refresh token
|
|
22
|
+
* exists in storage). ProtectedRoute calls `signIn()` only when this returns
|
|
23
|
+
* true; otherwise it navigates to the login page.
|
|
24
|
+
*
|
|
25
|
+
* Explicit logout clears the stored token, so canRecover() returns false
|
|
26
|
+
* and the user sees the login page as expected.
|
|
27
|
+
*/
|
|
28
|
+
canRecover: () => boolean;
|
|
11
29
|
}
|
|
12
|
-
declare function useAuthContext():
|
|
30
|
+
declare function useAuthContext(): AuthContextValue;
|
|
13
31
|
declare function AuthProvider({ value, children }: {
|
|
14
|
-
value:
|
|
32
|
+
value: AuthContextValue;
|
|
15
33
|
children: ReactNode;
|
|
16
|
-
}): react.FunctionComponentElement<react.ProviderProps<
|
|
34
|
+
}): react.FunctionComponentElement<react.ProviderProps<AuthContextValue | null>>;
|
|
17
35
|
|
|
18
36
|
export { AuthProvider, useAuthContext };
|
|
19
|
-
export type {
|
|
37
|
+
export type { AuthContextValue };
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -2,43 +2,37 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
|
-
interface
|
|
5
|
+
interface AuthContextValue {
|
|
6
6
|
user: {
|
|
7
7
|
id: string;
|
|
8
8
|
} | null;
|
|
9
9
|
isLoading: boolean;
|
|
10
10
|
getAccessToken: () => Promise<string>;
|
|
11
11
|
organizationId?: string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Trigger WorkOS AuthKit's sign-in flow (redirect to WorkOS hosted auth page).
|
|
14
|
+
* Used by ProtectedRoute for auto-recovery when `canRecover()` returns true.
|
|
15
|
+
*/
|
|
16
|
+
signIn: (options?: {
|
|
17
|
+
state?: {
|
|
18
|
+
returnTo?: string;
|
|
19
|
+
};
|
|
20
|
+
}) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Returns true when a previous session can be recovered (refresh token
|
|
23
|
+
* exists in storage). ProtectedRoute calls `signIn()` only when this returns
|
|
24
|
+
* true; otherwise it navigates to the login page.
|
|
25
|
+
*
|
|
26
|
+
* Explicit logout clears the stored token, so canRecover() returns false
|
|
27
|
+
* and the user sees the login page as expected.
|
|
28
|
+
*/
|
|
29
|
+
canRecover: () => boolean;
|
|
12
30
|
}
|
|
13
|
-
declare function useAuthContext():
|
|
31
|
+
declare function useAuthContext(): AuthContextValue;
|
|
14
32
|
declare function AuthProvider({ value, children }: {
|
|
15
|
-
value:
|
|
33
|
+
value: AuthContextValue;
|
|
16
34
|
children: ReactNode;
|
|
17
|
-
}): react.FunctionComponentElement<react.ProviderProps<
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Bridge component that reads WorkOS AuthKit state and provides it
|
|
21
|
-
* via the generic AuthContext. Place inside AuthKitProvider.
|
|
22
|
-
*
|
|
23
|
-
* Narrows WorkOS User to { id: string } -- @repo/ui hooks only need the ID.
|
|
24
|
-
* Uses useMemo to stabilize the user object and prevent unnecessary
|
|
25
|
-
* useEffect re-runs in downstream hooks.
|
|
26
|
-
*/
|
|
27
|
-
declare function WorkOSAuthBridge({ children }: {
|
|
28
|
-
children: ReactNode;
|
|
29
|
-
}): react_jsx_runtime.JSX.Element;
|
|
30
|
-
|
|
31
|
-
interface OAuthContextValue {
|
|
32
|
-
user: {
|
|
33
|
-
id: string;
|
|
34
|
-
} | null;
|
|
35
|
-
isLoading: boolean;
|
|
36
|
-
organizationId: string | null;
|
|
37
|
-
getAccessToken: () => Promise<string>;
|
|
38
|
-
error: string | null;
|
|
39
|
-
initiateOAuthFlow: () => void;
|
|
40
|
-
}
|
|
41
|
-
declare function useOAuthContext(): OAuthContextValue;
|
|
35
|
+
}): react.FunctionComponentElement<react.ProviderProps<AuthContextValue | null>>;
|
|
42
36
|
|
|
43
37
|
/**
|
|
44
38
|
* Returns a stable reference to getAccessToken that won't change between renders
|
|
@@ -83,5 +77,100 @@ declare function useStableAccessToken(): () => Promise<string>;
|
|
|
83
77
|
*/
|
|
84
78
|
declare function useSessionCheck(): void;
|
|
85
79
|
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
interface InitializationError {
|
|
81
|
+
layer: 'auth' | 'profile' | 'organization';
|
|
82
|
+
message: string;
|
|
83
|
+
originalError?: Error;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface ProtectedRouteProps {
|
|
87
|
+
children: ReactNode;
|
|
88
|
+
/**
|
|
89
|
+
* Path to redirect to when user is unauthenticated and the auth adapter
|
|
90
|
+
* does not provide a `signIn` function.
|
|
91
|
+
* @default '/login'
|
|
92
|
+
*/
|
|
93
|
+
redirectTo?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Rendered while initialization is in progress.
|
|
96
|
+
* When not provided, nothing is rendered during initialization.
|
|
97
|
+
*/
|
|
98
|
+
fallback?: ReactNode;
|
|
99
|
+
/**
|
|
100
|
+
* Rendered when initialization fails with a non-organization error.
|
|
101
|
+
* Receives the error and a retry callback.
|
|
102
|
+
* When not provided, the error is silently swallowed (children not rendered).
|
|
103
|
+
*/
|
|
104
|
+
errorFallback?: (error: InitializationError, retry: () => void) => ReactNode;
|
|
105
|
+
/**
|
|
106
|
+
* When true (default), waits for both user AND organization to be ready
|
|
107
|
+
* before rendering children. When false, only waits for user readiness.
|
|
108
|
+
* @default true
|
|
109
|
+
*/
|
|
110
|
+
waitForOrganization?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Headless route guard for authenticated pages.
|
|
114
|
+
*
|
|
115
|
+
* Reads initialization state from the nearest InitializationProvider.
|
|
116
|
+
*
|
|
117
|
+
* When `canRecover()` returns true (refresh token exists), unauthenticated users
|
|
118
|
+
* are sent directly to WorkOS AuthKit via `signIn()`. WorkOS checks its
|
|
119
|
+
* server-side session and either signs the user in immediately (page-reload case)
|
|
120
|
+
* or shows a login form (logged-out case). Explicit logout destroys the
|
|
121
|
+
* server-side session, so the next auto-signIn correctly presents a login form
|
|
122
|
+
* rather than looping.
|
|
123
|
+
*
|
|
124
|
+
* When `canRecover()` returns false, falls back to navigating to `redirectTo`
|
|
125
|
+
* (default: '/login') with a `returnTo` search param.
|
|
126
|
+
*
|
|
127
|
+
* Organization-layer errors are allowed through -- routes like /invitations
|
|
128
|
+
* must be accessible even when the user has no org membership.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // With custom fallback (your Mantine loader):
|
|
132
|
+
* <ProtectedRoute fallback={<AppShellLoader />}>
|
|
133
|
+
* <DashboardPage />
|
|
134
|
+
* </ProtectedRoute>
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* // Wait only for user, not org (e.g. /invitations route):
|
|
138
|
+
* <ProtectedRoute waitForOrganization={false}>
|
|
139
|
+
* <InvitationsPage />
|
|
140
|
+
* </ProtectedRoute>
|
|
141
|
+
*/
|
|
142
|
+
declare function ProtectedRoute({ children, redirectTo, fallback, errorFallback, waitForOrganization }: ProtectedRouteProps): react_jsx_runtime.JSX.Element | null;
|
|
143
|
+
|
|
144
|
+
interface AdminGuardProps {
|
|
145
|
+
children: ReactNode;
|
|
146
|
+
/**
|
|
147
|
+
* Path to redirect non-admin users to.
|
|
148
|
+
* @default '/'
|
|
149
|
+
*/
|
|
150
|
+
redirectTo?: string;
|
|
151
|
+
/**
|
|
152
|
+
* Rendered while user readiness is being determined.
|
|
153
|
+
* When not provided, nothing is rendered during initialization.
|
|
154
|
+
*/
|
|
155
|
+
fallback?: ReactNode;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Headless route guard for platform admin pages.
|
|
159
|
+
*
|
|
160
|
+
* Reads `profile.is_platform_admin` from the nearest InitializationProvider.
|
|
161
|
+
* Non-admin users are redirected to `redirectTo` (default: '/').
|
|
162
|
+
*
|
|
163
|
+
* Must be nested inside a ProtectedRoute (or equivalent) so that
|
|
164
|
+
* `userReady` is guaranteed to be true when this guard runs.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* <ProtectedRoute>
|
|
168
|
+
* <AdminGuard fallback={<AppShellLoader />}>
|
|
169
|
+
* <AdminDashboard />
|
|
170
|
+
* </AdminGuard>
|
|
171
|
+
* </ProtectedRoute>
|
|
172
|
+
*/
|
|
173
|
+
declare function AdminGuard({ children, redirectTo, fallback }: AdminGuardProps): react_jsx_runtime.JSX.Element | null;
|
|
174
|
+
|
|
175
|
+
export { AdminGuard, AuthProvider, ProtectedRoute, useAuthContext, useSessionCheck as useRefocusSessionCheck, useSessionCheck, useStableAccessToken };
|
|
176
|
+
export type { AdminGuardProps, AuthContextValue, ProtectedRouteProps };
|
package/dist/auth/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export { useSessionCheck as useRefocusSessionCheck, useSessionCheck
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
export { AdminGuard, ProtectedRoute, useSessionCheck as useRefocusSessionCheck, useSessionCheck } from '../chunk-2JBWPFHF.js';
|
|
2
|
+
export { useStableAccessToken } from '../chunk-FWZJH3TL.js';
|
|
3
|
+
import '../chunk-NEK6JKPW.js';
|
|
4
|
+
import '../chunk-L2CM2CUA.js';
|
|
5
|
+
import '../chunk-DD3CCMCZ.js';
|
|
6
|
+
import '../chunk-KA7LO7U5.js';
|
|
4
7
|
export { AuthProvider, useAuthContext } from '../chunk-7PLEQFHO.js';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { useInitialization } from './chunk-NEK6JKPW.js';
|
|
2
|
+
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
3
|
+
import { useRef, useEffect } from 'react';
|
|
4
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
5
|
+
import { useNavigate, useLocation } from '@tanstack/react-router';
|
|
6
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function useSessionCheck() {
|
|
9
|
+
const { user } = useAuthContext();
|
|
10
|
+
const queryClient = useQueryClient();
|
|
11
|
+
const isCheckingRef = useRef(false);
|
|
12
|
+
const hadUserRef = useRef(false);
|
|
13
|
+
if (user) {
|
|
14
|
+
hadUserRef.current = true;
|
|
15
|
+
}
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const handleVisibilityChange = async () => {
|
|
18
|
+
if (isCheckingRef.current || document.visibilityState !== "visible") {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
isCheckingRef.current = true;
|
|
22
|
+
try {
|
|
23
|
+
if (!user && hadUserRef.current) {
|
|
24
|
+
window.location.replace("/login");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (user) {
|
|
28
|
+
await queryClient.cancelQueries();
|
|
29
|
+
queryClient.invalidateQueries();
|
|
30
|
+
}
|
|
31
|
+
} finally {
|
|
32
|
+
isCheckingRef.current = false;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
36
|
+
window.addEventListener("focus", handleVisibilityChange);
|
|
37
|
+
return () => {
|
|
38
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
39
|
+
window.removeEventListener("focus", handleVisibilityChange);
|
|
40
|
+
};
|
|
41
|
+
}, [user, queryClient]);
|
|
42
|
+
}
|
|
43
|
+
function ProtectedRoute({
|
|
44
|
+
children,
|
|
45
|
+
redirectTo = "/login",
|
|
46
|
+
fallback = null,
|
|
47
|
+
errorFallback,
|
|
48
|
+
waitForOrganization = true
|
|
49
|
+
}) {
|
|
50
|
+
const { userReady, allReady, isInitializing, error, retry } = useInitialization();
|
|
51
|
+
const { signIn, canRecover } = useAuthContext();
|
|
52
|
+
const navigate = useNavigate();
|
|
53
|
+
const location = useLocation();
|
|
54
|
+
const hasRedirected = useRef(false);
|
|
55
|
+
const unauthenticated = !isInitializing && !userReady && error?.layer !== "profile";
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (unauthenticated && !hasRedirected.current) {
|
|
58
|
+
hasRedirected.current = true;
|
|
59
|
+
const searchStr = location.searchStr ?? "";
|
|
60
|
+
const returnTo = location.pathname + searchStr;
|
|
61
|
+
if (canRecover()) {
|
|
62
|
+
signIn({ state: { returnTo: returnTo !== "/" ? returnTo : void 0 } });
|
|
63
|
+
} else {
|
|
64
|
+
navigate({
|
|
65
|
+
to: redirectTo,
|
|
66
|
+
search: returnTo !== "/" ? { returnTo } : {}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}, [unauthenticated, signIn, canRecover, navigate, redirectTo, location]);
|
|
71
|
+
if (isInitializing) {
|
|
72
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
73
|
+
}
|
|
74
|
+
if (error && error.layer !== "organization") {
|
|
75
|
+
if (errorFallback) {
|
|
76
|
+
return /* @__PURE__ */ jsx(Fragment, { children: errorFallback(error, retry) });
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (unauthenticated) {
|
|
81
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
82
|
+
}
|
|
83
|
+
if (waitForOrganization && !allReady && error?.layer !== "organization") {
|
|
84
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
85
|
+
}
|
|
86
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
87
|
+
}
|
|
88
|
+
function AdminGuard({ children, redirectTo = "/", fallback = null }) {
|
|
89
|
+
const { userReady, profile } = useInitialization();
|
|
90
|
+
const navigate = useNavigate();
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!userReady || !profile) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!profile.is_platform_admin) {
|
|
96
|
+
navigate({ to: redirectTo });
|
|
97
|
+
}
|
|
98
|
+
}, [userReady, profile, navigate, redirectTo]);
|
|
99
|
+
if (!userReady) {
|
|
100
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
101
|
+
}
|
|
102
|
+
if (!profile?.is_platform_admin) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { AdminGuard, ProtectedRoute, useSessionCheck };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// src/utils/error-utils.ts
|
|
2
|
+
var APIClientError = class extends Error {
|
|
3
|
+
statusCode;
|
|
4
|
+
code;
|
|
5
|
+
requestId;
|
|
6
|
+
fields;
|
|
7
|
+
retryAfter;
|
|
8
|
+
constructor(message, code, statusCode, requestId, fields, retryAfter) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "APIClientError";
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.statusCode = statusCode;
|
|
13
|
+
this.requestId = requestId;
|
|
14
|
+
this.fields = fields;
|
|
15
|
+
this.retryAfter = retryAfter;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function isAPIClientError(error) {
|
|
19
|
+
return error instanceof APIClientError;
|
|
20
|
+
}
|
|
21
|
+
function getErrorInfo(error) {
|
|
22
|
+
if (isAPIClientError(error)) {
|
|
23
|
+
return {
|
|
24
|
+
message: error.message,
|
|
25
|
+
code: error.code,
|
|
26
|
+
requestId: error.requestId,
|
|
27
|
+
statusCode: error.statusCode,
|
|
28
|
+
fields: error.fields,
|
|
29
|
+
retryAfter: error.retryAfter
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (error instanceof Error) {
|
|
33
|
+
return {
|
|
34
|
+
message: error.message
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
message: String(error)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function getErrorTitle(code) {
|
|
42
|
+
if (!code) return "Error";
|
|
43
|
+
switch (code) {
|
|
44
|
+
case "VALIDATION_ERROR":
|
|
45
|
+
return "Validation Error";
|
|
46
|
+
case "AUTHENTICATION_FAILED":
|
|
47
|
+
return "Authentication Required";
|
|
48
|
+
case "FORBIDDEN":
|
|
49
|
+
return "Access Denied";
|
|
50
|
+
case "NOT_FOUND":
|
|
51
|
+
return "Not Found";
|
|
52
|
+
case "CONFLICT":
|
|
53
|
+
return "Conflict";
|
|
54
|
+
case "RATE_LIMIT_EXCEEDED":
|
|
55
|
+
return "Rate Limit Exceeded";
|
|
56
|
+
case "INTERNAL_SERVER_ERROR":
|
|
57
|
+
return "Server Error";
|
|
58
|
+
case "SERVICE_UNAVAILABLE":
|
|
59
|
+
return "Service Temporarily Unavailable";
|
|
60
|
+
default:
|
|
61
|
+
return "Error";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function formatErrorMessage(message, requestId, fields, retryAfter) {
|
|
65
|
+
let formatted = message;
|
|
66
|
+
if (fields && Object.keys(fields).length > 0) {
|
|
67
|
+
const fieldErrors = [];
|
|
68
|
+
for (const [field, errors] of Object.entries(fields)) {
|
|
69
|
+
const fieldName = field === "root" || field === "_root" ? "Request" : field;
|
|
70
|
+
errors.forEach((error) => {
|
|
71
|
+
fieldErrors.push(`\u2022 ${fieldName}: ${error}`);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (fieldErrors.length > 0) {
|
|
75
|
+
formatted = fieldErrors.join("\n");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (retryAfter) {
|
|
79
|
+
formatted += `
|
|
80
|
+
|
|
81
|
+
Please wait ${retryAfter} seconds before retrying.`;
|
|
82
|
+
}
|
|
83
|
+
if (requestId) {
|
|
84
|
+
formatted += `
|
|
85
|
+
|
|
86
|
+
Request ID: ${requestId}`;
|
|
87
|
+
}
|
|
88
|
+
return formatted;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { APIClientError, formatErrorMessage, getErrorInfo, getErrorTitle, isAPIClientError };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { OrganizationProvider } from './chunk-UMXDDEAG.js';
|
|
2
|
+
import { ApiClientProvider, useApiClient } from './chunk-XLV6LYN2.js';
|
|
3
|
+
import { NotificationProvider } from './chunk-TIRMFDM4.js';
|
|
4
|
+
import { InitializationProvider } from './chunk-NEK6JKPW.js';
|
|
5
|
+
import { ProfileProvider } from './chunk-L2CM2CUA.js';
|
|
6
|
+
import { useOrganization } from './chunk-DD3CCMCZ.js';
|
|
7
|
+
import { ElevasisServiceProvider, useElevasisServices } from './chunk-KA7LO7U5.js';
|
|
8
|
+
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
9
|
+
import { lazy, Suspense, useRef } from 'react';
|
|
10
|
+
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
11
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
var LazyCoreAuthKitInner = lazy(() => import('./CoreAuthKitInner-3J4RVQO6.js').then((m) => ({ default: m.CoreAuthKitInner })));
|
|
14
|
+
var defaultQueryClient = null;
|
|
15
|
+
function getDefaultQueryClient() {
|
|
16
|
+
if (!defaultQueryClient) {
|
|
17
|
+
defaultQueryClient = new QueryClient({
|
|
18
|
+
defaultOptions: { queries: { retry: 1 } }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return defaultQueryClient;
|
|
22
|
+
}
|
|
23
|
+
function ElevasisCoreProvider({
|
|
24
|
+
auth,
|
|
25
|
+
queryClient,
|
|
26
|
+
apiUrl,
|
|
27
|
+
onError,
|
|
28
|
+
notifications,
|
|
29
|
+
children
|
|
30
|
+
}) {
|
|
31
|
+
if (auth.mode === "apiKey") {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`ElevasisCoreProvider: auth mode 'apiKey' is not yet implemented. Only 'authkit' mode is supported.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const resolvedQueryClient = queryClient ?? getDefaultQueryClient();
|
|
37
|
+
const content = apiUrl ? /* @__PURE__ */ jsx(CoreServiceBridge, { apiUrl, onError, notifications, children }) : children;
|
|
38
|
+
const AuthInner = /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(LazyCoreAuthKitInner, { auth, children: content }) });
|
|
39
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: resolvedQueryClient, children: AuthInner });
|
|
40
|
+
}
|
|
41
|
+
function CoreServiceBridge({
|
|
42
|
+
apiUrl,
|
|
43
|
+
onError,
|
|
44
|
+
notifications,
|
|
45
|
+
children
|
|
46
|
+
}) {
|
|
47
|
+
const { getAccessToken } = useAuthContext();
|
|
48
|
+
const orgIdRef = useRef(null);
|
|
49
|
+
const getOrganizationId = useRef(() => orgIdRef.current).current;
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
ApiClientProvider,
|
|
52
|
+
{
|
|
53
|
+
getAccessToken,
|
|
54
|
+
getOrganizationId,
|
|
55
|
+
isOrganizationReady: false,
|
|
56
|
+
onError,
|
|
57
|
+
children: /* @__PURE__ */ jsx(CoreServiceBridgeInner, { apiUrl, orgIdRef, notifications, children })
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
function CoreServiceBridgeInner({
|
|
62
|
+
apiUrl,
|
|
63
|
+
orgIdRef,
|
|
64
|
+
notifications,
|
|
65
|
+
children
|
|
66
|
+
}) {
|
|
67
|
+
const { apiRequest } = useApiClient(apiUrl);
|
|
68
|
+
return /* @__PURE__ */ jsx(ElevasisServiceProvider, { apiRequest, organizationId: null, isReady: false, children: /* @__PURE__ */ jsx(ProfileProvider, { children: /* @__PURE__ */ jsx(OrganizationProvider, { children: /* @__PURE__ */ jsx(OrgIdBridge, { orgIdRef, children: /* @__PURE__ */ jsx(CoreNotificationLayer, { notifications, children: /* @__PURE__ */ jsx(InitializationProvider, { children }) }) }) }) }) });
|
|
69
|
+
}
|
|
70
|
+
function OrgIdBridge({ orgIdRef, children }) {
|
|
71
|
+
const { currentWorkOSOrganizationId, isInitializing, isOrgRefreshing } = useOrganization();
|
|
72
|
+
const { apiRequest } = useElevasisServices();
|
|
73
|
+
orgIdRef.current = currentWorkOSOrganizationId;
|
|
74
|
+
const isReady = !!currentWorkOSOrganizationId && !isInitializing && !isOrgRefreshing;
|
|
75
|
+
return /* @__PURE__ */ jsx(ElevasisServiceProvider, { apiRequest, organizationId: currentWorkOSOrganizationId, isReady, children });
|
|
76
|
+
}
|
|
77
|
+
function CoreNotificationLayer({
|
|
78
|
+
notifications,
|
|
79
|
+
children
|
|
80
|
+
}) {
|
|
81
|
+
if (notifications) {
|
|
82
|
+
return /* @__PURE__ */ jsx(NotificationProvider, { adapter: notifications, children });
|
|
83
|
+
}
|
|
84
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { ElevasisCoreProvider };
|