@rebasepro/auth 0.0.1-canary.f81da60 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/api.ts","../src/hooks/useRebaseAuthController.ts","../src/hooks/useBackendUserManagement.ts","../src/components/RebaseLoginView.tsx","../src/components/RebaseAuth.tsx","../src/components/AdminViews.tsx"],"sourcesContent":["import { AuthResponse, RefreshResponse, Session, UserInfo } from \"./types\";\n\n/**\n * Default API URL - can be overridden in hook props\n */\nlet baseApiUrl = \"\";\n\n/**\n * Configure the API base URL\n */\nexport function setApiUrl(url: string): void {\n baseApiUrl = url;\n}\n\n/**\n * Get the current API URL\n */\nexport function getApiUrl(): string {\n return baseApiUrl;\n}\n\nclass AuthApiError extends Error {\n code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.code = code;\n this.name = \"AuthApiError\";\n }\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n let data: Record<string, unknown>;\n try {\n data = await response.json();\n } catch (parseError) {\n // Response wasn't JSON - could be network error or server issue\n throw new AuthApiError(\n `Server returned non-JSON response (status: ${response.status})`,\n \"PARSE_ERROR\"\n );\n }\n\n if (!response.ok) {\n throw new AuthApiError(\n (data as Record<string, Record<string, string>>).error?.message || \"Request failed\",\n (data as Record<string, Record<string, string>>).error?.code || \"UNKNOWN_ERROR\"\n );\n }\n\n return data as T;\n}\n\n/**\n * Wrapper for fetch that catches generic network failures (like server down)\n * and translates them to an AuthApiError.\n */\nasync function fetchWithHandling(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n try {\n return await fetch(input, init);\n } catch (error: unknown) {\n if (error instanceof TypeError && error.message.includes(\"Failed to fetch\")) {\n throw new AuthApiError(\n \"Failed to connect to the backend server. The backend might be down or failed to initialize (e.g., database connection timeout).\",\n \"NETWORK_ERROR\"\n );\n }\n throw new AuthApiError(\"Network error: \" + (error instanceof Error ? error.message : String(error)), \"NETWORK_ERROR\");\n }\n}\n\n/**\n * Register a new user with email/password\n */\nexport async function register(\n email: string,\n password: string,\n displayName?: string\n): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email,\npassword,\ndisplayName })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Login with email/password\n */\nexport async function login(email: string, password: string): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/login`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email,\npassword })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Login with Google token (ID token or access token)\n */\nexport async function googleLogin(token: string, tokenType: \"idToken\" | \"accessToken\" = \"idToken\"): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/google`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ [tokenType]: token })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Login with LinkedIn OAuth code\n */\nexport async function linkedinLogin(code: string, redirectUri: string): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/linkedin`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ code,\nredirectUri })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Generic OAuth login — works with any provider registered on the backend.\n * The `providerId` is used to build the endpoint: `/api/auth/{providerId}`.\n */\nexport async function oauthLogin(providerId: string, payload: Record<string, unknown>): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/${providerId}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload)\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<RefreshResponse> {\n console.log(\"[AUTH-API] Calling refresh endpoint...\");\n\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken })\n });\n\n console.log(\"[AUTH-API] Refresh response status:\", response.status);\n return handleResponse<RefreshResponse>(response);\n}\n\n/**\n * Logout and invalidate refresh token\n */\nexport async function logout(refreshToken?: string): Promise<void> {\n await fetchWithHandling(`${baseApiUrl}/api/auth/logout`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken })\n });\n}\n\n/**\n * Get current user info\n */\nexport async function getCurrentUser(accessToken: string): Promise<{ user: UserInfo }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/me`, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ user: UserInfo }>(response);\n}\n\n/**\n * Request password reset email\n */\nexport async function forgotPassword(email: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/forgot-password`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Reset password using token from email\n */\nexport async function resetPassword(token: string, password: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/reset-password`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token,\npassword })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Change password for authenticated user\n */\nexport async function changePassword(\n accessToken: string,\n oldPassword: string,\n newPassword: string\n): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/change-password`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n },\n body: JSON.stringify({ oldPassword,\nnewPassword })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Send email verification link\n */\nexport async function sendVerificationEmail(accessToken: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/send-verification`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Verify email address using token\n */\nexport async function verifyEmail(token: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/verify-email?token=${encodeURIComponent(token)}`, {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Update current user profile\n */\nexport async function updateProfile(\n accessToken: string,\n displayName?: string,\n photoURL?: string\n): Promise<{ user: UserInfo }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/me`, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n },\n body: JSON.stringify({ displayName,\nphotoURL })\n });\n\n return handleResponse<{ user: UserInfo }>(response);\n}\n\n/**\n * Fetch active sessions for current user\n */\nexport async function fetchSessions(accessToken: string, currentRefreshToken?: string): Promise<{ sessions: Session[] }> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n };\n if (currentRefreshToken) {\n headers[\"X-Refresh-Token\"] = currentRefreshToken;\n }\n\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions`, {\n method: \"GET\",\n headers\n });\n\n return handleResponse<{ sessions: Session[] }>(response);\n}\n\n/**\n * Revoke a specific session\n */\nexport async function revokeSession(accessToken: string, sessionId: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions/${sessionId}`, {\n method: \"DELETE\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Revoke all sessions for current user\n */\nexport async function revokeAllSessions(accessToken: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions`, {\n method: \"DELETE\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Auth config response from the backend\n */\nexport interface AuthConfigResponse {\n /** True when there are no users in the system and first user setup is needed */\n needsSetup: boolean;\n /** Whether new user registration is enabled */\n registrationEnabled: boolean;\n /** Whether Google OAuth is configured */\n googleEnabled: boolean;\n /** Whether LinkedIn OAuth is configured */\n linkedinEnabled: boolean;\n /** Whether email service is configured */\n emailServiceEnabled: boolean;\n /** Complete list of enabled OAuth provider IDs (e.g. [\"google\", \"github\", \"discord\"]) */\n enabledProviders?: string[];\n}\n\n/**\n * Fetch auth configuration / status from the backend\n * This is an unauthenticated endpoint used to detect bootstrap mode\n */\nexport async function fetchAuthConfig(): Promise<AuthConfigResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/config`, {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n\n return handleResponse<AuthConfigResponse>(response);\n}\n\nexport { AuthApiError };\n\n","import { useCallback, useEffect, useState, useRef } from \"react\";\nimport { User } from \"@rebasepro/types\";\nimport * as authApi from \"../api\";\nimport { AuthConfigResponse } from \"../api\";\nimport {\n RebaseAuthController,\n RebaseAuthControllerProps,\n AuthTokens,\n UserInfo\n} from \"../types\";\n\nconst STORAGE_KEY = \"rebase_auth\";\n\n// Buffer time before expiry to trigger refresh (2 minutes)\nconst TOKEN_REFRESH_BUFFER_MS = 2 * 60 * 1000;\n\n/**\n * Convert UserInfo from API to Rebase User type\n */\nfunction convertToUser(userInfo: UserInfo): User {\n return {\n uid: userInfo.uid,\n email: userInfo.email,\n displayName: userInfo.displayName || null,\n photoURL: userInfo.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: userInfo.roles || []\n };\n}\n\n/**\n * Storage data structure\n */\ninterface StoredAuthData {\n tokens: AuthTokens;\n user: UserInfo;\n}\n\n/**\n * Save auth data to localStorage\n */\nfunction saveAuthToStorage(tokens: AuthTokens, user: UserInfo): void {\n try {\n const data: StoredAuthData = { tokens,\nuser };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n const expiryDate = new Date(tokens.accessTokenExpiresAt);\n const expiryStr = Number.isFinite(tokens.accessTokenExpiresAt) ? expiryDate.toISOString() : \"invalid\";\n } catch (e) { /* ignore */ }\n}\n\n/**\n * Load auth data from localStorage\n */\nfunction loadAuthFromStorage(): StoredAuthData | null {\n try {\n const data = localStorage.getItem(STORAGE_KEY);\n if (data) {\n const parsed = JSON.parse(data);\n return parsed;\n }\n } catch (e) {\n console.warn(\"Failed to load auth from storage:\", e);\n }\n return null;\n}\n\n/**\n * Clear auth data from localStorage\n */\nfunction clearAuthFromStorage(): void {\n try {\n localStorage.removeItem(STORAGE_KEY);\n } catch (e) {\n console.warn(\"Failed to clear auth from storage:\", e);\n }\n}\n\n/**\n * Check if token is expired or about to expire\n */\nfunction isTokenExpiredOrNearExpiry(expiresAt: number, bufferMs: number = TOKEN_REFRESH_BUFFER_MS): boolean {\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Auth controller hook for JWT-based authentication\n * with @rebasepro/server-core\n *\n * @param props Configuration options\n * @returns RebaseAuthController instance\n */\nexport function useRebaseAuthController(\n props: RebaseAuthControllerProps = {}\n): RebaseAuthController {\n const { client, apiUrl, onSignOut, defineRolesFor } = props;\n\n const [user, setUser] = useState<User | null>(null);\n const [authLoading, setAuthLoading] = useState(false);\n const [initialLoading, setInitialLoading] = useState(true);\n const [authError, setAuthError] = useState<Error | null>(null);\n const [authProviderError, setAuthProviderError] = useState<Error | null>(null);\n const [loginSkipped, setLoginSkipped] = useState(false);\n const [extra, setExtra] = useState<unknown>(null);\n const [authConfig, setAuthConfig] = useState<AuthConfigResponse | null>(null);\n\n // Store tokens in ref for quick access, but also persist to localStorage\n const tokensRef = useRef<AuthTokens | null>(null);\n const refreshTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Track if a refresh is currently in progress to avoid concurrent refreshes\n const refreshPromiseRef = useRef<Promise<AuthTokens | null> | null>(null);\n // Track if component is mounted\n const isMountedRef = useRef(true);\n\n // Configure API URL on mount\n useEffect(() => {\n if (client) {\n authApi.setApiUrl(client.baseUrl);\n } else if (apiUrl) {\n authApi.setApiUrl(apiUrl);\n }\n }, [client, apiUrl]);\n\n // Clear session and sign out\n const clearSessionAndSignOut = useCallback(() => {\n tokensRef.current = null;\n clearAuthFromStorage();\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n refreshTimeoutRef.current = null;\n }\n setUser(null);\n setLoginSkipped(false);\n onSignOut?.();\n }, [onSignOut]);\n\n /**\n * Refresh the access token using the stored refresh token.\n * Returns the new tokens or null if refresh failed.\n */\n const refreshAccessToken = useCallback(async (): Promise<AuthTokens | null> => {\n // Prevent concurrent refreshes\n if (refreshPromiseRef.current) {\n // Wait for the current refresh to complete\n return refreshPromiseRef.current;\n }\n\n const executeRefresh = async (): Promise<AuthTokens | null> => {\n // Check if another tab has already refreshed the token\n const storedData = loadAuthFromStorage();\n if (storedData?.tokens?.accessTokenExpiresAt) {\n const storedTokens = storedData.tokens;\n // If stored token is newer and not expired\n if (!isTokenExpiredOrNearExpiry(storedTokens.accessTokenExpiresAt) && storedTokens.accessToken !== tokensRef.current?.accessToken) {\n tokensRef.current = storedTokens;\n return storedTokens;\n }\n }\n\n const currentTokens = tokensRef.current;\n if (!currentTokens?.refreshToken) {\n return null;\n }\n\n\n try {\n const response = await authApi.refreshAccessToken(currentTokens.refreshToken);\n const newTokens = response.tokens;\n\n // Update tokens immediately\n tokensRef.current = newTokens;\n\n // Persist to storage\n const latestStoredData = loadAuthFromStorage();\n if (latestStoredData) {\n saveAuthToStorage(newTokens, latestStoredData.user);\n }\n\n const newExpiryStr = Number.isFinite(newTokens.accessTokenExpiresAt) ? new Date(newTokens.accessTokenExpiresAt).toISOString() : \"invalid\";\n return newTokens;\n } catch (error: unknown) {\n\n // If it's a network error (e.g., backend restarting), we throw so callers can retry\n // instead of immediately assuming the refresh token is invalid and signing out.\n if (error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\") {\n throw error;\n }\n return null;\n } finally {\n refreshPromiseRef.current = null;\n }\n };\n\n refreshPromiseRef.current = executeRefresh();\n return refreshPromiseRef.current;\n }, []);\n\n // Schedule token refresh before expiry\n const scheduleTokenRefresh = useCallback((tokens: AuthTokens) => {\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n }\n\n // Calculate when to refresh (2 minutes before expiry)\n const expiresAt = tokens.accessTokenExpiresAt;\n const refreshAt = expiresAt - TOKEN_REFRESH_BUFFER_MS;\n const timeUntilRefresh = refreshAt - Date.now();\n\n if (timeUntilRefresh <= 0) {\n // Token already expired or about to expire - refresh now\n refreshAccessToken().then(newTokens => {\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n });\n return;\n }\n\n\n refreshTimeoutRef.current = setTimeout(async () => {\n if (!isMountedRef.current) return;\n\n try {\n const newTokens = await refreshAccessToken();\n\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n } catch (error) {\n // Network error - try again shortly instead of logging out\n if (isMountedRef.current) {\n refreshTimeoutRef.current = setTimeout(() => {\n scheduleTokenRefresh(tokens);\n }, 10000);\n }\n }\n }, timeUntilRefresh);\n }, [refreshAccessToken, clearSessionAndSignOut]);\n\n // Get auth token for API requests (with automatic refresh if needed)\n const getAuthToken = useCallback(async (): Promise<string> => {\n // If still loading, throw - the UI should show a spinner\n if (initialLoading) {\n throw new Error(\"Auth is still loading\");\n }\n\n const currentTokens = tokensRef.current;\n if (!currentTokens) {\n throw new Error(\"User is not logged in\");\n }\n\n // Check if token is expired or about to expire\n if (isTokenExpiredOrNearExpiry(currentTokens.accessTokenExpiresAt)) {\n try {\n const newTokens = await refreshAccessToken();\n if (!newTokens) {\n clearSessionAndSignOut();\n throw new Error(\"Session expired. Please login again.\");\n }\n return newTokens.accessToken;\n } catch (error: unknown) {\n // If the error was a network error during refresh, just re-throw it\n // so the user isn't logged out locally and the network request fails naturally.\n if (error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\") {\n throw error;\n }\n clearSessionAndSignOut();\n throw error;\n }\n }\n\n return currentTokens.accessToken;\n }, [initialLoading, refreshAccessToken, clearSessionAndSignOut]);\n\n // Install token getter onto client\n useEffect(() => {\n if (client) {\n client.setAuthTokenGetter(async () => {\n try { return await getAuthToken(); } catch { return null; }\n });\n if (client.setOnUnauthorized) {\n client.setOnUnauthorized(async () => {\n try {\n const newTokens = await refreshAccessToken();\n if (newTokens) return true;\n clearSessionAndSignOut();\n return false;\n } catch (e) {\n clearSessionAndSignOut();\n return false;\n }\n });\n }\n if (client.ws) {\n client.ws.setAuthTokenGetter(async () => {\n return await getAuthToken();\n });\n }\n }\n }, [client, getAuthToken, refreshAccessToken, clearSessionAndSignOut]);\n\n // Handle successful authentication\n const handleAuthSuccess = useCallback(async (userInfo: UserInfo, tokens: AuthTokens) => {\n tokensRef.current = tokens;\n let convertedUser = convertToUser(userInfo);\n\n // Apply custom roles if defineRolesFor provided\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(convertedUser);\n if (customRoles) {\n convertedUser = { ...convertedUser,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n // Save to localStorage for persistence\n saveAuthToStorage(tokens, userInfo);\n\n setUser(convertedUser);\n setAuthError(null);\n setAuthProviderError(null);\n setLoginSkipped(false);\n scheduleTokenRefresh(tokens);\n }, [scheduleTokenRefresh, defineRolesFor]);\n\n // Email/password login\n const emailPasswordLogin = useCallback(async (email: string, password: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.login(email, password);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Register new user\n const register = useCallback(async (email: string, password: string, displayName?: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.register(email, password, displayName);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Google login with ID token or access token\n const googleLogin = useCallback(async (token: string, tokenType: \"idToken\" | \"accessToken\" = \"idToken\") => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.googleLogin(token, tokenType);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Generic OAuth login — works with any provider registered on the backend\n const oauthLogin = useCallback(async (providerId: string, payload: Record<string, unknown>) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.oauthLogin(providerId, payload);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Sign out\n const signOut = useCallback(async () => {\n try {\n if (tokensRef.current) {\n await authApi.logout(tokensRef.current.refreshToken);\n }\n } catch (error) {\n console.error(\"Logout error:\", error);\n } finally {\n clearSessionAndSignOut();\n }\n }, [clearSessionAndSignOut]);\n\n // Skip login\n const skipLogin = useCallback(() => {\n setLoginSkipped(true);\n setUser(null);\n }, []);\n\n // Forgot password - request reset email\n const forgotPassword = useCallback(async (email: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n await authApi.forgotPassword(email);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, []);\n\n // Reset password using token\n const resetPassword = useCallback(async (token: string, password: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n await authApi.resetPassword(token, password);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, []);\n\n // Change password for authenticated user\n const changePassword = useCallback(async (oldPassword: string, newPassword: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.changePassword(tokensRef.current.accessToken, oldPassword, newPassword);\n // After password change, user needs to log in again (all sessions invalidated)\n clearSessionAndSignOut();\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [clearSessionAndSignOut]);\n\n // Update user profile\n const updateProfile = useCallback(async (displayName?: string, photoURL?: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n const response = await authApi.updateProfile(tokensRef.current.accessToken, displayName, photoURL);\n\n // Update local user state\n let convertedUser = convertToUser(response.user);\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(convertedUser);\n if (customRoles) {\n convertedUser = { ...convertedUser,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n // Update storage\n const storedData = loadAuthFromStorage();\n if (storedData) {\n saveAuthToStorage(storedData.tokens, response.user);\n }\n\n setUser(convertedUser);\n return convertedUser;\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [defineRolesFor]);\n\n // Fetch active sessions\n const fetchSessions = useCallback(async () => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n const response = await authApi.fetchSessions(tokensRef.current.accessToken, tokensRef.current.refreshToken);\n return response.sessions;\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, []);\n\n // Revoke a session\n const revokeSession = useCallback(async (sessionId: string) => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.revokeSession(tokensRef.current.accessToken, sessionId);\n // If the revoked session is the current one, the next API request will fail with 401\n // and trigger an auto-logout. Otherwise, it just removes it from the DB.\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, []);\n\n // Restore auth state from localStorage on mount\n useEffect(() => {\n isMountedRef.current = true;\n\n const restoreAuth = async () => {\n\n // Fetch auth config (needsSetup, registrationEnabled, etc.)\n try {\n const config = await authApi.fetchAuthConfig();\n if (isMountedRef.current) {\n setAuthConfig(config);\n }\n } catch (e) { /* ignore */ }\n\n const stored = loadAuthFromStorage();\n\n if (!stored) {\n setInitialLoading(false);\n return;\n }\n\n if (!stored.tokens?.refreshToken) {\n clearAuthFromStorage();\n setInitialLoading(false);\n return;\n }\n\n\n // Validate accessTokenExpiresAt is a valid number\n const expiresAt = stored.tokens.accessTokenExpiresAt;\n if (typeof expiresAt !== \"number\" || !Number.isFinite(expiresAt)) {\n clearAuthFromStorage();\n setInitialLoading(false);\n return;\n }\n\n\n // Check if access token is still valid\n if (!isTokenExpiredOrNearExpiry(stored.tokens.accessTokenExpiresAt)) {\n // Token is still valid - use it directly\n tokensRef.current = stored.tokens;\n\n let userToSet = convertToUser(stored.user);\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(userToSet);\n if (customRoles) {\n userToSet = { ...userToSet,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n setUser(userToSet);\n scheduleTokenRefresh(stored.tokens);\n setInitialLoading(false);\n return;\n }\n\n // Token is expired or near expiry - refresh it\n tokensRef.current = stored.tokens; // Set so refreshAccessToken can use it\n\n try {\n const newTokens = await refreshAccessToken();\n\n if (!newTokens) {\n clearAuthFromStorage();\n tokensRef.current = null;\n setInitialLoading(false);\n return;\n }\n\n if (!isMountedRef.current) return;\n\n // Fetch fresh user data from the server\n let userToSet: User;\n try {\n const meResponse = await authApi.getCurrentUser(newTokens.accessToken);\n\n if (!isMountedRef.current) return;\n\n const freshUserInfo = meResponse.user;\n\n // Update stored data with fresh user info\n saveAuthToStorage(newTokens, freshUserInfo);\n\n userToSet = convertToUser(freshUserInfo);\n\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(userToSet);\n if (!isMountedRef.current) return;\n if (customRoles) {\n userToSet = { ...userToSet,\nroles: customRoles.map(r => r.id) };\n }\n }\n } catch (meError: unknown) {\n if (!isMountedRef.current) return;\n userToSet = convertToUser(stored.user);\n }\n\n if (!isMountedRef.current) return;\n\n setUser(userToSet);\n scheduleTokenRefresh(newTokens);\n } catch (error: unknown) {\n if (!isMountedRef.current) return;\n\n // Do not clear the session entirely if it's just a temporary network outage\n if (!(error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\")) {\n clearAuthFromStorage();\n tokensRef.current = null;\n }\n } finally {\n if (isMountedRef.current) {\n setInitialLoading(false);\n }\n }\n };\n\n restoreAuth();\n\n return () => {\n isMountedRef.current = false;\n };\n }, [scheduleTokenRefresh, defineRolesFor, refreshAccessToken]);\n\n // Handle visibility change - refresh token when user returns to tab\n useEffect(() => {\n const handleVisibilityChange = async () => {\n if (initialLoading) return;\n\n if (document.visibilityState === \"visible\" && tokensRef.current) {\n // Check if token needs refreshing\n if (isTokenExpiredOrNearExpiry(tokensRef.current.accessTokenExpiresAt)) {\n try {\n const newTokens = await refreshAccessToken();\n\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n } catch (e) { /* ignore */ }\n }\n }\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [initialLoading, refreshAccessToken, scheduleTokenRefresh, clearSessionAndSignOut]);\n\n\n // Get currently configured API URL\n const getApiUrl = useCallback(() => {\n return authApi.getApiUrl();\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n }\n };\n }, []);\n\n // Revoke all sessions\n const revokeAllSessions = useCallback(async () => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.revokeAllSessions(tokensRef.current.accessToken);\n clearSessionAndSignOut();\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, [clearSessionAndSignOut]);\n\n return {\n user,\n authLoading,\n initialLoading,\n authError,\n authProviderError,\n loginSkipped,\n needsSetup: authConfig?.needsSetup ?? false,\n registrationEnabled: authConfig?.registrationEnabled ?? false,\n getAuthToken,\n getApiUrl,\n signOut,\n emailPasswordLogin,\n register,\n googleLogin,\n oauthLogin,\n skipLogin,\n forgotPassword,\n resetPassword,\n changePassword,\n updateProfile,\n fetchSessions,\n revokeSession,\n revokeAllSessions,\n extra,\n setExtra,\n capabilities: {\n emailPasswordLogin: true,\n googleLogin: !!(props.googleClientId),\n registration: authConfig?.registrationEnabled ?? false,\n passwordReset: true,\n sessionManagement: true,\n profileUpdate: true,\n emailVerification: false,\n enabledProviders: authConfig?.enabledProviders ?? []\n }\n };\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { Role, User } from \"@rebasepro/types\";\n\n/**\n * UserManagement interface - compatible with @rebasepro/user_management\n * Defined inline to avoid dependency on that package\n */\nexport interface UserManagement<USER extends User = User> {\n loading: boolean;\n\n users: USER[];\n saveUser: (user: USER) => Promise<USER>;\n createUser?: (user: USER) => Promise<{\n user: USER;\n invitationSent: boolean;\n temporaryPassword?: string;\n }>;\n resetPassword?: (user: USER) => Promise<{\n user: USER;\n invitationSent: boolean;\n temporaryPassword?: string;\n }>;\n deleteUser: (user: USER) => Promise<void>;\n\n roles: Role[];\n saveRole: (role: Role) => Promise<void>;\n deleteRole: (role: Role) => Promise<void>;\n\n isAdmin?: boolean;\n allowDefaultRolesCreation?: boolean;\n includeCollectionConfigPermissions?: boolean;\n defineRolesFor: (user: User) => Promise<Role[] | undefined> | Role[] | undefined;\n getUser: (uid: string) => User | null;\n\n /**\n * Search users with server-side pagination.\n * When provided, the CMS will use this for the users table\n * instead of loading all users into memory.\n */\n searchUsers?: (options: {\n search?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n orderDir?: \"asc\" | \"desc\";\n roleId?: string;\n }) => Promise<{ users: USER[]; total: number }>;\n\n usersError?: Error;\n rolesError?: Error;\n bootstrapAdmin?: () => Promise<void>;\n}\n\nexport interface BackendUserManagementConfig {\n /**\n * The Rebase Client instance\n */\n client?: any;\n\n /**\n * Base API URL for the backend (optional, extracted from client if not provided)\n */\n apiUrl?: string;\n\n /**\n * Function to get the current auth token (optional, extracted from client if not provided)\n */\n getAuthToken?: () => Promise<string>;\n\n /**\n * Current logged-in user\n */\n currentUser?: User | null;\n}\n\ninterface ApiUser {\n uid: string;\n email: string;\n displayName?: string | null;\n photoURL?: string | null;\n roles: string[];\n createdAt?: string;\n updatedAt?: string;\n}\n\ninterface ApiRole {\n id: string;\n name: string;\n isAdmin?: boolean;\n config?: Record<string, any>;\n}\n\n/**\n * Convert API user to Rebase User\n * @param apiUser - The API user object\n * @param availableRoles - Optional array of available roles to look up names\n */\nfunction convertUser(apiUser: ApiUser): User {\n return {\n uid: apiUser.uid,\n email: apiUser.email,\n displayName: apiUser.displayName || null,\n photoURL: apiUser.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: apiUser.roles,\n createdAt: apiUser.createdAt ? new Date(apiUser.createdAt) : null\n } as User;\n}\n\n/**\n * Convert API role to Rebase Role\n */\nfunction convertRole(apiRole: ApiRole): Role {\n return {\n id: apiRole.id,\n name: apiRole.name,\n isAdmin: apiRole.isAdmin ?? false,\n config: apiRole.config ?? undefined\n };\n}\n\n/**\n * Hook to manage users and roles via backend API\n * Compatible with Rebase UserManagement interface\n */\nexport function useBackendUserManagement(config: BackendUserManagementConfig): UserManagement {\n const { client, apiUrl, getAuthToken, currentUser } = config;\n\n // We no longer load ALL users into memory.\n // `users` now only holds admin/role-bearing users for getUser/defineRolesFor lookups.\n const [users, setUsers] = useState<User[]>([]);\n const [roles, setRoles] = useState<Role[]>([]);\n const [loading, setLoading] = useState(true);\n const [usersError, setUsersError] = useState<Error | undefined>();\n const [rolesError, setRolesError] = useState<Error | undefined>();\n\n /**\n * Make authenticated API request\n */\n const apiRequest = useCallback(async (\n endpoint: string,\n method = \"GET\",\n body?: Record<string, unknown>,\n retryCount = 6,\n signal?: AbortSignal\n ): Promise<any> => {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < retryCount; attempt++) {\n if (signal?.aborted) {\n const error = new Error(\"Request aborted\");\n error.name = \"AbortError\";\n throw error;\n }\n\n try {\n // Determine token provider\n const token = getAuthToken ? await getAuthToken() : (client ? await client.resolveToken() : null);\n const baseUrl = apiUrl || (client?.baseUrl ? client.baseUrl : \"\");\n\n // Use /api/admin prefix for admin endpoints\n const response = await fetch(`${baseUrl}/api/admin${endpoint}`, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { \"Authorization\": `Bearer ${token}` } : {})\n },\n body: body ? JSON.stringify(body) : undefined,\n signal\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage = \"API request failed\";\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error?.message || errorMessage;\n } catch (e) {\n errorMessage = errorText || `HTTP error ${response.status}`;\n }\n\n const error = Object.assign(new Error(errorMessage), { status: response.status });\n throw error;\n }\n\n return await response.json();\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\" || signal?.aborted) {\n throw error;\n }\n\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Retry conditions: Network errors (TypeError) OR 5xx Server Errors (Backend rebooting)\n const isNetworkError = error instanceof TypeError;\n const isServerError = typeof (error as { status?: number }).status === \"number\" && (error as { status: number }).status >= 500 && (error as { status: number }).status < 600;\n\n if (attempt < retryCount - 1 && (isNetworkError || isServerError)) {\n const delay = Math.min(1000 * Math.pow(2, attempt), 5000); // 1s, 2s, 4s...\n console.warn(`Admin API request to ${endpoint} failed, retrying in ${delay}ms...`);\n\n // Wait for delay or abort\n await new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(new Error(\"AbortError\"));\n const timer = setTimeout(resolve, delay);\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n clearTimeout(timer);\n reject(new Error(\"AbortError\"));\n }, { once: true });\n }\n }).catch(() => {}); // Catch AbortError from wait\n\n if (signal?.aborted) {\n const abortError = new Error(\"Request aborted\");\n abortError.name = \"AbortError\";\n throw abortError;\n }\n continue;\n }\n\n console.error(\"Admin API error after retries:\", error);\n throw error;\n }\n }\n throw lastError;\n }, [apiUrl, getAuthToken]);\n\n /**\n * Load roles from API\n */\n const loadRoles = useCallback(async (signal?: AbortSignal) => {\n try {\n const data = await apiRequest(\"/roles\", \"GET\", undefined, 6, signal);\n setRoles(data.roles.map(convertRole));\n setRolesError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load roles:\", error);\n setRolesError(error instanceof Error ? error : new Error(String(error)));\n }\n }, [apiRequest]);\n\n /**\n * Load users for getUser/defineRolesFor lookups and for UserSelect dropdowns.\n */\n const loadUsers = useCallback(async (signal?: AbortSignal) => {\n try {\n // Load all users to satisfy Rebase CMS UserSelect field bindings\n const data = await apiRequest(\"/users\", \"GET\", undefined, 6, signal);\n const allUsers: User[] = data.users.map((u: ApiUser) => convertUser(u));\n setUsers(allUsers);\n setUsersError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load users:\", error);\n setUsersError(error instanceof Error ? error : new Error(String(error)));\n }\n }, [apiRequest]);\n\n /**\n * Initial data load - only when user is logged in\n * Load roles first, then admin users\n */\n useEffect(() => {\n // Don't load if no user is logged in\n if (!currentUser) {\n setLoading(false);\n return;\n }\n\n const abortController = new AbortController();\n\n const load = async () => {\n setLoading(true);\n // Load roles first\n try {\n const data = await apiRequest(\"/roles\", \"GET\", undefined, 6, abortController.signal);\n setRoles(data.roles.map(convertRole));\n setRolesError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name !== \"AbortError\") {\n console.error(\"Failed to load roles:\", error);\n setRolesError(error);\n }\n }\n // Then load all users if not aborted\n if (!abortController.signal.aborted) {\n await loadUsers(abortController.signal);\n }\n\n if (!abortController.signal.aborted) {\n setLoading(false);\n }\n };\n load();\n\n return () => {\n abortController.abort();\n };\n }, [currentUser, apiRequest, loadUsers]);\n\n /**\n * Search users with server-side pagination.\n * This is the primary method used by the UsersView table.\n */\n const searchUsers = useCallback(async (options: {\n search?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n orderDir?: \"asc\" | \"desc\";\n roleId?: string;\n }): Promise<{ users: User[]; total: number }> => {\n const params = new URLSearchParams();\n if (options.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options.offset !== undefined) params.set(\"offset\", String(options.offset));\n if (options.search) params.set(\"search\", options.search);\n if (options.orderBy) params.set(\"orderBy\", options.orderBy);\n if (options.orderDir) params.set(\"orderDir\", options.orderDir);\n if (options.roleId) params.set(\"role\", options.roleId);\n const qs = params.toString();\n\n const data = await apiRequest(\"/users\" + (qs ? \"?\" + qs : \"\"), \"GET\");\n return {\n users: data.users.map((u: ApiUser) => convertUser(u)),\n total: data.total\n };\n }, [apiRequest]);\n\n /**\n * Save user (create or update)\n */\n const saveUser = useCallback(async (user: User): Promise<User> => {\n const roleIds = user.roles ?? [];\n\n // Check if user exists\n const existingUser = users.find(u => u.uid === user.uid);\n\n if (existingUser) {\n // Update\n const data = await apiRequest(`/users/${user.uid}`, \"PUT\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const updated = convertUser(data.user);\n setUsers(prev => prev.map(u => u.uid === updated.uid ? updated : u));\n return updated;\n } else {\n // Create\n const data = await apiRequest(\"/users\", \"POST\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const created = convertUser(data.user);\n setUsers(prev => [...prev, created]);\n return created;\n }\n }, [apiRequest, users, roles]);\n\n /**\n * Create a new user with invitation/password generation support.\n * Returns additional info about how credentials were delivered.\n */\n const createUser = useCallback(async (user: User): Promise<{\n user: User;\n invitationSent: boolean;\n temporaryPassword?: string;\n }> => {\n const roleIds = user.roles ?? [];\n\n const data = await apiRequest(\"/users\", \"POST\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const created = convertUser(data.user);\n // Add to users cache\n setUsers(prev => [...prev, created]);\n return {\n user: created,\n invitationSent: data.invitationSent ?? false,\n temporaryPassword: data.temporaryPassword\n };\n }, [apiRequest, roles]);\n\n /**\n * Reset the password for an existing user\n */\n const resetPassword = useCallback(async (user: User): Promise<{\n user: User;\n invitationSent: boolean;\n temporaryPassword?: string;\n }> => {\n const data = await apiRequest(`/users/${user.uid}/reset-password`, \"POST\");\n const updatedUser = convertUser(data.user);\n setUsers(prev => prev.map(u => u.uid === updatedUser.uid ? updatedUser : u));\n return {\n user: updatedUser,\n invitationSent: data.invitationSent ?? false,\n temporaryPassword: data.temporaryPassword\n };\n }, [apiRequest]);\n\n /**\n * Delete user\n */\n const deleteUser = useCallback(async (user: User): Promise<void> => {\n await apiRequest(`/users/${user.uid}`, \"DELETE\");\n setUsers(prev => prev.filter(u => u.uid !== user.uid));\n }, [apiRequest]);\n\n /**\n * Save role (create or update)\n */\n const saveRole = useCallback(async (role: Role): Promise<void> => {\n // Check if role exists\n const existingRole = roles.find(r => r.id === role.id);\n\n if (existingRole) {\n // Update\n const data = await apiRequest(`/roles/${role.id}`, \"PUT\", {\n name: role.name,\n isAdmin: role.isAdmin,\n config: role.config\n });\n const updated = convertRole(data.role);\n setRoles(prev => prev.map(r => r.id === updated.id ? updated : r));\n } else {\n // Create\n const data = await apiRequest(\"/roles\", \"POST\", {\n id: role.id,\n name: role.name,\n isAdmin: role.isAdmin ?? false,\n config: role.config\n });\n const created = convertRole(data.role);\n setRoles(prev => [...prev, created]);\n }\n }, [apiRequest, roles]);\n\n /**\n * Delete role\n */\n const deleteRole = useCallback(async (role: Role): Promise<void> => {\n await apiRequest(`/roles/${role.id}`, \"DELETE\");\n setRoles(prev => prev.filter(r => r.id !== role.id));\n }, [apiRequest]);\n\n /**\n * Get user by uid\n */\n const getUser = useCallback((uid: string): User | null => {\n return users.find(u => u.uid === uid) ?? null;\n }, [users]);\n\n /**\n * Define roles for a given user (for authController)\n */\n const defineRolesFor = useCallback(async (user: User): Promise<Role[] | undefined> => {\n // Find the user in our list\n const existingUser = users.find(u => u.uid === user.uid || u.email === user.email);\n if (!existingUser) return undefined;\n\n // Return roles from our cached role data (string IDs → full Role objects)\n const userRoleIds = existingUser.roles ?? [];\n return roles.filter(r => userRoleIds.includes(r.id));\n }, [users, roles]);\n\n /**\n * Check if current user is admin\n */\n const isAdmin = currentUser?.roles?.includes(\"admin\") ?? false;\n\n\n /**\n * Bootstrap default admin\n */\n const bootstrapAdmin = useCallback(async (): Promise<void> => {\n try {\n await apiRequest(\"/bootstrap\", \"POST\");\n // Reload users and roles after successful bootstrap\n const data = await apiRequest(\"/roles\");\n const loadedRoles = data.roles.map(convertRole);\n setRoles(loadedRoles);\n await loadUsers();\n } catch (error) {\n console.error(\"Failed to bootstrap admin:\", error);\n throw error;\n }\n }, [apiRequest, loadUsers]);\n\n return {\n loading,\n users,\n saveUser,\n createUser,\n resetPassword,\n deleteUser,\n roles,\n saveRole,\n deleteRole,\n isAdmin,\n allowDefaultRolesCreation: true,\n includeCollectionConfigPermissions: true,\n defineRolesFor,\n getUser,\n searchUsers,\n usersError,\n rolesError,\n bootstrapAdmin\n };\n}\n","\nimport React, { ReactNode, useEffect, useRef, useState } from \"react\";\n\nimport { Button, CircularProgress, cls, IconButton, LoadingButton, Menu, MenuItem, TextField, Typography, iconSize } from \"@rebasepro/ui\";\nimport { ArrowLeftIcon, MailIcon, MoonIcon, SunIcon, SunMoonIcon } from \"lucide-react\";\nimport { ErrorView, LanguageToggle, RebaseLogo, useModeController, useTranslation } from \"@rebasepro/core\";\n\nimport { RebaseAuthController } from \"../types\";\n\n/**\n * Props for RebaseLoginView\n */\nexport interface RebaseLoginViewProps {\n /**\n * Auth controller from useRebaseAuthController\n */\n authController: RebaseAuthController;\n\n /**\n * Path to the logo displayed in the login screen\n */\n logo?: string;\n\n /**\n * Enable the skip login button\n */\n allowSkipLogin?: boolean;\n\n /**\n * Disable the login buttons\n */\n disabled?: boolean;\n\n /**\n * Prevent users from creating new accounts\n */\n disableSignupScreen?: boolean;\n\n /**\n * Display this component when no user is found\n */\n noUserComponent?: ReactNode;\n\n /**\n * Display this component below the sign-in buttons\n */\n additionalComponent?: ReactNode;\n\n /**\n * Error message when user is not allowed access\n */\n notAllowedError?: string | Error;\n\n /**\n * Enable Google login button (requires googleClientId in hook)\n */\n googleEnabled?: boolean;\n\n /**\n * Google client ID for OAuth\n */\n googleClientId?: string;\n}\n\ntype AuthMode = \"buttons\" | \"login\" | \"register\" | \"forgot\";\n\n/**\n * Login view component for custom JWT authentication\n */\nexport function RebaseLoginView({\n logo,\n authController,\n noUserComponent,\n disableSignupScreen = false,\n disabled = false,\n notAllowedError,\n googleEnabled = false,\n googleClientId\n}: RebaseLoginViewProps) {\n\n const modeState = useModeController();\n const { mode: colorMode, setMode: setColorMode } = modeState;\n const { t } = useTranslation();\n\n const [mode, setMode] = useState<AuthMode>(\"buttons\");\n const [fadeIn, setFadeIn] = useState(false);\n const [viewVisible, setViewVisible] = useState(true);\n\n const switchMode = (newMode: AuthMode) => {\n setViewVisible(false);\n setTimeout(() => {\n setMode(newMode);\n setViewVisible(true);\n }, 150);\n };\n\n // Auto-show setup form when no users exist (bootstrap mode)\n const isBootstrapMode = authController.needsSetup;\n\n useEffect(() => {\n const timer = setTimeout(() => setFadeIn(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n function buildErrorView() {\n if (!authController.authProviderError) return null;\n if (authController.user != null) return null;\n return (\n <div className=\"w-full\">\n <ErrorView error={authController.authProviderError.message ?? authController.authProviderError}/>\n </div>\n );\n }\n\n let logoComponent;\n if (logo) {\n logoComponent = <img src={logo}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\"\n }}\n alt={\"Logo\"}/>;\n } else {\n logoComponent = <RebaseLogo/>;\n }\n\n let notAllowedMessage: string | undefined;\n if (notAllowedError) {\n if (typeof notAllowedError === \"string\") {\n notAllowedMessage = notAllowedError;\n } else if (notAllowedError instanceof Error) {\n notAllowedMessage = notAllowedError.message;\n } else {\n notAllowedMessage = \"It looks like you don't have access to the CMS, based on the specified Authenticator configuration\";\n }\n }\n\n const showRegistration = !disableSignupScreen && authController.registrationEnabled;\n\n return (\n <div\n className={cls(\n \"relative flex items-center justify-center h-screen w-screen p-4 transition-opacity duration-500 bg-white dark:bg-surface-900\",\n fadeIn ? \"opacity-100\" : \"opacity-0\"\n )}>\n\n {/* Top-right controls */}\n <div className=\"absolute top-4 right-4 flex items-center gap-1 z-10\">\n <LanguageToggle/>\n <Menu\n trigger={<IconButton\n color=\"inherit\"\n aria-label=\"Toggle theme\">\n {colorMode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : <SunIcon size={iconSize.small}/>}\n </IconButton>}>\n <MenuItem onClick={() => setColorMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setColorMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")}</MenuItem>\n <MenuItem onClick={() => setColorMode(\"system\")}><SunMoonIcon size={iconSize.smallest}/> {t(\"system_mode\")}</MenuItem>\n </Menu>\n </div>\n\n <div className=\"flex flex-col items-center w-[480px] max-w-full p-8 sm:p-10\">\n {/* Logo */}\n <div className=\"w-32 h-32 m-2 mb-6\">\n {logoComponent}\n </div>\n\n {notAllowedMessage && (\n <div className=\"p-4 w-full\">\n <ErrorView error={notAllowedMessage}/>\n </div>\n )}\n\n {mode !== \"forgot\" && buildErrorView()}\n\n <div className={cls(\n \"w-full transition-opacity duration-150\",\n viewVisible ? \"opacity-100\" : \"opacity-0\"\n )}>\n {/* Bootstrap mode: show setup form directly */}\n {isBootstrapMode && !authController.user && (\n <LoginForm\n authController={authController}\n registrationMode={true}\n onClose={() => {}}\n onForgotPassword={() => {}}\n noUserComponent={noUserComponent}\n disableSignupScreen={false}\n bootstrapMode={true}\n />\n )}\n\n {/* Normal mode */}\n {!isBootstrapMode && (\n <>\n {/* Provider buttons screen */}\n {mode === \"buttons\" && (\n <div className=\"w-full flex flex-col gap-3 mt-2\">\n <LoginButton\n disabled={disabled}\n text={\"Sign in with email\"}\n icon={<MailIcon/>}\n onClick={() => switchMode(\"login\")}\n />\n {googleEnabled && googleClientId && (\n <GoogleLoginButton\n disabled={disabled}\n googleClientId={googleClientId}\n authController={authController}\n />\n )}\n {showRegistration && (\n <Button\n className=\"w-full\"\n variant=\"filled\"\n color=\"primary\"\n size=\"large\"\n onClick={() => switchMode(\"register\")}\n >\n Create an account\n </Button>\n )}\n </div>\n )}\n\n {/* Login form */}\n {mode === \"login\" && (\n <LoginForm\n authController={authController}\n registrationMode={false}\n onClose={() => switchMode(\"buttons\")}\n onForgotPassword={() => switchMode(\"forgot\")}\n noUserComponent={noUserComponent}\n disableSignupScreen={disableSignupScreen}\n switchToRegister={showRegistration ? () => switchMode(\"register\") : undefined}\n />\n )}\n\n {/* Registration form */}\n {mode === \"register\" && (\n <LoginForm\n authController={authController}\n registrationMode={true}\n onClose={() => switchMode(\"buttons\")}\n onForgotPassword={() => switchMode(\"forgot\")}\n noUserComponent={noUserComponent}\n disableSignupScreen={disableSignupScreen}\n switchToLogin={() => switchMode(\"login\")}\n />\n )}\n\n {/* Forgot password form */}\n {mode === \"forgot\" && (\n <ForgotPasswordForm\n authController={authController}\n onClose={() => switchMode(\"login\")}\n />\n )}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction LoginButton({\n icon,\n onClick,\n text,\n disabled\n}: { icon: React.ReactNode, onClick: () => void, text: string, disabled?: boolean }) {\n return (\n <Button\n disabled={disabled}\n className=\"w-full\"\n variant=\"outlined\"\n size=\"large\"\n onClick={onClick}>\n <div className=\"flex items-center justify-center w-full gap-3 py-1\">\n <span className=\"flex items-center justify-center w-5 h-5\">\n {icon}\n </span>\n <Typography variant=\"button\">{text}</Typography>\n </div>\n </Button>\n );\n}\n\nconst GoogleIcon = () => (\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\">\n <path fill=\"#4285F4\"\n d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"/>\n <path fill=\"#34A853\"\n d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/>\n <path fill=\"#FBBC05\"\n d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/>\n <path fill=\"#EA4335\"\n d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/>\n </svg>\n);\n\nfunction GoogleLoginButton({\n disabled,\n googleClientId,\n authController\n}: {\n disabled?: boolean,\n googleClientId: string,\n authController: RebaseAuthController\n}) {\n const tokenClientRef = useRef<any>(null);\n\n useEffect(() => {\n const google = (window as any).google;\n if (!google || tokenClientRef.current) return;\n\n tokenClientRef.current = google.accounts.oauth2.initTokenClient({\n client_id: googleClientId,\n scope: \"openid email profile\",\n callback: async (response: { access_token?: string; error?: string }) => {\n if (response.error || !response.access_token) {\n console.error(\"Google login error:\", response.error);\n return;\n }\n try {\n await authController.googleLogin(response.access_token, \"accessToken\");\n } catch (err: unknown) {\n console.error(\"Google login error:\", err);\n }\n }\n });\n }, [googleClientId, authController]);\n\n const handleClick = () => {\n if (!tokenClientRef.current) {\n console.error(\"Google Sign-In not loaded\");\n return;\n }\n tokenClientRef.current.requestAccessToken();\n };\n\n return (\n <LoginButton\n disabled={disabled}\n text=\"Sign in with Google\"\n icon={<GoogleIcon/>}\n onClick={handleClick}\n />\n );\n}\n\nfunction LoginForm({\n onClose,\n onForgotPassword,\n authController,\n registrationMode,\n noUserComponent,\n disableSignupScreen,\n bootstrapMode = false,\n switchToRegister,\n switchToLogin\n}: {\n onClose: () => void,\n onForgotPassword: () => void,\n authController: RebaseAuthController,\n registrationMode: boolean,\n noUserComponent?: ReactNode,\n disableSignupScreen: boolean,\n bootstrapMode?: boolean,\n switchToRegister?: () => void,\n switchToLogin?: () => void\n}) {\n const passwordRef = useRef<HTMLInputElement | null>(null);\n\n const [email, setEmail] = useState<string>();\n const [password, setPassword] = useState<string>();\n const [displayName, setDisplayName] = useState<string>();\n\n useEffect(() => {\n if (!document) return;\n const escFunction = (event: KeyboardEvent) => {\n if (event.keyCode === 27) {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", escFunction, false);\n return () => {\n document.removeEventListener(\"keydown\", escFunction, false);\n };\n }, [onClose]);\n\n function handleEnterPassword() {\n if (email && password) {\n authController.emailPasswordLogin(email, password);\n }\n }\n\n function handleRegistration() {\n if (email && password) {\n authController.register(email, password, displayName);\n }\n }\n\n const handleSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n if (registrationMode)\n handleRegistration();\n else\n handleEnterPassword();\n };\n\n const title = bootstrapMode\n ? \"Welcome!\"\n : registrationMode\n ? \"Create account\"\n : \"Sign in\";\n\n const subtitle = bootstrapMode\n ? \"Create your admin account to get started. This account will have admin privileges.\"\n : registrationMode\n ? \"Fill in your details to create a new account\"\n : \"Enter your credentials to continue\";\n\n const buttonLabel = registrationMode ? \"Create account\" : \"Sign in\";\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col w-full gap-1 mt-2\">\n {!bootstrapMode && (\n <div className=\"w-full mb-2 -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n )}\n\n <Typography variant=\"h6\" className=\"mb-0.5\">\n {title}\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\" className=\"mb-5\">\n {subtitle}\n </Typography>\n\n {registrationMode && noUserComponent && (\n <div className=\"w-full mb-2\">\n {noUserComponent}\n </div>\n )}\n\n {registrationMode && (\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Display Name\n </Typography>\n <TextField placeholder=\"Jane Doe (optional)\"\n className=\"w-full\"\n value={displayName ?? \"\"}\n disabled={authController.initialLoading}\n type=\"text\"\n size=\"medium\"\n onChange={(event) => setDisplayName(event.target.value)}/>\n </div>\n )}\n\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Email\n </Typography>\n <TextField placeholder=\"you@example.com\"\n className=\"w-full\"\n autoFocus\n value={email ?? \"\"}\n disabled={authController.initialLoading}\n type=\"email\"\n size=\"medium\"\n onChange={(event) => setEmail(event.target.value)}/>\n </div>\n\n <div className=\"w-full mb-1\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Password\n </Typography>\n <TextField placeholder=\"••••••••\"\n className=\"w-full\"\n value={password ?? \"\"}\n disabled={authController.initialLoading}\n inputRef={passwordRef}\n type=\"password\"\n size=\"medium\"\n onChange={(event) => setPassword(event.target.value)}/>\n </div>\n\n {registrationMode && (\n <Typography variant=\"caption\" color=\"secondary\" className=\"mb-3\">\n Password must be 8+ characters with uppercase, lowercase, and a number\n </Typography>\n )}\n\n {!registrationMode && (\n <div className=\"w-full text-right mb-3\">\n <button\n type=\"button\"\n className={cls(\n \"text-xs font-medium hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={onForgotPassword}\n >\n Forgot password?\n </button>\n </div>\n )}\n\n <LoadingButton\n type=\"submit\"\n variant=\"filled\"\n color=\"primary\"\n className=\"w-full mt-1\"\n size=\"large\"\n loading={authController.authLoading}\n disabled={authController.authLoading || !email || !password}\n >\n {buttonLabel}\n </LoadingButton>\n\n {/* Switch between login/register */}\n {switchToRegister && (\n <div className=\"mt-4 text-center\">\n <Typography variant=\"body2\" color=\"secondary\">\n Don&apos;t have an account?{\" \"}\n <button\n type=\"button\"\n className={cls(\n \"font-semibold hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={switchToRegister}\n >\n Create one\n </button>\n </Typography>\n </div>\n )}\n\n {switchToLogin && (\n <div className=\"mt-4 text-center\">\n <Typography variant=\"body2\" color=\"secondary\">\n Already have an account?{\" \"}\n <button\n type=\"button\"\n className={cls(\n \"font-semibold hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={switchToLogin}\n >\n Sign in\n </button>\n </Typography>\n </div>\n )}\n </form>\n );\n}\n\nfunction ForgotPasswordForm({\n onClose,\n authController\n}: {\n onClose: () => void,\n authController: RebaseAuthController\n}) {\n const [email, setEmail] = useState<string>(\"\");\n const [submitted, setSubmitted] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!document) return;\n const escFunction = (event: KeyboardEvent) => {\n if (event.keyCode === 27) {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", escFunction, false);\n return () => {\n document.removeEventListener(\"keydown\", escFunction, false);\n };\n }, [onClose]);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n setError(null);\n\n if (!email) {\n setError(\"Please enter your email address\");\n return;\n }\n\n try {\n await authController.forgotPassword(email);\n setSubmitted(true);\n } catch (err: unknown) {\n // Check for EMAIL_NOT_CONFIGURED error\n if (err instanceof Error && (err as { code?: string }).code === \"EMAIL_NOT_CONFIGURED\") {\n setError(\"Password reset is not available. Please contact your administrator.\");\n } else {\n // Still show success (security: don't reveal if email exists)\n setSubmitted(true);\n }\n }\n };\n\n if (submitted) {\n return (\n <div className=\"flex flex-col w-full gap-4 mt-2\">\n <div className=\"w-full -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n\n <div className={cls(\n \"text-center rounded-xl p-6\",\n \"bg-surface-50 dark:bg-surface-950\"\n )}>\n <div className=\"text-3xl mb-3\">📧</div>\n <Typography variant=\"subtitle1\" className=\"mb-2\">\n Check your email\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\">\n If an account exists for <strong>{email}</strong>, you&apos;ll receive a password reset link shortly.\n </Typography>\n </div>\n\n <Button onClick={onClose} variant=\"text\" className=\"mt-2\">\n Back to sign in\n </Button>\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col w-full gap-1 mt-2\">\n <div className=\"w-full mb-2 -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n\n <Typography variant=\"h6\" className=\"mb-0.5\">\n Reset password\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\" className=\"mb-5\">\n Enter your email and we&apos;ll send you a reset link.\n </Typography>\n\n {error && (\n <div className=\"w-full mb-3\">\n <ErrorView error={error}/>\n </div>\n )}\n\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Email\n </Typography>\n <TextField\n placeholder=\"you@example.com\"\n className=\"w-full\"\n autoFocus\n value={email}\n type=\"email\"\n size=\"medium\"\n onChange={(event) => setEmail(event.target.value)}\n />\n </div>\n\n <LoadingButton\n type=\"submit\"\n variant=\"filled\"\n color=\"primary\"\n className=\"w-full\"\n size=\"large\"\n loading={authController.authLoading}\n disabled={authController.authLoading || !email}\n >\n Send reset link\n </LoadingButton>\n </form>\n );\n}\n","import React, { useLayoutEffect, useRef } from \"react\";\nimport { useRebaseRegistryDispatch } from \"@rebasepro/core\";\nimport type { RebaseAuthConfig } from \"@rebasepro/types\";\n\n/**\n * Declarative component to configure authentication in Rebase.\n * Renders nothing — purely registers config into the RebaseRegistry.\n */\nexport function RebaseAuth({ loginView }: RebaseAuthConfig) {\n const dispatch = useRebaseRegistryDispatch();\n const registeredRef = useRef(false);\n\n useLayoutEffect(() => {\n dispatch.registerAuth({ loginView });\n registeredRef.current = true;\n return () => {\n registeredRef.current = false;\n dispatch.unregisterAuth();\n };\n }, [dispatch, loginView]);\n\n return null;\n}\n","\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport {\n useSnackbarController,\n ConfirmationDialog,\n useAuthController\n} from \"@rebasepro/core\";\nimport { AppView, EntityCollection, Role, SecurityRule, User } from \"@rebasepro/types\";\n\nimport { Button, Chip, Container, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Paper, Table, TableBody, TableCell, TableHeader, TableRow, TextField, Typography, CircularProgress, CenteredView, Tooltip, Checkbox, MultiSelect, MultiSelectItem, LoadingButton, getColorSchemeForSeed, ChipColorScheme, ChipColorKey } from \"@rebasepro/ui\";\nimport { PlusIcon, Trash2Icon } from \"lucide-react\";\nimport { UserManagement } from \"../hooks/useBackendUserManagement\";\n\ninterface AdminViewsProps {\n userManagement: UserManagement;\n apiUrl: string;\n getAuthToken: () => Promise<string>;\n collections?: EntityCollection[];\n}\n\n/**\n * Create admin views for user and role management\n */\nexport function createUserManagementAdminViews({ userManagement, apiUrl, getAuthToken, collections = [] }: AdminViewsProps): AppView[] {\n return [\n {\n slug: \"dev/users\",\n name: \"CMS Users\",\n group: \"Admin\",\n icon: \"face\",\n view: <UsersView userManagement={userManagement} apiUrl={apiUrl} getAuthToken={getAuthToken}/>\n },\n {\n slug: \"dev/roles\",\n name: \"Roles\",\n group: \"Admin\",\n icon: \"gpp_good\",\n view: <RolesView userManagement={userManagement} collections={collections}/>\n }\n ];\n}\n\n// ============================================\n// RoleChip Component (matches original)\n// ============================================\nfunction RoleChip({ role }: { role: Role }) {\n let colorScheme: ChipColorScheme | ChipColorKey;\n if (role.isAdmin) {\n colorScheme = \"blue\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellow\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"gray\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip colorScheme={colorScheme} key={role.id}>\n {role.name}\n </Chip>\n );\n}\n\n// ============================================\n// UsersView Component\n// ============================================\nexport function UsersView({ userManagement, apiUrl, getAuthToken }: {\n userManagement: UserManagement;\n apiUrl: string;\n getAuthToken: () => Promise<string>;\n}) {\n const { users, roles, saveUser, deleteUser, loading } = userManagement;\n const usersError = 'usersError' in userManagement ? (userManagement as { usersError?: Error }).usersError : undefined;\n const snackbarController = useSnackbarController();\n const { user: loggedInUser } = useAuthController();\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedUser, setSelectedUser] = useState<User | undefined>();\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n const [userToDelete, setUserToDelete] = useState<User | undefined>();\n const [deleteInProgress, setDeleteInProgress] = useState(false);\n const [formKey, setFormKey] = useState(0);\n const [bootstrapping, setBootstrapping] = useState(false);\n\n // Check if any admin exists\n const hasAdmin = users.some(u => u.roles?.includes(\"admin\"));\n\n const handleBootstrap = async () => {\n setBootstrapping(true);\n try {\n const token = await getAuthToken();\n const response = await fetch(`${apiUrl}/api/admin/bootstrap`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`\n }\n });\n const data = await response.json();\n if (!response.ok) {\n throw new Error(data.error?.message || \"Bootstrap failed\");\n }\n snackbarController.open({ type: \"success\",\nmessage: \"You are now an admin! Refreshing...\" });\n // Reload to get new roles\n window.location.reload();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to bootstrap admin\" });\n } finally {\n setBootstrapping(false);\n }\n };\n\n const handleAddUser = () => {\n setSelectedUser(undefined);\n setFormKey(k => k + 1);\n setDialogOpen(true);\n };\n\n const handleEditUser = (user: User) => {\n setSelectedUser(user);\n setDialogOpen(true);\n };\n\n const handleClose = () => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n };\n\n const handleDelete = async () => {\n if (!userToDelete) return;\n setDeleteInProgress(true);\n try {\n await deleteUser(userToDelete);\n snackbarController.open({ type: \"success\",\nmessage: \"User deleted successfully\" });\n setDeleteConfirmOpen(false);\n setUserToDelete(undefined);\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Error deleting user\" });\n } finally {\n setDeleteInProgress(false);\n }\n };\n\n if (loading) {\n return <CenteredView><CircularProgress/></CenteredView>;\n }\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n {/* Bootstrap warning when no admins */}\n {!hasAdmin && !usersError && loggedInUser && (\n <div className=\"bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 rounded p-4 flex items-center justify-between\">\n <div>\n <Typography variant=\"label\" className=\"text-yellow-800 dark:text-yellow-200\">\n No admin users exist. You can make yourself an admin.\n </Typography>\n </div>\n <Button\n onClick={handleBootstrap}\n disabled={bootstrapping}\n >\n {bootstrapping ? <CircularProgress size=\"small\"/> : \"Make me admin\"}\n </Button>\n </div>\n )}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\" className=\"grow\" component=\"h4\">\n Users\n </Typography>\n <Button startIcon={<PlusIcon/>} onClick={handleAddUser}>\n Add user\n </Button>\n </div>\n\n <div className=\"overflow-auto\">\n <Table className=\"w-full\">\n <TableHeader>\n <TableCell header className=\"truncate w-16\"></TableCell>\n <TableCell header>Email</TableCell>\n <TableCell header>Name</TableCell>\n <TableCell header>Roles</TableCell>\n </TableHeader>\n <TableBody>\n {users.map(user => (\n <TableRow key={user.uid} onClick={() => handleEditUser(user)}>\n <TableCell style={{ width: \"64px\" }}>\n <Tooltip asChild title=\"Delete this user\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setUserToDelete(user);\n setDeleteConfirmOpen(true);\n }}>\n <Trash2Icon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className=\"font-medium\">{user.displayName}</TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-2\">\n {user.roles?.map((roleId: string) => {\n const role = roles.find(r => r.id === roleId);\n return role ? <RoleChip key={roleId} role={role}/> : <span key={roleId}>{roleId}</span>;\n })}\n </div>\n </TableCell>\n </TableRow>\n ))}\n\n {users.length === 0 && (\n <TableRow>\n <TableCell colspan={4}>\n <CenteredView className=\"flex flex-col gap-4 my-8 items-center\">\n <Typography variant=\"label\">\n {usersError\n ? \"You don't have permission to view users\"\n : \"There are no users yet\"}\n </Typography>\n {usersError && (\n <Typography variant=\"caption\" className=\"text-surface-500\">\n Contact an administrator if you need access to this section.\n </Typography>\n )}\n </CenteredView>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n\n {/* User Edit Dialog */}\n <UserDetailsForm\n key={selectedUser?.uid ?? `new-${formKey}`}\n open={dialogOpen}\n user={selectedUser}\n roles={roles}\n saveUser={saveUser}\n handleClose={handleClose}\n />\n\n {/* Delete Confirmation */}\n <ConfirmationDialog\n open={deleteConfirmOpen}\n loading={deleteInProgress}\n onAccept={handleDelete}\n onCancel={() => { setDeleteConfirmOpen(false); setUserToDelete(undefined); }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}\n />\n </Container>\n );\n}\n\n// ============================================\n// UserDetailsForm Component (matches original)\n// ============================================\nfunction UserDetailsForm({\n open,\n user: userProp,\n roles,\n saveUser,\n handleClose\n}: {\n open: boolean;\n user?: User;\n roles: Role[];\n saveUser: (user: User) => Promise<User>;\n handleClose: () => void;\n}) {\n const snackbarController = useSnackbarController();\n const isNewUser = !userProp;\n\n const [displayName, setDisplayName] = useState(userProp?.displayName || \"\");\n const [email, setEmail] = useState(userProp?.email || \"\");\n const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>(\n userProp?.roles || [\"editor\"]\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<{ displayName?: string; email?: string; roles?: string }>({});\n const [submitCount, setSubmitCount] = useState(0);\n\n const validate = () => {\n const newErrors: typeof errors = {};\n if (!displayName) newErrors.displayName = \"Required\";\n if (!email) newErrors.email = \"Required\";\n else if (!/\\S+@\\S+\\.\\S+/.test(email)) newErrors.email = \"Invalid email\";\n if (selectedRoleIds.length === 0) newErrors.roles = \"At least one role is required\";\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setSubmitCount(c => c + 1);\n\n if (!validate()) return;\n\n setIsSubmitting(true);\n try {\n const userToSave: User = {\n uid: userProp?.uid || crypto.randomUUID(),\n email,\n displayName: displayName || null,\n photoURL: userProp?.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: selectedRoleIds\n };\n await saveUser(userToSave);\n handleClose();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to save user\" });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const dirty = isNewUser ||\n displayName !== (userProp?.displayName || \"\") ||\n email !== (userProp?.email || \"\") ||\n JSON.stringify(selectedRoleIds.sort()) !== JSON.stringify((userProp?.roles || []).sort());\n\n return (\n <Dialog open={open} onOpenChange={(open) => !open ? handleClose() : undefined} maxWidth=\"4xl\">\n <form onSubmit={handleSubmit} autoComplete=\"off\" noValidate\n style={{ display: \"flex\",\nflexDirection: \"column\",\nposition: \"relative\",\nheight: \"100%\" }}>\n\n <DialogTitle variant=\"h4\" gutterBottom={false}>\n User\n </DialogTitle>\n\n <DialogContent className=\"h-full grow\">\n <div className=\"grid grid-cols-12 gap-4\">\n <div className=\"col-span-12\">\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && errors.displayName ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12\">\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n label=\"Email\"\n disabled={!isNewUser}\n />\n <FieldCaption>\n {submitCount > 0 && errors.email ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12\">\n <MultiSelect\n className=\"w-full\"\n label=\"Roles\"\n value={selectedRoleIds}\n onValueChange={(value: string[]) => setSelectedRoleIds(value)}\n >\n {roles.map(role => (\n <MultiSelectItem key={role.id} value={role.id}>\n <RoleChip role={role}/>\n </MultiSelectItem>\n ))}\n </MultiSelect>\n </div>\n </div>\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Dialog>\n );\n}\n\n// ============================================\n// RolesView Component\n// ============================================\nexport function RolesView({ userManagement, collections = [] }: { userManagement: UserManagement, collections?: EntityCollection[] }) {\n const { roles, saveRole, deleteRole, loading, allowDefaultRolesCreation } = userManagement;\n const rolesError = 'rolesError' in userManagement ? (userManagement as { rolesError?: Error }).rolesError : undefined;\n const snackbarController = useSnackbarController();\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n const [roleToDelete, setRoleToDelete] = useState<Role | undefined>();\n const [deleteInProgress, setDeleteInProgress] = useState(false);\n\n const handleAddRole = () => {\n setSelectedRole(undefined);\n setDialogOpen(true);\n };\n\n const handleEditRole = (role: Role) => {\n setSelectedRole(role);\n setDialogOpen(true);\n };\n\n const handleClose = () => {\n setDialogOpen(false);\n setSelectedRole(undefined);\n };\n\n const handleDelete = async () => {\n if (!roleToDelete) return;\n setDeleteInProgress(true);\n try {\n await deleteRole(roleToDelete);\n snackbarController.open({ type: \"success\",\nmessage: \"Role deleted successfully\" });\n setDeleteConfirmOpen(false);\n setRoleToDelete(undefined);\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Error deleting role\" });\n } finally {\n setDeleteInProgress(false);\n }\n };\n\n const createDefaultRoles = () => {\n const defaultRoles: Role[] = [\n { id: \"admin\",\nname: \"Admin\",\nisAdmin: true },\n { id: \"editor\",\nname: \"Editor\",\nisAdmin: false },\n { id: \"viewer\",\nname: \"Viewer\",\nisAdmin: false }\n ];\n defaultRoles.forEach(role => saveRole(role));\n };\n\n if (loading) {\n return <CenteredView><CircularProgress/></CenteredView>;\n }\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\" className=\"grow\" component=\"h4\">\n Roles\n </Typography>\n <Button startIcon={<PlusIcon/>} onClick={handleAddRole}>\n Add role\n </Button>\n </div>\n\n <div className=\"w-full overflow-auto\">\n <Table className=\"w-full\">\n <TableHeader>\n <TableCell header className=\"w-16\"></TableCell>\n <TableCell header>Role</TableCell>\n <TableCell header className=\"items-center\">Is Admin</TableCell>\n </TableHeader>\n <TableBody>\n {roles.map(role => {\n return (\n <TableRow key={role.id} onClick={() => handleEditRole(role)}>\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin && (\n <Tooltip asChild title=\"Delete this role\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setRoleToDelete(role);\n setDeleteConfirmOpen(true);\n }}>\n <Trash2Icon/>\n </IconButton>\n </Tooltip>\n )}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className=\"items-center\">\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n </TableRow>\n );\n })}\n\n {roles.length === 0 && (\n <TableRow>\n <TableCell colspan={4}>\n <CenteredView className=\"flex flex-col gap-4 my-8 items-center\">\n <Typography variant=\"label\">\n {rolesError\n ? \"You don't have permission to view roles\"\n : \"You don\\u0026apos;t have any roles yet.\"}\n </Typography>\n {rolesError && (\n <Typography variant=\"caption\" className=\"text-surface-500\">\n Contact an administrator if you need access to this section.\n </Typography>\n )}\n {!rolesError && allowDefaultRolesCreation && (\n <Button onClick={createDefaultRoles}>\n Create default roles\n </Button>\n )}\n </CenteredView>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n\n {/* Role Edit Dialog */}\n <RoleDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n saveRole={saveRole}\n handleClose={handleClose}\n collections={collections}\n />\n\n {/* Delete Confirmation */}\n <ConfirmationDialog\n open={deleteConfirmOpen}\n loading={deleteInProgress}\n onAccept={handleDelete}\n onCancel={() => { setDeleteConfirmOpen(false); setRoleToDelete(undefined); }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}\n />\n </Container>\n );\n}\n\n// ============================================\n// RoleDetailsForm Component\n// ============================================\nfunction RoleDetailsForm({\n open,\n role: roleProp,\n saveRole,\n handleClose,\n collections = []\n}: {\n open: boolean;\n role?: Role;\n saveRole: (role: Role) => Promise<void>;\n handleClose: () => void;\n collections?: EntityCollection[];\n}) {\n const snackbarController = useSnackbarController();\n const isNewRole = !roleProp;\n\n const [roleId, setRoleId] = useState(roleProp?.id || \"\");\n const [roleName, setRoleName] = useState(roleProp?.name || \"\");\n const [isAdmin, setIsAdmin] = useState(roleProp?.isAdmin ?? false);\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<{ id?: string; name?: string }>({});\n const [submitCount, setSubmitCount] = useState(0);\n\n const validate = () => {\n const newErrors: typeof errors = {};\n if (!roleId) newErrors.id = \"Required\";\n if (!roleName) newErrors.name = \"Required\";\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setSubmitCount(c => c + 1);\n\n if (!validate()) return;\n\n setIsSubmitting(true);\n try {\n await saveRole({\n id: roleId,\n name: roleName,\n isAdmin\n });\n handleClose();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to save role\" });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={(open) => !open ? handleClose() : undefined} maxWidth=\"6xl\">\n <form onSubmit={handleSubmit} autoComplete=\"off\" noValidate\n style={{ display: \"flex\",\nflexDirection: \"column\",\nposition: \"relative\",\nheight: \"100%\" }}>\n\n <DialogTitle variant=\"h4\" gutterBottom={false}>\n Role\n </DialogTitle>\n\n <DialogContent className=\"h-full grow overflow-y-auto\">\n <div className=\"grid grid-cols-12 gap-4\">\n <div className=\"col-span-12 sm:col-span-4\">\n <TextField\n name=\"id\"\n required\n error={submitCount > 0 && Boolean(errors.id)}\n value={roleId}\n onChange={(e) => setRoleId(e.target.value)}\n label=\"Role ID\"\n disabled={!isNewRole}\n />\n <FieldCaption>\n {submitCount > 0 && errors.id ? errors.id : \"Unique identifier for this role\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12 sm:col-span-4\">\n <TextField\n name=\"name\"\n required\n error={submitCount > 0 && Boolean(errors.name)}\n value={roleName}\n onChange={(e) => setRoleName(e.target.value)}\n label=\"Role Name\"\n />\n <FieldCaption>\n {submitCount > 0 && errors.name ? errors.name : \"Display name for this role\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12 sm:col-span-4 flex items-start pt-2\">\n <label className=\"flex items-center gap-2 cursor-pointer mt-3\">\n <Checkbox\n checked={isAdmin}\n onCheckedChange={(checked) => setIsAdmin(Boolean(checked))}\n />\n <span className=\"font-medium\">Is Admin</span>\n </label>\n </div>\n\n {/* Permissions matrix */}\n <div className=\"col-span-12\">\n <CollectionPermissionsMatrix roleId={roleId} isAdmin={isAdmin} collections={collections}/>\n </div>\n </div>\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n type=\"submit\"\n loading={isSubmitting}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Dialog>\n );\n}\n\n// ============================================\n// CollectionPermissionsMatrix Component\n// ============================================\nconst CRUD_OPS = [\n { op: \"select\" as const,\nlabel: \"Read\" },\n { op: \"insert\" as const,\nlabel: \"Create\" },\n { op: \"update\" as const,\nlabel: \"Edit\" },\n { op: \"delete\" as const,\nlabel: \"Delete\" }\n];\n\n/** Inline check: does roleId have access for this operation on these securityRules? */\nfunction hasRoleAccess(\n rules: SecurityRule[] | undefined,\n roleId: string,\n op: \"select\" | \"insert\" | \"update\" | \"delete\"\n): boolean {\n if (!rules || rules.length === 0) return true; // no rules = unrestricted\n const applicable = rules.filter(r =>\n r.operation === op || r.operation === \"all\" ||\n r.operations?.includes(op) || r.operations?.includes(\"all\")\n );\n if (applicable.length === 0) return false;\n const forRole = applicable.filter(r =>\n !r.roles || r.roles.length === 0 || r.roles.includes(roleId) || r.roles.includes(\"public\")\n );\n if (forRole.length === 0) return false;\n // Restrictive rules: any failing one denies immediately\n for (const r of forRole) {\n if ((r.mode ?? \"permissive\") === \"restrictive\") return false;\n }\n return forRole.some(r => (r.mode ?? \"permissive\") === \"permissive\");\n}\n\nfunction PermCell({ granted }: { granted: boolean }) {\n return (\n <span className={granted\n ? \"text-green-500 dark:text-green-400 text-base select-none\"\n : \"text-surface-300 dark:text-surface-600 text-base select-none\"}\n >\n {granted ? \"✓\" : \"✗\"}\n </span>\n );\n}\n\nfunction CollectionPermissionsMatrix({ roleId, isAdmin, collections }: { roleId: string; isAdmin: boolean; collections: EntityCollection[] }) {\n if (!collections || collections.length === 0) {\n return (\n <div className=\"mt-4\">\n <Typography variant=\"label\" className=\"text-surface-400\">No collections configured</Typography>\n </div>\n );\n }\n\n const topLevel = collections;\n\n return (\n <div className=\"mt-6\">\n <Typography variant=\"label\" className=\"mb-2 block text-surface-600 dark:text-surface-400 uppercase tracking-wide text-xs\">\n Collection permissions\n </Typography>\n <div className=\"rounded-lg border border-surface-200 dark:border-surface-700 overflow-hidden\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableCell header>Collection</TableCell>\n {CRUD_OPS.map(({ op, label }) => (\n <TableCell key={op} header className=\"text-center w-24\">{label}</TableCell>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {topLevel.map((collection) => {\n const extCol = collection as EntityCollection & { securityRules?: SecurityRule[] };\n const noRules = !extCol.securityRules || extCol.securityRules.length === 0;\n return (\n <TableRow key={collection.slug}>\n <TableCell>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{collection.name}</span>\n {noRules && !isAdmin && (\n <Tooltip title=\"No security rules — unrestricted\">\n <Chip className=\"text-xs\" colorScheme=\"yellow\">No rules</Chip>\n </Tooltip>\n )}\n </div>\n <span className=\"text-xs text-surface-400 font-mono\">{collection.slug}</span>\n </TableCell>\n {CRUD_OPS.map(({ op }) => (\n <TableCell key={op} className=\"text-center\">\n <PermCell granted={isAdmin || hasRoleAccess(extCol.securityRules, roleId, op)}/>\n </TableCell>\n ))}\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n {!roleId && (\n <Typography variant=\"caption\" className=\"mt-2 text-surface-400 italic\">\n Enter a role ID above to preview permissions\n </Typography>\n )}\n </div>\n );\n}\n\n// ============================================\n// Internal Components\n// ============================================\nfunction FieldCaption({ children }: React.PropsWithChildren) {\n return (\n <Typography variant=\"caption\" className=\"text-surface-500 mt-1.5 ml-1 block\">\n {children}\n </Typography>\n );\n}\n"],"names":["authApi.setApiUrl","refreshAccessToken","authApi.refreshAccessToken","authApi.login","register","authApi.register","googleLogin","authApi.googleLogin","oauthLogin","authApi.oauthLogin","authApi.logout","forgotPassword","authApi.forgotPassword","resetPassword","authApi.resetPassword","changePassword","authApi.changePassword","updateProfile","authApi.updateProfile","fetchSessions","authApi.fetchSessions","revokeSession","authApi.revokeSession","authApi.fetchAuthConfig","authApi.getCurrentUser","getApiUrl","authApi.getApiUrl","revokeAllSessions","authApi.revokeAllSessions","open"],"mappings":";;;;;AAKA,IAAI,aAAa;AAKV,SAAS,UAAU,KAAmB;AACzC,eAAa;AACjB;AAKO,SAAS,YAAoB;AAChC,SAAO;AACX;AAEA,MAAM,qBAAqB,MAAM;AAAA,EAC7B;AAAA,EAEA,YAAY,SAAiB,MAAc;AACvC,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EAChB;AACJ;AAEA,eAAe,eAAkB,UAAgC;AAC7D,MAAI;AACJ,MAAI;AACA,WAAO,MAAM,SAAS,KAAA;AAAA,EAC1B,SAAS,YAAY;AAEjB,UAAM,IAAI;AAAA,MACN,8CAA8C,SAAS,MAAM;AAAA,MAC7D;AAAA,IAAA;AAAA,EAER;AAEA,MAAI,CAAC,SAAS,IAAI;AACd,UAAM,IAAI;AAAA,MACL,KAAgD,OAAO,WAAW;AAAA,MAClE,KAAgD,OAAO,QAAQ;AAAA,IAAA;AAAA,EAExE;AAEA,SAAO;AACX;AAMA,eAAe,kBAAkB,OAA0B,MAAuC;AAC9F,MAAI;AACA,WAAO,MAAM,MAAM,OAAO,IAAI;AAAA,EAClC,SAAS,OAAgB;AACrB,QAAI,iBAAiB,aAAa,MAAM,QAAQ,SAAS,iBAAiB,GAAG;AACzE,YAAM,IAAI;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,IAER;AACA,UAAM,IAAI,aAAa,qBAAqB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,IAAI,eAAe;AAAA,EACxH;AACJ;AAKA,eAAsB,SAClB,OACA,UACA,aACqB;AACrB,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,sBAAsB;AAAA,IACxE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU;AAAA,MAAE;AAAA,MAC/B;AAAA,MACA;AAAA,IAAA,CAAa;AAAA,EAAA,CACR;AAED,SAAO,eAA6B,QAAQ;AAChD;AAKA,eAAsB,MAAM,OAAe,UAAyC;AAChF,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,mBAAmB;AAAA,IACrE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU;AAAA,MAAE;AAAA,MAC/B;AAAA,IAAA,CAAU;AAAA,EAAA,CACL;AAED,SAAO,eAA6B,QAAQ;AAChD;AAKA,eAAsB,YAAY,OAAe,YAAuC,WAAkC;AACtH,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,oBAAoB;AAAA,IACtE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU,EAAE,CAAC,SAAS,GAAG,OAAO;AAAA,EAAA,CAC9C;AAED,SAAO,eAA6B,QAAQ;AAChD;AAoBA,eAAsB,WAAW,YAAoB,SAAyD;AAC1G,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,aAAa,UAAU,IAAI;AAAA,IAC7E,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU,OAAO;AAAA,EAAA,CAC/B;AAED,SAAO,eAA6B,QAAQ;AAChD;AAKA,eAAsB,mBAAmB,cAAgD;AACrF,UAAQ,IAAI,wCAAwC;AAEpD,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,qBAAqB;AAAA,IACvE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU,EAAE,cAAc;AAAA,EAAA,CACxC;AAED,UAAQ,IAAI,uCAAuC,SAAS,MAAM;AAClE,SAAO,eAAgC,QAAQ;AACnD;AAKA,eAAsB,OAAO,cAAsC;AAC/D,QAAM,kBAAkB,GAAG,UAAU,oBAAoB;AAAA,IACrD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU,EAAE,cAAc;AAAA,EAAA,CACxC;AACL;AAKA,eAAsB,eAAe,aAAkD;AACnF,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,gBAAgB;AAAA,IAClE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU,WAAW;AAAA,IAAA;AAAA,EAC1C,CACH;AAED,SAAO,eAAmC,QAAQ;AACtD;AAKA,eAAsB,eAAe,OAA+D;AAChG,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,6BAA6B;AAAA,IAC/E,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU,EAAE,OAAO;AAAA,EAAA,CACjC;AAED,SAAO,eAAsD,QAAQ;AACzE;AAKA,eAAsB,cAAc,OAAe,UAAkE;AACjH,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,4BAA4B;AAAA,IAC9E,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAC3B,MAAM,KAAK,UAAU;AAAA,MAAE;AAAA,MAC/B;AAAA,IAAA,CAAU;AAAA,EAAA,CACL;AAED,SAAO,eAAsD,QAAQ;AACzE;AAKA,eAAsB,eAClB,aACA,aACA,aAC8C;AAC9C,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,6BAA6B;AAAA,IAC/E,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU,WAAW;AAAA,IAAA;AAAA,IAE1C,MAAM,KAAK,UAAU;AAAA,MAAE;AAAA,MAC/B;AAAA,IAAA,CAAa;AAAA,EAAA,CACR;AAED,SAAO,eAAsD,QAAQ;AACzE;AAgCA,eAAsB,cAClB,aACA,aACA,UAC2B;AAC3B,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,gBAAgB;AAAA,IAClE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU,WAAW;AAAA,IAAA;AAAA,IAE1C,MAAM,KAAK,UAAU;AAAA,MAAE;AAAA,MAC/B;AAAA,IAAA,CAAU;AAAA,EAAA,CACL;AAED,SAAO,eAAmC,QAAQ;AACtD;AAKA,eAAsB,cAAc,aAAqB,qBAAgE;AACrH,QAAM,UAAkC;AAAA,IACpC,gBAAgB;AAAA,IAChB,iBAAiB,UAAU,WAAW;AAAA,EAAA;AAE1C,MAAI,qBAAqB;AACrB,YAAQ,iBAAiB,IAAI;AAAA,EACjC;AAEA,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,sBAAsB;AAAA,IACxE,QAAQ;AAAA,IACR;AAAA,EAAA,CACH;AAED,SAAO,eAAwC,QAAQ;AAC3D;AAKA,eAAsB,cAAc,aAAqB,WAAmE;AACxH,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,sBAAsB,SAAS,IAAI;AAAA,IACrF,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU,WAAW;AAAA,IAAA;AAAA,EAC1C,CACH;AAED,SAAO,eAAsD,QAAQ;AACzE;AAKA,eAAsB,kBAAkB,aAAqE;AACzG,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,sBAAsB;AAAA,IACxE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU,WAAW;AAAA,IAAA;AAAA,EAC1C,CACH;AAED,SAAO,eAAsD,QAAQ;AACzE;AAwBA,eAAsB,kBAA+C;AACjE,QAAM,WAAW,MAAM,kBAAkB,GAAG,UAAU,oBAAoB;AAAA,IACtE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,EAAmB,CACjD;AAED,SAAO,eAAmC,QAAQ;AACtD;AC/VA,MAAM,cAAc;AAGpB,MAAM,0BAA0B,IAAI,KAAK;AAKzC,SAAS,cAAc,UAA0B;AAC7C,SAAO;AAAA,IACH,KAAK,SAAS;AAAA,IACd,OAAO,SAAS;AAAA,IAChB,aAAa,SAAS,eAAe;AAAA,IACrC,UAAU,SAAS,YAAY;AAAA,IAC/B,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,OAAO,SAAS,SAAS,CAAA;AAAA,EAAC;AAElC;AAaA,SAAS,kBAAkB,QAAoB,MAAsB;AACjE,MAAI;AACA,UAAM,OAAuB;AAAA,MAAE;AAAA,MACvC;AAAA,IAAA;AACQ,iBAAa,QAAQ,aAAa,KAAK,UAAU,IAAI,CAAC;AACtD,UAAM,aAAa,IAAI,KAAK,OAAO,oBAAoB;AACvD,UAAM,YAAY,OAAO,SAAS,OAAO,oBAAoB,IAAI,WAAW,gBAAgB;AAAA,EAChG,SAAS,GAAG;AAAA,EAAe;AAC/B;AAKA,SAAS,sBAA6C;AAClD,MAAI;AACA,UAAM,OAAO,aAAa,QAAQ,WAAW;AAC7C,QAAI,MAAM;AACN,YAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,aAAO;AAAA,IACX;AAAA,EACJ,SAAS,GAAG;AACR,YAAQ,KAAK,qCAAqC,CAAC;AAAA,EACvD;AACA,SAAO;AACX;AAKA,SAAS,uBAA6B;AAClC,MAAI;AACA,iBAAa,WAAW,WAAW;AAAA,EACvC,SAAS,GAAG;AACR,YAAQ,KAAK,sCAAsC,CAAC;AAAA,EACxD;AACJ;AAKA,SAAS,2BAA2B,WAAmB,WAAmB,yBAAkC;AACxG,SAAO,KAAK,QAAQ,YAAY;AACpC;AASO,SAAS,wBACZ,QAAmC,IACf;AACpB,QAAM,EAAE,QAAQ,QAAQ,WAAW,mBAAmB;AAEtD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAClD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAuB,IAAI;AAC7D,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAuB,IAAI;AAC7E,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkB,IAAI;AAChD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAoC,IAAI;AAG5E,QAAM,YAAY,OAA0B,IAAI;AAChD,QAAM,oBAAoB,OAA6C,IAAI;AAE3E,QAAM,oBAAoB,OAA0C,IAAI;AAExE,QAAM,eAAe,OAAO,IAAI;AAGhC,YAAU,MAAM;AACZ,QAAI,QAAQ;AACRA,gBAAkB,OAAO,OAAO;AAAA,IACpC,WAAW,QAAQ;AACfA,gBAAkB,MAAM;AAAA,IAC5B;AAAA,EACJ,GAAG,CAAC,QAAQ,MAAM,CAAC;AAGnB,QAAM,yBAAyB,YAAY,MAAM;AAC7C,cAAU,UAAU;AACpB,yBAAA;AACA,QAAI,kBAAkB,SAAS;AAC3B,mBAAa,kBAAkB,OAAO;AACtC,wBAAkB,UAAU;AAAA,IAChC;AACA,YAAQ,IAAI;AACZ,oBAAgB,KAAK;AACrB,gBAAA;AAAA,EACJ,GAAG,CAAC,SAAS,CAAC;AAMd,QAAMC,uBAAqB,YAAY,YAAwC;AAE3E,QAAI,kBAAkB,SAAS;AAE3B,aAAO,kBAAkB;AAAA,IAC7B;AAEA,UAAM,iBAAiB,YAAwC;AAE3D,YAAM,aAAa,oBAAA;AACnB,UAAI,YAAY,QAAQ,sBAAsB;AAC1C,cAAM,eAAe,WAAW;AAEhC,YAAI,CAAC,2BAA2B,aAAa,oBAAoB,KAAK,aAAa,gBAAgB,UAAU,SAAS,aAAa;AAC/H,oBAAU,UAAU;AACpB,iBAAO;AAAA,QACX;AAAA,MACJ;AAEA,YAAM,gBAAgB,UAAU;AAChC,UAAI,CAAC,eAAe,cAAc;AAC9B,eAAO;AAAA,MACX;AAGA,UAAI;AACA,cAAM,WAAW,MAAMC,mBAA2B,cAAc,YAAY;AAC5E,cAAM,YAAY,SAAS;AAG3B,kBAAU,UAAU;AAGpB,cAAM,mBAAmB,oBAAA;AACzB,YAAI,kBAAkB;AAClB,4BAAkB,WAAW,iBAAiB,IAAI;AAAA,QACtD;AAEA,cAAM,eAAe,OAAO,SAAS,UAAU,oBAAoB,IAAI,IAAI,KAAK,UAAU,oBAAoB,EAAE,YAAA,IAAgB;AAChI,eAAO;AAAA,MACX,SAAS,OAAgB;AAIrB,YAAI,iBAAiB,SAAU,MAA4B,SAAS,iBAAiB;AACjF,gBAAM;AAAA,QACV;AACA,eAAO;AAAA,MACX,UAAA;AACI,0BAAkB,UAAU;AAAA,MAChC;AAAA,IACJ;AAEA,sBAAkB,UAAU,eAAA;AAC5B,WAAO,kBAAkB;AAAA,EAC7B,GAAG,CAAA,CAAE;AAGL,QAAM,uBAAuB,YAAY,CAAC,WAAuB;AAC7D,QAAI,kBAAkB,SAAS;AAC3B,mBAAa,kBAAkB,OAAO;AAAA,IAC1C;AAGA,UAAM,YAAY,OAAO;AACzB,UAAM,YAAY,YAAY;AAC9B,UAAM,mBAAmB,YAAY,KAAK,IAAA;AAE1C,QAAI,oBAAoB,GAAG;AAEvBD,2BAAA,EAAqB,KAAK,CAAA,cAAa;AACnC,YAAI,aAAa,aAAa,SAAS;AACnC,+BAAqB,SAAS;AAAA,QAClC,WAAW,CAAC,aAAa,aAAa,SAAS;AAC3C,iCAAA;AAAA,QACJ;AAAA,MACJ,CAAC;AACD;AAAA,IACJ;AAGA,sBAAkB,UAAU,WAAW,YAAY;AAC/C,UAAI,CAAC,aAAa,QAAS;AAE3B,UAAI;AACA,cAAM,YAAY,MAAMA,qBAAA;AAExB,YAAI,aAAa,aAAa,SAAS;AACnC,+BAAqB,SAAS;AAAA,QAClC,WAAW,CAAC,aAAa,aAAa,SAAS;AAC3C,iCAAA;AAAA,QACJ;AAAA,MACJ,SAAS,OAAO;AAEZ,YAAI,aAAa,SAAS;AACtB,4BAAkB,UAAU,WAAW,MAAM;AACzC,iCAAqB,MAAM;AAAA,UAC/B,GAAG,GAAK;AAAA,QACZ;AAAA,MACJ;AAAA,IACJ,GAAG,gBAAgB;AAAA,EACvB,GAAG,CAACA,sBAAoB,sBAAsB,CAAC;AAG/C,QAAM,eAAe,YAAY,YAA6B;AAE1D,QAAI,gBAAgB;AAChB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C;AAEA,UAAM,gBAAgB,UAAU;AAChC,QAAI,CAAC,eAAe;AAChB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C;AAGA,QAAI,2BAA2B,cAAc,oBAAoB,GAAG;AAChE,UAAI;AACA,cAAM,YAAY,MAAMA,qBAAA;AACxB,YAAI,CAAC,WAAW;AACZ,iCAAA;AACA,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QAC1D;AACA,eAAO,UAAU;AAAA,MACrB,SAAS,OAAgB;AAGrB,YAAI,iBAAiB,SAAU,MAA4B,SAAS,iBAAiB;AACjF,gBAAM;AAAA,QACV;AACA,+BAAA;AACA,cAAM;AAAA,MACV;AAAA,IACJ;AAEA,WAAO,cAAc;AAAA,EACzB,GAAG,CAAC,gBAAgBA,sBAAoB,sBAAsB,CAAC;AAG/D,YAAU,MAAM;AACZ,QAAI,QAAQ;AACR,aAAO,mBAAmB,YAAY;AAClC,YAAI;AAAE,iBAAO,MAAM,aAAA;AAAA,QAAgB,QAAQ;AAAE,iBAAO;AAAA,QAAM;AAAA,MAC9D,CAAC;AACD,UAAI,OAAO,mBAAmB;AAC1B,eAAO,kBAAkB,YAAY;AACjC,cAAI;AACA,kBAAM,YAAY,MAAMA,qBAAA;AACxB,gBAAI,UAAW,QAAO;AACtB,mCAAA;AACA,mBAAO;AAAA,UACX,SAAS,GAAG;AACR,mCAAA;AACA,mBAAO;AAAA,UACX;AAAA,QACJ,CAAC;AAAA,MACL;AACA,UAAI,OAAO,IAAI;AACX,eAAO,GAAG,mBAAmB,YAAY;AACrC,iBAAO,MAAM,aAAA;AAAA,QACjB,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,QAAQ,cAAcA,sBAAoB,sBAAsB,CAAC;AAGrE,QAAM,oBAAoB,YAAY,OAAO,UAAoB,WAAuB;AACpF,cAAU,UAAU;AACpB,QAAI,gBAAgB,cAAc,QAAQ;AAG1C,QAAI,gBAAgB;AAChB,YAAM,cAAc,MAAM,eAAe,aAAa;AACtD,UAAI,aAAa;AACb,wBAAgB;AAAA,UAAE,GAAG;AAAA,UACrC,OAAO,YAAY,IAAI,CAAA,MAAK,EAAE,EAAE;AAAA,QAAA;AAAA,MACpB;AAAA,IACJ;AAGA,sBAAkB,QAAQ,QAAQ;AAElC,YAAQ,aAAa;AACrB,iBAAa,IAAI;AACjB,yBAAqB,IAAI;AACzB,oBAAgB,KAAK;AACrB,yBAAqB,MAAM;AAAA,EAC/B,GAAG,CAAC,sBAAsB,cAAc,CAAC;AAGzC,QAAM,qBAAqB,YAAY,OAAO,OAAe,aAAqB;AAC9E,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAM,WAAW,MAAME,MAAc,OAAO,QAAQ;AACpD,YAAM,kBAAkB,SAAS,MAAM,SAAS,MAAM;AAAA,IAC1D,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAMC,aAAW,YAAY,OAAO,OAAe,UAAkB,gBAAyB;AAC1F,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAM,WAAW,MAAMC,SAAiB,OAAO,UAAU,WAAW;AACpE,YAAM,kBAAkB,SAAS,MAAM,SAAS,MAAM;AAAA,IAC1D,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAMC,gBAAc,YAAY,OAAO,OAAe,YAAuC,cAAc;AACvG,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAM,WAAW,MAAMC,YAAoB,OAAO,SAAS;AAC3D,YAAM,kBAAkB,SAAS,MAAM,SAAS,MAAM;AAAA,IAC1D,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAMC,eAAa,YAAY,OAAO,YAAoB,YAAqC;AAC3F,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAM,WAAW,MAAMC,WAAmB,YAAY,OAAO;AAC7D,YAAM,kBAAkB,SAAS,MAAM,SAAS,MAAM;AAAA,IAC1D,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAM,UAAU,YAAY,YAAY;AACpC,QAAI;AACA,UAAI,UAAU,SAAS;AACnB,cAAMC,OAAe,UAAU,QAAQ,YAAY;AAAA,MACvD;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,iBAAiB,KAAK;AAAA,IACxC,UAAA;AACI,6BAAA;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,sBAAsB,CAAC;AAG3B,QAAM,YAAY,YAAY,MAAM;AAChC,oBAAgB,IAAI;AACpB,YAAQ,IAAI;AAAA,EAChB,GAAG,CAAA,CAAE;AAGL,QAAMC,mBAAiB,YAAY,OAAO,UAAkB;AACxD,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAMC,eAAuB,KAAK;AAAA,IACtC,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAMC,kBAAgB,YAAY,OAAO,OAAe,aAAqB;AACzE,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,YAAMC,cAAsB,OAAO,QAAQ;AAAA,IAC/C,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAMC,mBAAiB,YAAY,OAAO,aAAqB,gBAAwB;AACnF,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,UAAI,CAAC,UAAU,SAAS;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AACA,YAAMC,eAAuB,UAAU,QAAQ,aAAa,aAAa,WAAW;AAEpF,6BAAA;AAAA,IACJ,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,sBAAsB,CAAC;AAG3B,QAAMC,kBAAgB,YAAY,OAAO,aAAsB,aAAsB;AACjF,mBAAe,IAAI;AACnB,yBAAqB,IAAI;AAEzB,QAAI;AACA,UAAI,CAAC,UAAU,SAAS;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AACA,YAAM,WAAW,MAAMC,cAAsB,UAAU,QAAQ,aAAa,aAAa,QAAQ;AAGjG,UAAI,gBAAgB,cAAc,SAAS,IAAI;AAC/C,UAAI,gBAAgB;AAChB,cAAM,cAAc,MAAM,eAAe,aAAa;AACtD,YAAI,aAAa;AACb,0BAAgB;AAAA,YAAE,GAAG;AAAA,YACzC,OAAO,YAAY,IAAI,CAAA,MAAK,EAAE,EAAE;AAAA,UAAA;AAAA,QAChB;AAAA,MACJ;AAGA,YAAM,aAAa,oBAAA;AACnB,UAAI,YAAY;AACZ,0BAAkB,WAAW,QAAQ,SAAS,IAAI;AAAA,MACtD;AAEA,cAAQ,aAAa;AACrB,aAAO;AAAA,IACX,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV,UAAA;AACI,qBAAe,KAAK;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,cAAc,CAAC;AAGnB,QAAMC,kBAAgB,YAAY,YAAY;AAC1C,QAAI;AACA,UAAI,CAAC,UAAU,SAAS;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AACA,YAAM,WAAW,MAAMC,cAAsB,UAAU,QAAQ,aAAa,UAAU,QAAQ,YAAY;AAC1G,aAAO,SAAS;AAAA,IACpB,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAMC,kBAAgB,YAAY,OAAO,cAAsB;AAC3D,QAAI;AACA,UAAI,CAAC,UAAU,SAAS;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AACA,YAAMC,cAAsB,UAAU,QAAQ,aAAa,SAAS;AAAA,IAGxE,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,YAAU,MAAM;AACZ,iBAAa,UAAU;AAEvB,UAAM,cAAc,YAAY;AAG5B,UAAI;AACA,cAAM,SAAS,MAAMC,gBAAQ;AAC7B,YAAI,aAAa,SAAS;AACtB,wBAAc,MAAM;AAAA,QACxB;AAAA,MACJ,SAAS,GAAG;AAAA,MAAe;AAE3B,YAAM,SAAS,oBAAA;AAEf,UAAI,CAAC,QAAQ;AACT,0BAAkB,KAAK;AACvB;AAAA,MACJ;AAEA,UAAI,CAAC,OAAO,QAAQ,cAAc;AAC9B,6BAAA;AACA,0BAAkB,KAAK;AACvB;AAAA,MACJ;AAIA,YAAM,YAAY,OAAO,OAAO;AAChC,UAAI,OAAO,cAAc,YAAY,CAAC,OAAO,SAAS,SAAS,GAAG;AAC9D,6BAAA;AACA,0BAAkB,KAAK;AACvB;AAAA,MACJ;AAIA,UAAI,CAAC,2BAA2B,OAAO,OAAO,oBAAoB,GAAG;AAEjE,kBAAU,UAAU,OAAO;AAE3B,YAAI,YAAY,cAAc,OAAO,IAAI;AACzC,YAAI,gBAAgB;AAChB,gBAAM,cAAc,MAAM,eAAe,SAAS;AAClD,cAAI,aAAa;AACb,wBAAY;AAAA,cAAE,GAAG;AAAA,cACzC,OAAO,YAAY,IAAI,CAAA,MAAK,EAAE,EAAE;AAAA,YAAA;AAAA,UACZ;AAAA,QACJ;AAEA,gBAAQ,SAAS;AACjB,6BAAqB,OAAO,MAAM;AAClC,0BAAkB,KAAK;AACvB;AAAA,MACJ;AAGA,gBAAU,UAAU,OAAO;AAE3B,UAAI;AACA,cAAM,YAAY,MAAMtB,qBAAA;AAExB,YAAI,CAAC,WAAW;AACZ,+BAAA;AACA,oBAAU,UAAU;AACpB,4BAAkB,KAAK;AACvB;AAAA,QACJ;AAEA,YAAI,CAAC,aAAa,QAAS;AAG3B,YAAI;AACJ,YAAI;AACA,gBAAM,aAAa,MAAMuB,eAAuB,UAAU,WAAW;AAErE,cAAI,CAAC,aAAa,QAAS;AAE3B,gBAAM,gBAAgB,WAAW;AAGjC,4BAAkB,WAAW,aAAa;AAE1C,sBAAY,cAAc,aAAa;AAEvC,cAAI,gBAAgB;AAChB,kBAAM,cAAc,MAAM,eAAe,SAAS;AAClD,gBAAI,CAAC,aAAa,QAAS;AAC3B,gBAAI,aAAa;AACb,0BAAY;AAAA,gBAAE,GAAG;AAAA,gBAC7C,OAAO,YAAY,IAAI,CAAA,MAAK,EAAE,EAAE;AAAA,cAAA;AAAA,YACR;AAAA,UACJ;AAAA,QACJ,SAAS,SAAkB;AACvB,cAAI,CAAC,aAAa,QAAS;AAC3B,sBAAY,cAAc,OAAO,IAAI;AAAA,QACzC;AAEA,YAAI,CAAC,aAAa,QAAS;AAE3B,gBAAQ,SAAS;AACjB,6BAAqB,SAAS;AAAA,MAClC,SAAS,OAAgB;AACrB,YAAI,CAAC,aAAa,QAAS;AAG3B,YAAI,EAAE,iBAAiB,SAAU,MAA4B,SAAS,kBAAkB;AACpF,+BAAA;AACA,oBAAU,UAAU;AAAA,QACxB;AAAA,MACJ,UAAA;AACI,YAAI,aAAa,SAAS;AACtB,4BAAkB,KAAK;AAAA,QAC3B;AAAA,MACJ;AAAA,IACJ;AAEA,gBAAA;AAEA,WAAO,MAAM;AACT,mBAAa,UAAU;AAAA,IAC3B;AAAA,EACJ,GAAG,CAAC,sBAAsB,gBAAgBvB,oBAAkB,CAAC;AAG7D,YAAU,MAAM;AACZ,UAAM,yBAAyB,YAAY;AACvC,UAAI,eAAgB;AAEpB,UAAI,SAAS,oBAAoB,aAAa,UAAU,SAAS;AAE7D,YAAI,2BAA2B,UAAU,QAAQ,oBAAoB,GAAG;AACpE,cAAI;AACA,kBAAM,YAAY,MAAMA,qBAAA;AAExB,gBAAI,aAAa,aAAa,SAAS;AACnC,mCAAqB,SAAS;AAAA,YAClC,WAAW,CAAC,aAAa,aAAa,SAAS;AAC3C,qCAAA;AAAA,YACJ;AAAA,UACJ,SAAS,GAAG;AAAA,UAAe;AAAA,QAC/B;AAAA,MACJ;AAAA,IACJ;AAEA,aAAS,iBAAiB,oBAAoB,sBAAsB;AAEpE,WAAO,MAAM;AACT,eAAS,oBAAoB,oBAAoB,sBAAsB;AAAA,IAC3E;AAAA,EACJ,GAAG,CAAC,gBAAgBA,sBAAoB,sBAAsB,sBAAsB,CAAC;AAIrF,QAAMwB,cAAY,YAAY,MAAM;AAChC,WAAOC,UAAQ;AAAA,EACnB,GAAG,CAAA,CAAE;AAGL,YAAU,MAAM;AACZ,WAAO,MAAM;AACT,mBAAa,UAAU;AACvB,UAAI,kBAAkB,SAAS;AAC3B,qBAAa,kBAAkB,OAAO;AAAA,MAC1C;AAAA,IACJ;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAMC,sBAAoB,YAAY,YAAY;AAC9C,QAAI;AACA,UAAI,CAAC,UAAU,SAAS;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AACA,YAAMC,kBAA0B,UAAU,QAAQ,WAAW;AAC7D,6BAAA;AAAA,IACJ,SAAS,OAAgB;AACrB,2BAAqB,KAAc;AACnC,YAAM;AAAA,IACV;AAAA,EACJ,GAAG,CAAC,sBAAsB,CAAC;AAE3B,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,YAAY,cAAc;AAAA,IACtC,qBAAqB,YAAY,uBAAuB;AAAA,IACxD;AAAA,IAAA,WACAH;AAAAA,IACA;AAAA,IACA;AAAA,IAAA,UACArB;AAAAA,IAAA,aACAE;AAAAA,IAAA,YACAE;AAAAA,IACA;AAAA,IAAA,gBACAG;AAAAA,IAAA,eACAE;AAAAA,IAAA,gBACAE;AAAAA,IAAA,eACAE;AAAAA,IAAA,eACAE;AAAAA,IAAA,eACAE;AAAAA,IAAA,mBACAM;AAAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,MACV,oBAAoB;AAAA,MACpB,aAAa,CAAC,CAAE,MAAM;AAAA,MACtB,cAAc,YAAY,uBAAuB;AAAA,MACjD,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,kBAAkB,YAAY,oBAAoB,CAAA;AAAA,IAAC;AAAA,EACvD;AAER;AC5oBA,SAAS,YAAY,SAAwB;AACzC,SAAO;AAAA,IACH,KAAK,QAAQ;AAAA,IACb,OAAO,QAAQ;AAAA,IACf,aAAa,QAAQ,eAAe;AAAA,IACpC,UAAU,QAAQ,YAAY;AAAA,IAC9B,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ,YAAY,IAAI,KAAK,QAAQ,SAAS,IAAI;AAAA,EAAA;AAErE;AAKA,SAAS,YAAY,SAAwB;AACzC,SAAO;AAAA,IACH,IAAI,QAAQ;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,QAAQ,QAAQ,UAAU;AAAA,EAAA;AAElC;AAMO,SAAS,yBAAyB,QAAqD;AAC1F,QAAM,EAAE,QAAQ,QAAQ,cAAc,gBAAgB;AAItD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,CAAA,CAAE;AAC7C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,CAAA,CAAE;AAC7C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAA;AACpC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAA;AAKpC,QAAM,aAAa,YAAY,OAC3B,UACA,SAAS,OACT,MACA,aAAa,GACb,WACe;AACf,QAAI,YAA0B;AAC9B,aAAS,UAAU,GAAG,UAAU,YAAY,WAAW;AACnD,UAAI,QAAQ,SAAS;AACjB,cAAM,QAAQ,IAAI,MAAM,iBAAiB;AACzC,cAAM,OAAO;AACb,cAAM;AAAA,MACV;AAEA,UAAI;AAEA,cAAM,QAAQ,eAAe,MAAM,aAAA,IAAkB,SAAS,MAAM,OAAO,aAAA,IAAiB;AAC5F,cAAM,UAAU,WAAW,QAAQ,UAAU,OAAO,UAAU;AAG9D,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,aAAa,QAAQ,IAAI;AAAA,UAC5D;AAAA,UACA,SAAS;AAAA,YACL,gBAAgB;AAAA,YAChB,GAAI,QAAQ,EAAE,iBAAiB,UAAU,KAAK,OAAO,CAAA;AAAA,UAAC;AAAA,UAE1D,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,UACpC;AAAA,QAAA,CACH;AAED,YAAI,CAAC,SAAS,IAAI;AACd,gBAAM,YAAY,MAAM,SAAS,KAAA;AACjC,cAAI,eAAe;AACnB,cAAI;AACA,kBAAM,YAAY,KAAK,MAAM,SAAS;AACtC,2BAAe,UAAU,OAAO,WAAW;AAAA,UAC/C,SAAS,GAAG;AACR,2BAAe,aAAa,cAAc,SAAS,MAAM;AAAA,UAC7D;AAEA,gBAAM,QAAQ,OAAO,OAAO,IAAI,MAAM,YAAY,GAAG,EAAE,QAAQ,SAAS,QAAQ;AAChF,gBAAM;AAAA,QACV;AAEA,eAAO,MAAM,SAAS,KAAA;AAAA,MAC1B,SAAS,OAAgB;AACrB,YAAI,iBAAiB,SAAS,MAAM,SAAS,gBAAgB,QAAQ,SAAS;AAC1E,gBAAM;AAAA,QACV;AAEA,oBAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAGpE,cAAM,iBAAiB,iBAAiB;AACxC,cAAM,gBAAgB,OAAQ,MAA8B,WAAW,YAAa,MAA6B,UAAU,OAAQ,MAA6B,SAAS;AAEzK,YAAI,UAAU,aAAa,MAAM,kBAAkB,gBAAgB;AAC/D,gBAAM,QAAQ,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAI;AACxD,kBAAQ,KAAK,wBAAwB,QAAQ,wBAAwB,KAAK,OAAO;AAGjF,gBAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AACzC,gBAAI,QAAQ,QAAS,QAAO,OAAO,IAAI,MAAM,YAAY,CAAC;AAC1D,kBAAM,QAAQ,WAAW,SAAS,KAAK;AACvC,gBAAI,QAAQ;AACR,qBAAO,iBAAiB,SAAS,MAAM;AACnC,6BAAa,KAAK;AAClB,uBAAO,IAAI,MAAM,YAAY,CAAC;AAAA,cAClC,GAAG,EAAE,MAAM,MAAM;AAAA,YACrB;AAAA,UACJ,CAAC,EAAE,MAAM,MAAM;AAAA,UAAC,CAAC;AAEjB,cAAI,QAAQ,SAAS;AACjB,kBAAM,aAAa,IAAI,MAAM,iBAAiB;AAC9C,uBAAW,OAAO;AAClB,kBAAM;AAAA,UACV;AACA;AAAA,QACJ;AAEA,gBAAQ,MAAM,kCAAkC,KAAK;AACrD,cAAM;AAAA,MACV;AAAA,IACJ;AACA,UAAM;AAAA,EACV,GAAG,CAAC,QAAQ,YAAY,CAAC;AAKP,cAAY,OAAO,WAAyB;AAC1D,QAAI;AACA,YAAM,OAAO,MAAM,WAAW,UAAU,OAAO,QAAW,GAAG,MAAM;AACnE,eAAS,KAAK,MAAM,IAAI,WAAW,CAAC;AACpC,oBAAc,MAAS;AAAA,IAC3B,SAAS,OAAgB;AACrB,UAAI,iBAAiB,SAAS,MAAM,SAAS,aAAc;AAC3D,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC3E;AAAA,EACJ,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,YAAY,YAAY,OAAO,WAAyB;AAC1D,QAAI;AAEA,YAAM,OAAO,MAAM,WAAW,UAAU,OAAO,QAAW,GAAG,MAAM;AACnE,YAAM,WAAmB,KAAK,MAAM,IAAI,CAAC,MAAe,YAAY,CAAC,CAAC;AACtE,eAAS,QAAQ;AACjB,oBAAc,MAAS;AAAA,IAC3B,SAAS,OAAgB;AACrB,UAAI,iBAAiB,SAAS,MAAM,SAAS,aAAc;AAC3D,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC3E;AAAA,EACJ,GAAG,CAAC,UAAU,CAAC;AAMf,YAAU,MAAM;AAEZ,QAAI,CAAC,aAAa;AACd,iBAAW,KAAK;AAChB;AAAA,IACJ;AAEA,UAAM,kBAAkB,IAAI,gBAAA;AAE5B,UAAM,OAAO,YAAY;AACrB,iBAAW,IAAI;AAEf,UAAI;AACA,cAAM,OAAO,MAAM,WAAW,UAAU,OAAO,QAAW,GAAG,gBAAgB,MAAM;AACnF,iBAAS,KAAK,MAAM,IAAI,WAAW,CAAC;AACpC,sBAAc,MAAS;AAAA,MAC3B,SAAS,OAAgB;AACrB,YAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACvD,kBAAQ,MAAM,yBAAyB,KAAK;AAC5C,wBAAc,KAAK;AAAA,QACvB;AAAA,MACJ;AAEA,UAAI,CAAC,gBAAgB,OAAO,SAAS;AACjC,cAAM,UAAU,gBAAgB,MAAM;AAAA,MAC1C;AAEA,UAAI,CAAC,gBAAgB,OAAO,SAAS;AACjC,mBAAW,KAAK;AAAA,MACpB;AAAA,IACJ;AACA,SAAA;AAEA,WAAO,MAAM;AACT,sBAAgB,MAAA;AAAA,IACpB;AAAA,EACJ,GAAG,CAAC,aAAa,YAAY,SAAS,CAAC;AAMvC,QAAM,cAAc,YAAY,OAAO,YAOU;AAC7C,UAAM,SAAS,IAAI,gBAAA;AACnB,QAAI,QAAQ,UAAU,OAAW,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAC1E,QAAI,QAAQ,WAAW,OAAW,QAAO,IAAI,UAAU,OAAO,QAAQ,MAAM,CAAC;AAC7E,QAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACvD,QAAI,QAAQ,QAAS,QAAO,IAAI,WAAW,QAAQ,OAAO;AAC1D,QAAI,QAAQ,SAAU,QAAO,IAAI,YAAY,QAAQ,QAAQ;AAC7D,QAAI,QAAQ,OAAQ,QAAO,IAAI,QAAQ,QAAQ,MAAM;AACrD,UAAM,KAAK,OAAO,SAAA;AAElB,UAAM,OAAO,MAAM,WAAW,YAAY,KAAK,MAAM,KAAK,KAAK,KAAK;AACpE,WAAO;AAAA,MACH,OAAO,KAAK,MAAM,IAAI,CAAC,MAAe,YAAY,CAAC,CAAC;AAAA,MACpD,OAAO,KAAK;AAAA,IAAA;AAAA,EAEpB,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,WAAW,YAAY,OAAO,SAA8B;AAC9D,UAAM,UAAU,KAAK,SAAS,CAAA;AAG9B,UAAM,eAAe,MAAM,KAAK,OAAK,EAAE,QAAQ,KAAK,GAAG;AAEvD,QAAI,cAAc;AAEd,YAAM,OAAO,MAAM,WAAW,UAAU,KAAK,GAAG,IAAI,OAAO;AAAA,QACvD,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,OAAO;AAAA,MAAA,CACV;AACD,YAAM,UAAU,YAAY,KAAK,IAAI;AACrC,eAAS,CAAA,SAAQ,KAAK,IAAI,CAAA,MAAK,EAAE,QAAQ,QAAQ,MAAM,UAAU,CAAC,CAAC;AACnE,aAAO;AAAA,IACX,OAAO;AAEH,YAAM,OAAO,MAAM,WAAW,UAAU,QAAQ;AAAA,QAC5C,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,OAAO;AAAA,MAAA,CACV;AACD,YAAM,UAAU,YAAY,KAAK,IAAI;AACrC,eAAS,CAAA,SAAQ,CAAC,GAAG,MAAM,OAAO,CAAC;AACnC,aAAO;AAAA,IACX;AAAA,EACJ,GAAG,CAAC,YAAY,OAAO,KAAK,CAAC;AAM7B,QAAM,aAAa,YAAY,OAAO,SAIhC;AACF,UAAM,UAAU,KAAK,SAAS,CAAA;AAE9B,UAAM,OAAO,MAAM,WAAW,UAAU,QAAQ;AAAA,MAC5C,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,OAAO;AAAA,IAAA,CACV;AACD,UAAM,UAAU,YAAY,KAAK,IAAI;AAErC,aAAS,CAAA,SAAQ,CAAC,GAAG,MAAM,OAAO,CAAC;AACnC,WAAO;AAAA,MACH,MAAM;AAAA,MACN,gBAAgB,KAAK,kBAAkB;AAAA,MACvC,mBAAmB,KAAK;AAAA,IAAA;AAAA,EAEhC,GAAG,CAAC,YAAY,KAAK,CAAC;AAKtB,QAAMd,iBAAgB,YAAY,OAAO,SAInC;AACF,UAAM,OAAO,MAAM,WAAW,UAAU,KAAK,GAAG,mBAAmB,MAAM;AACzE,UAAM,cAAc,YAAY,KAAK,IAAI;AACzC,aAAS,CAAA,SAAQ,KAAK,IAAI,CAAA,MAAK,EAAE,QAAQ,YAAY,MAAM,cAAc,CAAC,CAAC;AAC3E,WAAO;AAAA,MACH,MAAM;AAAA,MACN,gBAAgB,KAAK,kBAAkB;AAAA,MACvC,mBAAmB,KAAK;AAAA,IAAA;AAAA,EAEhC,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,aAAa,YAAY,OAAO,SAA8B;AAChE,UAAM,WAAW,UAAU,KAAK,GAAG,IAAI,QAAQ;AAC/C,aAAS,CAAA,SAAQ,KAAK,OAAO,CAAA,MAAK,EAAE,QAAQ,KAAK,GAAG,CAAC;AAAA,EACzD,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,WAAW,YAAY,OAAO,SAA8B;AAE9D,UAAM,eAAe,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE;AAErD,QAAI,cAAc;AAEd,YAAM,OAAO,MAAM,WAAW,UAAU,KAAK,EAAE,IAAI,OAAO;AAAA,QACtD,MAAM,KAAK;AAAA,QACX,SAAS,KAAK;AAAA,QACd,QAAQ,KAAK;AAAA,MAAA,CAChB;AACD,YAAM,UAAU,YAAY,KAAK,IAAI;AACrC,eAAS,CAAA,SAAQ,KAAK,IAAI,CAAA,MAAK,EAAE,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC;AAAA,IACrE,OAAO;AAEH,YAAM,OAAO,MAAM,WAAW,UAAU,QAAQ;AAAA,QAC5C,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,SAAS,KAAK,WAAW;AAAA,QACzB,QAAQ,KAAK;AAAA,MAAA,CAChB;AACD,YAAM,UAAU,YAAY,KAAK,IAAI;AACrC,eAAS,CAAA,SAAQ,CAAC,GAAG,MAAM,OAAO,CAAC;AAAA,IACvC;AAAA,EACJ,GAAG,CAAC,YAAY,KAAK,CAAC;AAKtB,QAAM,aAAa,YAAY,OAAO,SAA8B;AAChE,UAAM,WAAW,UAAU,KAAK,EAAE,IAAI,QAAQ;AAC9C,aAAS,CAAA,SAAQ,KAAK,OAAO,CAAA,MAAK,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,EACvD,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,UAAU,YAAY,CAAC,QAA6B;AACtD,WAAO,MAAM,KAAK,CAAA,MAAK,EAAE,QAAQ,GAAG,KAAK;AAAA,EAC7C,GAAG,CAAC,KAAK,CAAC;AAKV,QAAM,iBAAiB,YAAY,OAAO,SAA4C;AAElF,UAAM,eAAe,MAAM,KAAK,CAAA,MAAK,EAAE,QAAQ,KAAK,OAAO,EAAE,UAAU,KAAK,KAAK;AACjF,QAAI,CAAC,aAAc,QAAO;AAG1B,UAAM,cAAc,aAAa,SAAS,CAAA;AAC1C,WAAO,MAAM,OAAO,CAAA,MAAK,YAAY,SAAS,EAAE,EAAE,CAAC;AAAA,EACvD,GAAG,CAAC,OAAO,KAAK,CAAC;AAKjB,QAAM,UAAU,aAAa,OAAO,SAAS,OAAO,KAAK;AAMzD,QAAM,iBAAiB,YAAY,YAA2B;AAC1D,QAAI;AACA,YAAM,WAAW,cAAc,MAAM;AAErC,YAAM,OAAO,MAAM,WAAW,QAAQ;AACtC,YAAM,cAAc,KAAK,MAAM,IAAI,WAAW;AAC9C,eAAS,WAAW;AACpB,YAAM,UAAA;AAAA,IACV,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM;AAAA,IACV;AAAA,EACJ,GAAG,CAAC,YAAY,SAAS,CAAC;AAE1B,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,2BAA2B;AAAA,IAC3B,oCAAoC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAER;AC7bO,SAAS,gBAAgB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA,gBAAgB;AAAA,EAChB;AACJ,GAAyB;AAErB,QAAM,YAAY,kBAAA;AAClB,QAAM,EAAE,MAAM,WAAW,SAAS,iBAAiB;AACnD,QAAM,EAAE,EAAA,IAAM,eAAA;AAEd,QAAM,CAAC,MAAM,OAAO,IAAI,SAAmB,SAAS;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,IAAI;AAEnD,QAAM,aAAa,CAAC,YAAsB;AACtC,mBAAe,KAAK;AACpB,eAAW,MAAM;AACb,cAAQ,OAAO;AACf,qBAAe,IAAI;AAAA,IACvB,GAAG,GAAG;AAAA,EACV;AAGA,QAAM,kBAAkB,eAAe;AAEvC,YAAU,MAAM;AACZ,UAAM,QAAQ,WAAW,MAAM,UAAU,IAAI,GAAG,EAAE;AAClD,WAAO,MAAM,aAAa,KAAK;AAAA,EACnC,GAAG,CAAA,CAAE;AAEL,WAAS,iBAAiB;AACtB,QAAI,CAAC,eAAe,kBAAmB,QAAO;AAC9C,QAAI,eAAe,QAAQ,KAAM,QAAO;AACxC,WACI,oBAAC,OAAA,EAAI,WAAU,UACX,UAAA,oBAAC,WAAA,EAAU,OAAO,eAAe,kBAAkB,WAAW,eAAe,kBAAA,CAAkB,GACnG;AAAA,EAER;AAEA,MAAI;AACJ,MAAI,MAAM;AACN,oBAAgB;AAAA,MAAC;AAAA,MAAA;AAAA,QAAI,KAAK;AAAA,QACtB,OAAO;AAAA,UACH,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,QAAA;AAAA,QAEf,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACb,OAAO;AACH,wCAAiB,YAAA,EAAU;AAAA,EAC/B;AAEA,MAAI;AACJ,MAAI,iBAAiB;AACjB,QAAI,OAAO,oBAAoB,UAAU;AACrC,0BAAoB;AAAA,IACxB,WAAW,2BAA2B,OAAO;AACzC,0BAAoB,gBAAgB;AAAA,IACxC,OAAO;AACH,0BAAoB;AAAA,IACxB;AAAA,EACJ;AAEA,QAAM,mBAAmB,CAAC,uBAAuB,eAAe;AAEhE,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,WAAW;AAAA,QACP;AAAA,QACA,SAAS,gBAAgB;AAAA,MAAA;AAAA,MAI7B,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,uDACX,UAAA;AAAA,UAAA,oBAAC,gBAAA,EAAc;AAAA,UACf;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,SAAS;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACN,OAAM;AAAA,kBACN,cAAW;AAAA,kBACV,UAAA,cAAc,SACT,oBAAC,UAAA,EAAS,MAAM,SAAS,MAAA,CAAM,IAC/B,oBAAC,SAAA,EAAQ,MAAM,SAAS,MAAA,CAAM;AAAA,gBAAA;AAAA,cAAA;AAAA,cAExC,UAAA;AAAA,gBAAA,qBAAC,UAAA,EAAS,SAAS,MAAM,aAAa,MAAM,GAAG,UAAA;AAAA,kBAAA,oBAAC,UAAA,EAAS,MAAM,SAAS,SAAA,CAAS;AAAA,kBAAE;AAAA,kBAAE,EAAE,WAAW;AAAA,gBAAA,GAAE;AAAA,qCACnG,UAAA,EAAS,SAAS,MAAM,aAAa,OAAO,GAAG,UAAA;AAAA,kBAAA,oBAAC,SAAA,EAAQ,MAAM,SAAS,SAAA,CAAS;AAAA,kBAAE;AAAA,kBAAE,EAAE,YAAY;AAAA,gBAAA,GAAE;AAAA,qCACpG,UAAA,EAAS,SAAS,MAAM,aAAa,QAAQ,GAAG,UAAA;AAAA,kBAAA,oBAAC,aAAA,EAAY,MAAM,SAAS,SAAA,CAAS;AAAA,kBAAE;AAAA,kBAAE,EAAE,aAAa;AAAA,gBAAA,EAAA,CAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAC/G,GACJ;AAAA,QAEA,qBAAC,OAAA,EAAI,WAAU,+DAEX,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,sBACV,UAAA,eACL;AAAA,UAEC,yCACI,OAAA,EAAI,WAAU,cACX,UAAA,oBAAC,WAAA,EAAU,OAAO,kBAAA,CAAkB,EAAA,CACxC;AAAA,UAGH,SAAS,YAAY,eAAA;AAAA,UAEtB,qBAAC,SAAI,WAAW;AAAA,YACZ;AAAA,YACA,cAAc,gBAAgB;AAAA,UAAA,GAG7B,UAAA;AAAA,YAAA,mBAAmB,CAAC,eAAe,QAChC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG;AAAA,gBACA,kBAAkB;AAAA,gBAClB,SAAS,MAAM;AAAA,gBAAC;AAAA,gBAChB,kBAAkB,MAAM;AAAA,gBAAC;AAAA,gBACzB;AAAA,gBACA,qBAAqB;AAAA,gBACrB,eAAe;AAAA,cAAA;AAAA,YAAA;AAAA,YAKtB,CAAC,mBACE,qBAAA,UAAA,EAEK,UAAA;AAAA,cAAA,SAAS,aACN,qBAAC,OAAA,EAAI,WAAU,mCACX,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG;AAAA,oBACA,MAAM;AAAA,oBACN,0BAAO,UAAA,EAAQ;AAAA,oBACf,SAAS,MAAM,WAAW,OAAO;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEpC,iBAAiB,kBACd;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG;AAAA,oBACA;AAAA,oBACA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGP,oBACG;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG,WAAU;AAAA,oBACV,SAAQ;AAAA,oBACR,OAAM;AAAA,oBACN,MAAK;AAAA,oBACL,SAAS,MAAM,WAAW,UAAU;AAAA,oBACvC,UAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAED,GAER;AAAA,cAIH,SAAS,WACN;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACG;AAAA,kBACA,kBAAkB;AAAA,kBAClB,SAAS,MAAM,WAAW,SAAS;AAAA,kBACnC,kBAAkB,MAAM,WAAW,QAAQ;AAAA,kBAC3C;AAAA,kBACA;AAAA,kBACA,kBAAkB,mBAAmB,MAAM,WAAW,UAAU,IAAI;AAAA,gBAAA;AAAA,cAAA;AAAA,cAK3E,SAAS,cACN;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACG;AAAA,kBACA,kBAAkB;AAAA,kBAClB,SAAS,MAAM,WAAW,SAAS;AAAA,kBACnC,kBAAkB,MAAM,WAAW,QAAQ;AAAA,kBAC3C;AAAA,kBACA;AAAA,kBACA,eAAe,MAAM,WAAW,OAAO;AAAA,gBAAA;AAAA,cAAA;AAAA,cAK9C,SAAS,YACN;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACG;AAAA,kBACA,SAAS,MAAM,WAAW,OAAO;AAAA,gBAAA;AAAA,cAAA;AAAA,YACrC,EAAA,CAER;AAAA,UAAA,EAAA,CAER;AAAA,QAAA,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGZ;AAEA,SAAS,YAAY;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAqF;AACjF,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG;AAAA,MACA,WAAU;AAAA,MACV,SAAQ;AAAA,MACR,MAAK;AAAA,MACL;AAAA,MACA,UAAA,qBAAC,OAAA,EAAI,WAAU,sDACX,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,4CACX,UAAA,MACL;AAAA,QACA,oBAAC,YAAA,EAAW,SAAQ,UAAU,UAAA,KAAA,CAAK;AAAA,MAAA,EAAA,CACvC;AAAA,IAAA;AAAA,EAAA;AAGZ;AAEA,MAAM,aAAa,MACf,qBAAC,OAAA,EAAI,SAAQ,aAAY,OAAM,MAAK,QAAO,MACvC,UAAA;AAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,MAAK;AAAA,MACP,GAAE;AAAA,IAAA;AAAA,EAAA;AAAA,EACN;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,MAAK;AAAA,MACP,GAAE;AAAA,IAAA;AAAA,EAAA;AAAA,EACN;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,MAAK;AAAA,MACP,GAAE;AAAA,IAAA;AAAA,EAAA;AAAA,EACN;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,MAAK;AAAA,MACP,GAAE;AAAA,IAAA;AAAA,EAAA;AAAqI,GAC/I;AAGJ,SAAS,kBAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACJ,GAIG;AACC,QAAM,iBAAiB,OAAY,IAAI;AAEvC,YAAU,MAAM;AACZ,UAAM,SAAU,OAAe;AAC/B,QAAI,CAAC,UAAU,eAAe,QAAS;AAEvC,mBAAe,UAAU,OAAO,SAAS,OAAO,gBAAgB;AAAA,MAC5D,WAAW;AAAA,MACX,OAAO;AAAA,MACP,UAAU,OAAO,aAAwD;AACrE,YAAI,SAAS,SAAS,CAAC,SAAS,cAAc;AAC1C,kBAAQ,MAAM,uBAAuB,SAAS,KAAK;AACnD;AAAA,QACJ;AACA,YAAI;AACA,gBAAM,eAAe,YAAY,SAAS,cAAc,aAAa;AAAA,QACzE,SAAS,KAAc;AACnB,kBAAQ,MAAM,uBAAuB,GAAG;AAAA,QAC5C;AAAA,MACJ;AAAA,IAAA,CACH;AAAA,EACL,GAAG,CAAC,gBAAgB,cAAc,CAAC;AAEnC,QAAM,cAAc,MAAM;AACtB,QAAI,CAAC,eAAe,SAAS;AACzB,cAAQ,MAAM,2BAA2B;AACzC;AAAA,IACJ;AACA,mBAAe,QAAQ,mBAAA;AAAA,EAC3B;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG;AAAA,MACA,MAAK;AAAA,MACL,0BAAO,YAAA,EAAU;AAAA,MACjB,SAAS;AAAA,IAAA;AAAA,EAAA;AAGrB;AAEA,SAAS,UAAU;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AACJ,GAUG;AACC,QAAM,cAAc,OAAgC,IAAI;AAExD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAA;AAC1B,QAAM,CAAC,UAAU,WAAW,IAAI,SAAA;AAChC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAA;AAEtC,YAAU,MAAM;AACZ,QAAI,CAAC,SAAU;AACf,UAAM,cAAc,CAAC,UAAyB;AAC1C,UAAI,MAAM,YAAY,IAAI;AACtB,gBAAA;AAAA,MACJ;AAAA,IACJ;AACA,aAAS,iBAAiB,WAAW,aAAa,KAAK;AACvD,WAAO,MAAM;AACT,eAAS,oBAAoB,WAAW,aAAa,KAAK;AAAA,IAC9D;AAAA,EACJ,GAAG,CAAC,OAAO,CAAC;AAEZ,WAAS,sBAAsB;AAC3B,QAAI,SAAS,UAAU;AACnB,qBAAe,mBAAmB,OAAO,QAAQ;AAAA,IACrD;AAAA,EACJ;AAEA,WAAS,qBAAqB;AAC1B,QAAI,SAAS,UAAU;AACnB,qBAAe,SAAS,OAAO,UAAU,WAAW;AAAA,IACxD;AAAA,EACJ;AAEA,QAAM,eAAe,CAAC,UAA2B;AAC7C,UAAM,eAAA;AACN,QAAI;AACA,yBAAA;AAAA;AAEA,0BAAA;AAAA,EACR;AAEA,QAAM,QAAQ,gBACR,aACA,mBACI,mBACA;AAEV,QAAM,WAAW,gBACX,uFACA,mBACI,iDACA;AAEV,QAAM,cAAc,mBAAmB,mBAAmB;AAE1D,SACI,qBAAC,QAAA,EAAK,UAAU,cAAc,WAAU,mCACnC,UAAA;AAAA,IAAA,CAAC,iBACE,oBAAC,OAAA,EAAI,WAAU,uBACX,UAAA,oBAAC,YAAA,EAAW,SAAS,SACjB,UAAA,oBAAC,eAAA,CAAA,CAAa,EAAA,CAClB,GACJ;AAAA,wBAGH,YAAA,EAAW,SAAQ,MAAK,WAAU,UAC9B,UAAA,OACL;AAAA,IACA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QACnD,UAAA,SAAA,CACL;AAAA,IAEC,oBAAoB,mBACjB,oBAAC,OAAA,EAAI,WAAU,eACV,UAAA,iBACL;AAAA,IAGH,oBACG,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,MAAA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QAAO,UAAA,eAAA,CAE/D;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAU,aAAY;AAAA,UACnB,WAAU;AAAA,UACV,OAAO,eAAe;AAAA,UACtB,UAAU,eAAe;AAAA,UACzB,MAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU,CAAC,UAAU,eAAe,MAAM,OAAO,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAAE,GAChE;AAAA,IAGJ,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,MAAA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QAAO,UAAA,QAAA,CAE/D;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAU,aAAY;AAAA,UACnB,WAAU;AAAA,UACV,WAAS;AAAA,UACT,OAAO,SAAS;AAAA,UAChB,UAAU,eAAe;AAAA,UACzB,MAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAAE,GAC1D;AAAA,IAEA,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,MAAA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QAAO,UAAA,WAAA,CAE/D;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAU,aAAY;AAAA,UACnB,WAAU;AAAA,UACV,OAAO,YAAY;AAAA,UACnB,UAAU,eAAe;AAAA,UACzB,UAAU;AAAA,UACV,MAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU,CAAC,UAAU,YAAY,MAAM,OAAO,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAAE,GAC7D;AAAA,IAEC,wCACI,YAAA,EAAW,SAAQ,WAAU,OAAM,aAAY,WAAU,QAAO,UAAA,yEAAA,CAEjE;AAAA,IAGH,CAAC,oBACE,oBAAC,OAAA,EAAI,WAAU,0BACX,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAK;AAAA,QACL,WAAW;AAAA,UACP;AAAA,UACA;AAAA,QAAA;AAAA,QAEJ,SAAS;AAAA,QACZ,UAAA;AAAA,MAAA;AAAA,IAAA,GAGL;AAAA,IAGJ;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,WAAU;AAAA,QACV,MAAK;AAAA,QACL,SAAS,eAAe;AAAA,QACxB,UAAU,eAAe,eAAe,CAAC,SAAS,CAAC;AAAA,QAElD,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAIJ,oBACG,oBAAC,OAAA,EAAI,WAAU,oBACX,+BAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,aAAY,UAAA;AAAA,MAAA;AAAA,MACd;AAAA,MAC5B;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,MAAK;AAAA,UACL,WAAW;AAAA,YACP;AAAA,YACA;AAAA,UAAA;AAAA,UAEJ,SAAS;AAAA,UACZ,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACJ,EAAA,CACJ;AAAA,IAGH,iBACG,oBAAC,OAAA,EAAI,WAAU,oBACX,+BAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,aAAY,UAAA;AAAA,MAAA;AAAA,MACjB;AAAA,MACzB;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,MAAK;AAAA,UACL,WAAW;AAAA,YACP;AAAA,YACA;AAAA,UAAA;AAAA,UAEJ,SAAS;AAAA,UACZ,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACJ,EAAA,CACJ;AAAA,EAAA,GAER;AAER;AAEA,SAAS,mBAAmB;AAAA,EACxB;AAAA,EACA;AACJ,GAGG;AACC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,EAAE;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,YAAU,MAAM;AACZ,QAAI,CAAC,SAAU;AACf,UAAM,cAAc,CAAC,UAAyB;AAC1C,UAAI,MAAM,YAAY,IAAI;AACtB,gBAAA;AAAA,MACJ;AAAA,IACJ;AACA,aAAS,iBAAiB,WAAW,aAAa,KAAK;AACvD,WAAO,MAAM;AACT,eAAS,oBAAoB,WAAW,aAAa,KAAK;AAAA,IAC9D;AAAA,EACJ,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,eAAe,OAAO,UAA2B;AACnD,UAAM,eAAA;AACN,aAAS,IAAI;AAEb,QAAI,CAAC,OAAO;AACR,eAAS,iCAAiC;AAC1C;AAAA,IACJ;AAEA,QAAI;AACA,YAAM,eAAe,eAAe,KAAK;AACzC,mBAAa,IAAI;AAAA,IACrB,SAAS,KAAc;AAEnB,UAAI,eAAe,SAAU,IAA0B,SAAS,wBAAwB;AACpF,iBAAS,qEAAqE;AAAA,MAClF,OAAO;AAEH,qBAAa,IAAI;AAAA,MACrB;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,WAAW;AACX,WACI,qBAAC,OAAA,EAAI,WAAU,mCACX,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,kBACX,UAAA,oBAAC,YAAA,EAAW,SAAS,SACjB,UAAA,oBAAC,eAAA,CAAA,CAAa,EAAA,CAClB,GACJ;AAAA,MAEA,qBAAC,SAAI,WAAW;AAAA,QACZ;AAAA,QACA;AAAA,MAAA,GAEA,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAI,WAAU,iBAAgB,UAAA,MAAE;AAAA,4BAChC,YAAA,EAAW,SAAQ,aAAY,WAAU,QAAO,UAAA,oBAEjD;AAAA,QACA,qBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,aAAY,UAAA;AAAA,UAAA;AAAA,UACjB,oBAAC,YAAQ,UAAA,MAAA,CAAM;AAAA,UAAS;AAAA,QAAA,EAAA,CACrD;AAAA,MAAA,GACJ;AAAA,MAEA,oBAAC,UAAO,SAAS,SAAS,SAAQ,QAAO,WAAU,QAAO,UAAA,kBAAA,CAE1D;AAAA,IAAA,GACJ;AAAA,EAER;AAEA,SACI,qBAAC,QAAA,EAAK,UAAU,cAAc,WAAU,mCACpC,UAAA;AAAA,IAAA,oBAAC,OAAA,EAAI,WAAU,uBACP,UAAA,oBAAC,YAAA,EAAW,SAAS,SACjB,UAAA,oBAAC,eAAA,CAAA,CAAa,EAAA,CACtB,GACJ;AAAA,wBAEC,YAAA,EAAW,SAAQ,MAAK,WAAU,UAAS,UAAA,kBAE5C;AAAA,IACA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QAAO,UAAA,oDAAA,CAE/D;AAAA,IAEC,6BACI,OAAA,EAAI,WAAU,eACX,UAAA,oBAAC,WAAA,EAAU,OAAa,EAAA,CAC5B;AAAA,IAGJ,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,MAAA,oBAAC,cAAW,SAAQ,SAAQ,OAAM,aAAY,WAAU,QAAO,UAAA,QAAA,CAE/D;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,aAAY;AAAA,UACZ,WAAU;AAAA,UACV,WAAS;AAAA,UACT,OAAO;AAAA,UACP,MAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IACpD,GACJ;AAAA,IAEA;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,WAAU;AAAA,QACV,MAAK;AAAA,QACL,SAAS,eAAe;AAAA,QACxB,UAAU,eAAe,eAAe,CAAC;AAAA,QAC5C,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GACJ;AAER;AC7qBO,SAAS,WAAW,EAAE,aAA+B;AACxD,QAAM,WAAW,0BAAA;AACjB,QAAM,gBAAgB,OAAO,KAAK;AAElC,kBAAgB,MAAM;AAClB,aAAS,aAAa,EAAE,WAAW;AACnC,kBAAc,UAAU;AACxB,WAAO,MAAM;AACT,oBAAc,UAAU;AACxB,eAAS,eAAA;AAAA,IACb;AAAA,EACJ,GAAG,CAAC,UAAU,SAAS,CAAC;AAExB,SAAO;AACX;ACCO,SAAS,+BAA+B,EAAE,gBAAgB,QAAQ,cAAc,cAAc,CAAA,KAAkC;AACnI,SAAO;AAAA,IACH;AAAA,MACI,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM,oBAAC,WAAA,EAAU,gBAAgC,QAAgB,aAAA,CAA2B;AAAA,IAAA;AAAA,IAEhG;AAAA,MACI,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM,oBAAC,WAAA,EAAU,gBAAgC,YAAA,CAAyB;AAAA,IAAA;AAAA,EAC9E;AAER;AAKA,SAAS,SAAS,EAAE,QAAwB;AACxC,MAAI;AACJ,MAAI,KAAK,SAAS;AACd,kBAAc;AAAA,EAClB,WAAW,KAAK,OAAO,UAAU;AAC7B,kBAAc;AAAA,EAClB,WAAW,KAAK,OAAO,UAAU;AAC7B,kBAAc;AAAA,EAClB,OAAO;AACH,kBAAc,sBAAsB,KAAK,EAAE;AAAA,EAC/C;AAEA,6BACK,MAAA,EAAK,aACD,UAAA,KAAK,KAAA,GAD2B,KAAK,EAE1C;AAER;AAKO,SAAS,UAAU,EAAE,gBAAgB,QAAQ,gBAIjD;AACC,QAAM,EAAE,OAAO,OAAO,UAAU,YAAY,YAAY;AACxD,QAAM,aAAa,gBAAgB,iBAAkB,eAA0C,aAAa;AAC5G,QAAM,qBAAqB,sBAAA;AAC3B,QAAM,EAAE,MAAM,aAAA,IAAiB,kBAAA;AAE/B,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAA;AACxC,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAChE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAA;AACxC,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAC9D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,CAAC;AACxC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AAGxD,QAAM,WAAW,MAAM,KAAK,CAAA,MAAK,EAAE,OAAO,SAAS,OAAO,CAAC;AAE3D,QAAM,kBAAkB,YAAY;AAChC,qBAAiB,IAAI;AACrB,QAAI;AACA,YAAM,QAAQ,MAAM,aAAA;AACpB,YAAM,WAAW,MAAM,MAAM,GAAG,MAAM,wBAAwB;AAAA,QAC1D,QAAQ;AAAA,QACR,SAAS;AAAA,UACL,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,KAAK;AAAA,QAAA;AAAA,MACpC,CACH;AACD,YAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,UAAI,CAAC,SAAS,IAAI;AACd,cAAM,IAAI,MAAM,KAAK,OAAO,WAAW,kBAAkB;AAAA,MAC7D;AACA,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS;AAAA,MAAA,CAAuC;AAEpC,aAAO,SAAS,OAAA;AAAA,IACpB,SAAS,OAAgB;AACrB,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,CAA6B;AAAA,IACvE,UAAA;AACI,uBAAiB,KAAK;AAAA,IAC1B;AAAA,EACJ;AAEA,QAAM,gBAAgB,MAAM;AACxB,oBAAgB,MAAS;AACzB,eAAW,CAAA,MAAK,IAAI,CAAC;AACrB,kBAAc,IAAI;AAAA,EACtB;AAEA,QAAM,iBAAiB,CAAC,SAAe;AACnC,oBAAgB,IAAI;AACpB,kBAAc,IAAI;AAAA,EACtB;AAEA,QAAM,cAAc,MAAM;AACtB,kBAAc,KAAK;AACnB,oBAAgB,MAAS;AAAA,EAC7B;AAEA,QAAM,eAAe,YAAY;AAC7B,QAAI,CAAC,aAAc;AACnB,wBAAoB,IAAI;AACxB,QAAI;AACA,YAAM,WAAW,YAAY;AAC7B,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS;AAAA,MAAA,CAA6B;AAC1B,2BAAqB,KAAK;AAC1B,sBAAgB,MAAS;AAAA,IAC7B,SAAS,OAAgB;AACrB,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,CAAuB;AAAA,IACjE,UAAA;AACI,0BAAoB,KAAK;AAAA,IAC7B;AAAA,EACJ;AAEA,MAAI,SAAS;AACT,WAAO,oBAAC,cAAA,EAAa,UAAA,oBAAC,kBAAA,CAAA,CAAgB,GAAE;AAAA,EAC5C;AAEA,SACI,qBAAC,WAAA,EAAU,WAAU,mCAAkC,UAAU,OAE5D,UAAA;AAAA,IAAA,CAAC,YAAY,CAAC,cAAc,gBACzB,qBAAC,OAAA,EAAI,WAAU,kIACX,UAAA;AAAA,MAAA,oBAAC,OAAA,EACG,8BAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,wCAAuC,mEAE7E,EAAA,CACJ;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,SAAS;AAAA,UACT,UAAU;AAAA,UAET,UAAA,gBAAgB,oBAAC,kBAAA,EAAiB,MAAK,SAAO,IAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IACxD,GACJ;AAAA,IAGJ,qBAAC,OAAA,EAAI,WAAU,2BACX,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,cAAY,MAAC,SAAQ,MAAK,WAAU,QAAO,WAAU,MAAK,UAAA,QAAA,CAEtE;AAAA,MACA,oBAAC,UAAO,WAAW,oBAAC,YAAQ,GAAI,SAAS,eAAe,UAAA,WAAA,CAExD;AAAA,IAAA,GACJ;AAAA,wBAEC,OAAA,EAAI,WAAU,iBACX,UAAA,qBAAC,OAAA,EAAM,WAAU,UACb,UAAA;AAAA,MAAA,qBAAC,aAAA,EACG,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAU,QAAM,MAAC,WAAU,iBAAgB;AAAA,QAC5C,oBAAC,WAAA,EAAU,QAAM,MAAC,UAAA,SAAK;AAAA,QACvB,oBAAC,WAAA,EAAU,QAAM,MAAC,UAAA,QAAI;AAAA,QACtB,oBAAC,WAAA,EAAU,QAAM,MAAC,UAAA,QAAA,CAAK;AAAA,MAAA,GAC3B;AAAA,2BACC,WAAA,EACI,UAAA;AAAA,QAAA,MAAM,IAAI,UACP,qBAAC,UAAA,EAAwB,SAAS,MAAM,eAAe,IAAI,GACvD,UAAA;AAAA,UAAA,oBAAC,WAAA,EAAU,OAAO,EAAE,OAAO,OAAA,GACvB,UAAA,oBAAC,SAAA,EAAQ,SAAO,MAAC,OAAM,oBACnB,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,MAAK;AAAA,cACL,SAAS,CAAC,MAAM;AACZ,kBAAE,gBAAA;AACF,gCAAgB,IAAI;AACpB,qCAAqB,IAAI;AAAA,cAC7B;AAAA,cACA,8BAAC,YAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA,GAEnB,EAAA,CACJ;AAAA,UACA,oBAAC,WAAA,EAAW,UAAA,KAAK,MAAA,CAAM;AAAA,UACvB,oBAAC,WAAA,EAAU,WAAU,eAAe,eAAK,aAAY;AAAA,UACrD,oBAAC,WAAA,EACG,UAAA,oBAAC,OAAA,EAAI,WAAU,wBACV,UAAA,KAAK,OAAO,IAAI,CAAC,WAAmB;AACjC,kBAAM,OAAO,MAAM,KAAK,CAAA,MAAK,EAAE,OAAO,MAAM;AAC5C,mBAAO,2BAAQ,UAAA,EAAsB,KAAA,GAAR,MAAmB,IAAK,oBAAC,QAAA,EAAmB,UAAA,OAAA,GAAT,MAAgB;AAAA,UACpF,CAAC,GACL,EAAA,CACJ;AAAA,QAAA,KAvBW,KAAK,GAwBpB,CACH;AAAA,QAEA,MAAM,WAAW,KACd,oBAAC,UAAA,EACG,UAAA,oBAAC,WAAA,EAAU,SAAS,GAChB,UAAA,qBAAC,cAAA,EAAa,WAAU,yCACpB,UAAA;AAAA,UAAA,oBAAC,YAAA,EAAW,SAAQ,SACf,UAAA,aACK,4CACA,0BACV;AAAA,UACC,cACG,oBAAC,YAAA,EAAW,SAAQ,WAAU,WAAU,oBAAmB,UAAA,+DAAA,CAE3D;AAAA,QAAA,EAAA,CAER,GACJ,EAAA,CACJ;AAAA,MAAA,EAAA,CAER;AAAA,IAAA,EAAA,CACJ,EAAA,CACJ;AAAA,IAGA;AAAA,MAAC;AAAA,MAAA;AAAA,QAEG,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MALK,cAAc,OAAO,OAAO,OAAO;AAAA,IAAA;AAAA,IAS5C;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAM;AAAA,QACN,SAAS;AAAA,QACT,UAAU;AAAA,QACV,UAAU,MAAM;AAAE,+BAAqB,KAAK;AAAG,0BAAgB,MAAS;AAAA,QAAG;AAAA,QAC3E,uCAAS,UAAA,UAAA,CAAO;AAAA,QAChB,sCAAQ,UAAA,6CAAA,CAA0C;AAAA,MAAA;AAAA,IAAA;AAAA,EACtD,GACJ;AAER;AAKA,SAAS,gBAAgB;AAAA,EACrB;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACJ,GAMG;AACC,QAAM,qBAAqB,sBAAA;AAC3B,QAAM,YAAY,CAAC;AAEnB,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,UAAU,eAAe,EAAE;AAC1E,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,UAAU,SAAS,EAAE;AACxD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI;AAAA,IAC1C,UAAU,SAAS,CAAC,QAAQ;AAAA,EAAA;AAEhC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAmE,CAAA,CAAE;AACjG,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAEhD,QAAM,WAAW,MAAM;AACnB,UAAM,YAA2B,CAAA;AACjC,QAAI,CAAC,YAAa,WAAU,cAAc;AAC1C,QAAI,CAAC,MAAO,WAAU,QAAQ;AAAA,aACrB,CAAC,eAAe,KAAK,KAAK,aAAa,QAAQ;AACxD,QAAI,gBAAgB,WAAW,EAAG,WAAU,QAAQ;AACpD,cAAU,SAAS;AACnB,WAAO,OAAO,KAAK,SAAS,EAAE,WAAW;AAAA,EAC7C;AAEA,QAAM,eAAe,OAAO,MAAuB;AAC/C,MAAE,eAAA;AACF,mBAAe,CAAA,MAAK,IAAI,CAAC;AAEzB,QAAI,CAAC,WAAY;AAEjB,oBAAgB,IAAI;AACpB,QAAI;AACA,YAAM,aAAmB;AAAA,QACrB,KAAK,UAAU,OAAO,OAAO,WAAA;AAAA,QAC7B;AAAA,QACA,aAAa,eAAe;AAAA,QAC5B,UAAU,UAAU,YAAY;AAAA,QAChC,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,OAAO;AAAA,MAAA;AAEX,YAAM,SAAS,UAAU;AACzB,kBAAA;AAAA,IACJ,SAAS,OAAgB;AACrB,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,CAAuB;AAAA,IACjE,UAAA;AACI,sBAAgB,KAAK;AAAA,IACzB;AAAA,EACJ;AAEA,QAAM,QAAQ,aACV,iBAAiB,UAAU,eAAe,OAC1C,WAAW,UAAU,SAAS,OAC9B,KAAK,UAAU,gBAAgB,KAAA,CAAM,MAAM,KAAK,WAAW,UAAU,SAAS,CAAA,GAAI,KAAA,CAAM;AAE5F,SACI,oBAAC,QAAA,EAAO,MAAY,cAAc,CAACgB,UAAS,CAACA,QAAO,YAAA,IAAgB,QAAW,UAAS,OACpF,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,UAAU;AAAA,MAAc,cAAa;AAAA,MAAM,YAAU;AAAA,MACvD,OAAO;AAAA,QAAE,SAAS;AAAA,QAClC,eAAe;AAAA,QACf,UAAU;AAAA,QACV,QAAQ;AAAA,MAAA;AAAA,MAEQ,UAAA;AAAA,QAAA,oBAAC,aAAA,EAAY,SAAQ,MAAK,cAAc,OAAO,UAAA,QAE/C;AAAA,4BAEC,eAAA,EAAc,WAAU,eACrB,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACX,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,MAAK;AAAA,gBACL,UAAQ;AAAA,gBACR,OAAO,cAAc,KAAK,QAAQ,OAAO,WAAW;AAAA,gBACpD,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,eAAe,EAAE,OAAO,KAAK;AAAA,gBAC9C,OAAM;AAAA,cAAA;AAAA,YAAA;AAAA,YAEV,oBAAC,gBACI,UAAA,cAAc,KAAK,OAAO,cAAc,OAAO,cAAc,oBAAA,CAClE;AAAA,UAAA,GACJ;AAAA,UAEA,qBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,UAAQ;AAAA,gBACR,OAAO,cAAc,KAAK,QAAQ,OAAO,KAAK;AAAA,gBAC9C,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,gBACxC,OAAM;AAAA,gBACN,UAAU,CAAC;AAAA,cAAA;AAAA,YAAA;AAAA,YAEf,oBAAC,gBACI,UAAA,cAAc,KAAK,OAAO,QAAQ,OAAO,QAAQ,qBAAA,CACtD;AAAA,UAAA,GACJ;AAAA,UAEA,oBAAC,OAAA,EAAI,WAAU,eACX,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,WAAU;AAAA,cACV,OAAM;AAAA,cACN,OAAO;AAAA,cACP,eAAe,CAAC,UAAoB,mBAAmB,KAAK;AAAA,cAE3D,UAAA,MAAM,IAAI,CAAA,SACP,oBAAC,mBAA8B,OAAO,KAAK,IACvC,UAAA,oBAAC,UAAA,EAAS,KAAA,CAAW,EAAA,GADH,KAAK,EAE3B,CACH;AAAA,YAAA;AAAA,UAAA,EACL,CACJ;AAAA,QAAA,EAAA,CACJ,EAAA,CACJ;AAAA,6BAEC,eAAA,EACG,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAO,SAAQ,QAAO,SAAS,aAAa,UAAA,UAE7C;AAAA,UACA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,UAAU,CAAC;AAAA,cACX,SAAS;AAAA,cAER,sBAAY,gBAAgB;AAAA,YAAA;AAAA,UAAA;AAAA,QACjC,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAER;AAER;AAKO,SAAS,UAAU,EAAE,gBAAgB,cAAc,CAAA,KAA4E;AAClI,QAAM,EAAE,OAAO,UAAU,YAAY,SAAS,8BAA8B;AAC5E,QAAM,aAAa,gBAAgB,iBAAkB,eAA0C,aAAa;AAC5G,QAAM,qBAAqB,sBAAA;AAE3B,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAA;AACxC,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAChE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAA;AACxC,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAE9D,QAAM,gBAAgB,MAAM;AACxB,oBAAgB,MAAS;AACzB,kBAAc,IAAI;AAAA,EACtB;AAEA,QAAM,iBAAiB,CAAC,SAAe;AACnC,oBAAgB,IAAI;AACpB,kBAAc,IAAI;AAAA,EACtB;AAEA,QAAM,cAAc,MAAM;AACtB,kBAAc,KAAK;AACnB,oBAAgB,MAAS;AAAA,EAC7B;AAEA,QAAM,eAAe,YAAY;AAC7B,QAAI,CAAC,aAAc;AACnB,wBAAoB,IAAI;AACxB,QAAI;AACA,YAAM,WAAW,YAAY;AAC7B,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS;AAAA,MAAA,CAA6B;AAC1B,2BAAqB,KAAK;AAC1B,sBAAgB,MAAS;AAAA,IAC7B,SAAS,OAAgB;AACrB,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,CAAuB;AAAA,IACjE,UAAA;AACI,0BAAoB,KAAK;AAAA,IAC7B;AAAA,EACJ;AAEA,QAAM,qBAAqB,MAAM;AAC7B,UAAM,eAAuB;AAAA,MACzB;AAAA,QAAE,IAAI;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MAAA;AAAA,MACG;AAAA,QAAE,IAAI;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MAAA;AAAA,MACG;AAAA,QAAE,IAAI;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MAAA;AAAA,IAAM;AAEP,iBAAa,QAAQ,CAAA,SAAQ,SAAS,IAAI,CAAC;AAAA,EAC/C;AAEA,MAAI,SAAS;AACT,WAAO,oBAAC,cAAA,EAAa,UAAA,oBAAC,kBAAA,CAAA,CAAgB,GAAE;AAAA,EAC5C;AAEA,SACI,qBAAC,WAAA,EAAU,WAAU,mCAAkC,UAAU,OAC7D,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,2BACX,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,cAAY,MAAC,SAAQ,MAAK,WAAU,QAAO,WAAU,MAAK,UAAA,QAAA,CAEtE;AAAA,MACA,oBAAC,UAAO,WAAW,oBAAC,YAAQ,GAAI,SAAS,eAAe,UAAA,WAAA,CAExD;AAAA,IAAA,GACJ;AAAA,wBAEC,OAAA,EAAI,WAAU,wBACX,UAAA,qBAAC,OAAA,EAAM,WAAU,UACb,UAAA;AAAA,MAAA,qBAAC,aAAA,EACG,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAU,QAAM,MAAC,WAAU,QAAO;AAAA,QACnC,oBAAC,WAAA,EAAU,QAAM,MAAC,UAAA,QAAI;AAAA,4BACrB,WAAA,EAAU,QAAM,MAAC,WAAU,gBAAe,UAAA,WAAA,CAAQ;AAAA,MAAA,GACvD;AAAA,2BACC,WAAA,EACI,UAAA;AAAA,QAAA,MAAM,IAAI,CAAA,SAAQ;AACf,sCACK,UAAA,EAAuB,SAAS,MAAM,eAAe,IAAI,GACtD,UAAA;AAAA,YAAA,oBAAC,WAAA,EAAU,OAAO,EAAE,OAAO,UACtB,UAAA,CAAC,KAAK,WACH,oBAAC,SAAA,EAAQ,SAAO,MAAC,OAAM,oBACnB,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,MAAK;AAAA,gBACL,SAAS,CAAC,MAAM;AACZ,oBAAE,gBAAA;AACF,kCAAgB,IAAI;AACpB,uCAAqB,IAAI;AAAA,gBAC7B;AAAA,gBACA,8BAAC,YAAA,CAAA,CAAU;AAAA,cAAA;AAAA,YAAA,GAEnB,EAAA,CAER;AAAA,YACA,oBAAC,WAAA,EACG,UAAA,oBAAC,UAAA,EAAS,MAAW,GACzB;AAAA,YACA,oBAAC,WAAA,EAAU,WAAU,gBACjB,UAAA,oBAAC,YAAS,SAAS,KAAK,WAAW,MAAA,CAAM,EAAA,CAC7C;AAAA,UAAA,EAAA,GArBW,KAAK,EAsBpB;AAAA,QAER,CAAC;AAAA,QAEA,MAAM,WAAW,KACd,oBAAC,UAAA,EACG,UAAA,oBAAC,WAAA,EAAU,SAAS,GAChB,UAAA,qBAAC,cAAA,EAAa,WAAU,yCACpB,UAAA;AAAA,UAAA,oBAAC,YAAA,EAAW,SAAQ,SACf,UAAA,aACK,4CACA,sCACV;AAAA,UACC,cACG,oBAAC,YAAA,EAAW,SAAQ,WAAU,WAAU,oBAAmB,UAAA,gEAE3D;AAAA,UAEH,CAAC,cAAc,iDACX,QAAA,EAAO,SAAS,oBAAoB,UAAA,uBAAA,CAErC;AAAA,QAAA,EAAA,CAER,GACJ,EAAA,CACJ;AAAA,MAAA,EAAA,CAER;AAAA,IAAA,EAAA,CACJ,EAAA,CACJ;AAAA,IAGA;AAAA,MAAC;AAAA,MAAA;AAAA,QAEG,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MALK,cAAc,MAAM;AAAA,IAAA;AAAA,IAS7B;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAM;AAAA,QACN,SAAS;AAAA,QACT,UAAU;AAAA,QACV,UAAU,MAAM;AAAE,+BAAqB,KAAK;AAAG,0BAAgB,MAAS;AAAA,QAAG;AAAA,QAC3E,uCAAS,UAAA,UAAA,CAAO;AAAA,QAChB,sCAAQ,UAAA,6CAAA,CAA0C;AAAA,MAAA;AAAA,IAAA;AAAA,EACtD,GACJ;AAER;AAKA,SAAS,gBAAgB;AAAA,EACrB;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA,cAAc,CAAA;AAClB,GAMG;AACC,QAAM,qBAAqB,sBAAA;AAC3B,QAAM,YAAY,CAAC;AAEnB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,UAAU,MAAM,EAAE;AACvD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,UAAU,QAAQ,EAAE;AAC7D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,UAAU,WAAW,KAAK;AAEjE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyC,CAAA,CAAE;AACvE,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAEhD,QAAM,WAAW,MAAM;AACnB,UAAM,YAA2B,CAAA;AACjC,QAAI,CAAC,OAAQ,WAAU,KAAK;AAC5B,QAAI,CAAC,SAAU,WAAU,OAAO;AAChC,cAAU,SAAS;AACnB,WAAO,OAAO,KAAK,SAAS,EAAE,WAAW;AAAA,EAC7C;AAEA,QAAM,eAAe,OAAO,MAAuB;AAC/C,MAAE,eAAA;AACF,mBAAe,CAAA,MAAK,IAAI,CAAC;AAEzB,QAAI,CAAC,WAAY;AAEjB,oBAAgB,IAAI;AACpB,QAAI;AACA,YAAM,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN;AAAA,MAAA,CACH;AACD,kBAAA;AAAA,IACJ,SAAS,OAAgB;AACrB,yBAAmB,KAAK;AAAA,QAAE,MAAM;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,CAAuB;AAAA,IACjE,UAAA;AACI,sBAAgB,KAAK;AAAA,IACzB;AAAA,EACJ;AAEA,SACI,oBAAC,QAAA,EAAO,MAAY,cAAc,CAACA,UAAS,CAACA,QAAO,YAAA,IAAgB,QAAW,UAAS,OACpF,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,UAAU;AAAA,MAAc,cAAa;AAAA,MAAM,YAAU;AAAA,MACvD,OAAO;AAAA,QAAE,SAAS;AAAA,QAClC,eAAe;AAAA,QACf,UAAU;AAAA,QACV,QAAQ;AAAA,MAAA;AAAA,MAEQ,UAAA;AAAA,QAAA,oBAAC,aAAA,EAAY,SAAQ,MAAK,cAAc,OAAO,UAAA,QAE/C;AAAA,4BAEC,eAAA,EAAc,WAAU,+BACrB,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACX,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,6BACX,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,MAAK;AAAA,gBACL,UAAQ;AAAA,gBACR,OAAO,cAAc,KAAK,QAAQ,OAAO,EAAE;AAAA,gBAC3C,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,KAAK;AAAA,gBACzC,OAAM;AAAA,gBACN,UAAU,CAAC;AAAA,cAAA;AAAA,YAAA;AAAA,YAEf,oBAAC,gBACI,UAAA,cAAc,KAAK,OAAO,KAAK,OAAO,KAAK,kCAAA,CAChD;AAAA,UAAA,GACJ;AAAA,UAEA,qBAAC,OAAA,EAAI,WAAU,6BACX,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,MAAK;AAAA,gBACL,UAAQ;AAAA,gBACR,OAAO,cAAc,KAAK,QAAQ,OAAO,IAAI;AAAA,gBAC7C,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,gBAC3C,OAAM;AAAA,cAAA;AAAA,YAAA;AAAA,YAEV,oBAAC,gBACI,UAAA,cAAc,KAAK,OAAO,OAAO,OAAO,OAAO,6BAAA,CACpD;AAAA,UAAA,GACJ;AAAA,8BAEC,OAAA,EAAI,WAAU,mDACX,UAAA,qBAAC,SAAA,EAAM,WAAU,+CACb,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,SAAS;AAAA,gBACT,iBAAiB,CAAC,YAAY,WAAW,QAAQ,OAAO,CAAC;AAAA,cAAA;AAAA,YAAA;AAAA,YAE7D,oBAAC,QAAA,EAAK,WAAU,eAAc,UAAA,WAAA,CAAQ;AAAA,UAAA,EAAA,CAC1C,EAAA,CACJ;AAAA,UAGA,oBAAC,SAAI,WAAU,eACX,8BAAC,6BAAA,EAA4B,QAAgB,SAAkB,YAAA,CAAyB,EAAA,CAC5F;AAAA,QAAA,EAAA,CACJ,EAAA,CACJ;AAAA,6BAEC,eAAA,EACG,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAO,SAAQ,QAAO,SAAS,aAAa,UAAA,UAE7C;AAAA,UACA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cAER,sBAAY,gBAAgB;AAAA,YAAA;AAAA,UAAA;AAAA,QACjC,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAER;AAER;AAKA,MAAM,WAAW;AAAA,EACb;AAAA,IAAE,IAAI;AAAA,IACV,OAAO;AAAA,EAAA;AAAA,EACH;AAAA,IAAE,IAAI;AAAA,IACV,OAAO;AAAA,EAAA;AAAA,EACH;AAAA,IAAE,IAAI;AAAA,IACV,OAAO;AAAA,EAAA;AAAA,EACH;AAAA,IAAE,IAAI;AAAA,IACV,OAAO;AAAA,EAAA;AACP;AAGA,SAAS,cACL,OACA,QACA,IACO;AACP,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,QAAM,aAAa,MAAM;AAAA,IAAO,CAAA,MAC5B,EAAE,cAAc,MAAM,EAAE,cAAc,SACtC,EAAE,YAAY,SAAS,EAAE,KAAK,EAAE,YAAY,SAAS,KAAK;AAAA,EAAA;AAE9D,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,QAAM,UAAU,WAAW;AAAA,IAAO,OAC9B,CAAC,EAAE,SAAS,EAAE,MAAM,WAAW,KAAK,EAAE,MAAM,SAAS,MAAM,KAAK,EAAE,MAAM,SAAS,QAAQ;AAAA,EAAA;AAE7F,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,aAAW,KAAK,SAAS;AACrB,SAAK,EAAE,QAAQ,kBAAkB,cAAe,QAAO;AAAA,EAC3D;AACA,SAAO,QAAQ,KAAK,CAAA,OAAM,EAAE,QAAQ,kBAAkB,YAAY;AACtE;AAEA,SAAS,SAAS,EAAE,WAAiC;AACjD,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAK,WAAW,UACX,6DACA;AAAA,MAED,oBAAU,MAAM;AAAA,IAAA;AAAA,EAAA;AAG7B;AAEA,SAAS,4BAA4B,EAAE,QAAQ,SAAS,eAAsF;AAC1I,MAAI,CAAC,eAAe,YAAY,WAAW,GAAG;AAC1C,WACI,oBAAC,OAAA,EAAI,WAAU,QACX,UAAA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,oBAAmB,UAAA,4BAAA,CAAyB,GACtF;AAAA,EAER;AAEA,QAAM,WAAW;AAEjB,SACI,qBAAC,OAAA,EAAI,WAAU,QACX,UAAA;AAAA,IAAA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,qFAAoF,UAAA,0BAE1H;AAAA,IACA,oBAAC,OAAA,EAAI,WAAU,gFACX,+BAAC,OAAA,EACG,UAAA;AAAA,MAAA,oBAAC,aAAA,EACG,+BAAC,UAAA,EACG,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAU,QAAM,MAAC,UAAA,cAAU;AAAA,QAC3B,SAAS,IAAI,CAAC,EAAE,IAAI,MAAA,MACjB,oBAAC,WAAA,EAAmB,QAAM,MAAC,WAAU,oBAAoB,UAAA,MAAA,GAAzC,EAA+C,CAClE;AAAA,MAAA,EAAA,CACL,EAAA,CACJ;AAAA,MACA,oBAAC,WAAA,EACI,UAAA,SAAS,IAAI,CAAC,eAAe;AAC1B,cAAM,SAAS;AACf,cAAM,UAAU,CAAC,OAAO,iBAAiB,OAAO,cAAc,WAAW;AACzE,oCACK,UAAA,EACG,UAAA;AAAA,UAAA,qBAAC,WAAA,EACG,UAAA;AAAA,YAAA,qBAAC,OAAA,EAAI,WAAU,2BACX,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,WAAU,eAAe,UAAA,WAAW,MAAK;AAAA,cAC9C,WAAW,CAAC,WACT,oBAAC,WAAQ,OAAM,oCACX,UAAA,oBAAC,MAAA,EAAK,WAAU,WAAU,aAAY,UAAS,sBAAQ,EAAA,CAC3D;AAAA,YAAA,GAER;AAAA,YACA,oBAAC,QAAA,EAAK,WAAU,sCAAsC,qBAAW,KAAA,CAAK;AAAA,UAAA,GAC1E;AAAA,UACC,SAAS,IAAI,CAAC,EAAE,SACb,oBAAC,WAAA,EAAmB,WAAU,eAC1B,UAAA,oBAAC,YAAS,SAAS,WAAW,cAAc,OAAO,eAAe,QAAQ,EAAE,EAAA,CAAE,EAAA,GADlE,EAEhB,CACH;AAAA,QAAA,EAAA,GAhBU,WAAW,IAiB1B;AAAA,MAER,CAAC,EAAA,CACL;AAAA,IAAA,EAAA,CACJ,EAAA,CACJ;AAAA,IACC,CAAC,UACE,oBAAC,YAAA,EAAW,SAAQ,WAAU,WAAU,gCAA+B,UAAA,+CAAA,CAEvE;AAAA,EAAA,GAER;AAER;AAKA,SAAS,aAAa,EAAE,YAAqC;AACzD,6BACK,YAAA,EAAW,SAAQ,WAAU,WAAU,sCACnC,UACL;AAER;"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/api.ts","../src/hooks/useRebaseAuthController.ts","../src/hooks/useBackendUserManagement.ts","../src/components/RebaseLoginView.tsx","../src/components/RebaseAuth.tsx","../src/components/AdminViews.tsx"],"sourcesContent":["import { AuthResponse, RefreshResponse, Session, UserInfo } from \"./types\";\n\n/**\n * Default API URL - can be overridden in hook props\n */\nlet baseApiUrl = \"\";\n\n/**\n * Configure the API base URL\n */\nexport function setApiUrl(url: string): void {\n baseApiUrl = url;\n}\n\n/**\n * Get the current API URL\n */\nexport function getApiUrl(): string {\n return baseApiUrl;\n}\n\nclass AuthApiError extends Error {\n code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.code = code;\n this.name = \"AuthApiError\";\n }\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n let data: Record<string, unknown>;\n try {\n data = await response.json();\n } catch (parseError) {\n // Response wasn't JSON - could be network error or server issue\n throw new AuthApiError(\n `Server returned non-JSON response (status: ${response.status})`,\n \"PARSE_ERROR\"\n );\n }\n\n if (!response.ok) {\n throw new AuthApiError(\n (data as Record<string, Record<string, string>>).error?.message || \"Request failed\",\n (data as Record<string, Record<string, string>>).error?.code || \"UNKNOWN_ERROR\"\n );\n }\n\n return data as T;\n}\n\n/**\n * Wrapper for fetch that catches generic network failures (like server down)\n * and translates them to an AuthApiError.\n */\nasync function fetchWithHandling(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n try {\n return await fetch(input, init);\n } catch (error: unknown) {\n if (error instanceof TypeError && error.message.includes(\"Failed to fetch\")) {\n throw new AuthApiError(\n \"Failed to connect to the backend server. The backend might be down or failed to initialize (e.g., database connection timeout).\",\n \"NETWORK_ERROR\"\n );\n }\n throw new AuthApiError(\"Network error: \" + (error instanceof Error ? error.message : String(error)), \"NETWORK_ERROR\");\n }\n}\n\n/**\n * Register a new user with email/password\n */\nexport async function register(\n email: string,\n password: string,\n displayName?: string\n): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email,\npassword,\ndisplayName })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Login with email/password\n */\nexport async function login(email: string, password: string): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/login`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email,\npassword })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Google login payload — one of the three supported flows.\n */\nexport type GoogleLoginPayload =\n | { idToken: string }\n | { accessToken: string }\n | { code: string; redirectUri: string };\n\n/**\n * Login with Google.\n *\n * Overload 1 (legacy): `googleLogin(\"token\", \"idToken\" | \"accessToken\")`\n * Overload 2 (code flow): `googleLogin({ code, redirectUri })`\n */\nexport async function googleLogin(payload: GoogleLoginPayload): Promise<AuthResponse>;\nexport async function googleLogin(token: string, tokenType?: \"idToken\" | \"accessToken\"): Promise<AuthResponse>;\nexport async function googleLogin(\n tokenOrPayload: string | GoogleLoginPayload,\n tokenType: \"idToken\" | \"accessToken\" = \"idToken\"\n): Promise<AuthResponse> {\n const body = typeof tokenOrPayload === \"string\"\n ? { [tokenType]: tokenOrPayload }\n : tokenOrPayload;\n\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/google`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body)\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Login with LinkedIn OAuth code\n */\nexport async function linkedinLogin(code: string, redirectUri: string): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/linkedin`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ code,\nredirectUri })\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Generic OAuth login — works with any provider registered on the backend.\n * The `providerId` is used to build the endpoint: `/api/auth/{providerId}`.\n */\nexport async function oauthLogin(providerId: string, payload: Record<string, unknown>): Promise<AuthResponse> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/${providerId}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload)\n });\n\n return handleResponse<AuthResponse>(response);\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<RefreshResponse> {\n console.log(\"[AUTH-API] Calling refresh endpoint...\");\n\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken })\n });\n\n console.log(\"[AUTH-API] Refresh response status:\", response.status);\n return handleResponse<RefreshResponse>(response);\n}\n\n/**\n * Logout and invalidate refresh token\n */\nexport async function logout(refreshToken?: string): Promise<void> {\n await fetchWithHandling(`${baseApiUrl}/api/auth/logout`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken })\n });\n}\n\n/**\n * Get current user info\n */\nexport async function getCurrentUser(accessToken: string): Promise<{ user: UserInfo }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/me`, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ user: UserInfo }>(response);\n}\n\n/**\n * Request password reset email\n */\nexport async function forgotPassword(email: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/forgot-password`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Reset password using token from email\n */\nexport async function resetPassword(token: string, password: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/reset-password`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token,\npassword })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Change password for authenticated user\n */\nexport async function changePassword(\n accessToken: string,\n oldPassword: string,\n newPassword: string\n): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/change-password`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n },\n body: JSON.stringify({ oldPassword,\nnewPassword })\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Send email verification link\n */\nexport async function sendVerificationEmail(accessToken: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/send-verification`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Verify email address using token\n */\nexport async function verifyEmail(token: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/verify-email?token=${encodeURIComponent(token)}`, {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Update current user profile\n */\nexport async function updateProfile(\n accessToken: string,\n displayName?: string,\n photoURL?: string\n): Promise<{ user: UserInfo }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/me`, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n },\n body: JSON.stringify({ displayName,\nphotoURL })\n });\n\n return handleResponse<{ user: UserInfo }>(response);\n}\n\n/**\n * Fetch active sessions for current user\n */\nexport async function fetchSessions(accessToken: string, currentRefreshToken?: string): Promise<{ sessions: Session[] }> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n };\n if (currentRefreshToken) {\n headers[\"X-Refresh-Token\"] = currentRefreshToken;\n }\n\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions`, {\n method: \"GET\",\n headers\n });\n\n return handleResponse<{ sessions: Session[] }>(response);\n}\n\n/**\n * Revoke a specific session\n */\nexport async function revokeSession(accessToken: string, sessionId: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions/${sessionId}`, {\n method: \"DELETE\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Revoke all sessions for current user\n */\nexport async function revokeAllSessions(accessToken: string): Promise<{ success: boolean; message: string }> {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/sessions`, {\n method: \"DELETE\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n\n return handleResponse<{ success: boolean; message: string }>(response);\n}\n\n/**\n * Auth config response from the backend\n */\nexport interface AuthConfigResponse {\n /** True when there are no users in the system and first user setup is needed */\n needsSetup: boolean;\n /** Whether new user registration is enabled */\n registrationEnabled: boolean;\n /** Whether Google OAuth is configured */\n googleEnabled: boolean;\n /** Whether LinkedIn OAuth is configured */\n linkedinEnabled: boolean;\n /** Whether email service is configured */\n emailServiceEnabled: boolean;\n /** Complete list of enabled OAuth provider IDs (e.g. [\"google\", \"github\", \"discord\"]) */\n enabledProviders?: string[];\n}\n\n/**\n * Inflight promise for `fetchAuthConfig` — ensures concurrent callers\n * (e.g. React StrictMode double-mount) reuse the same network request.\n */\nlet authConfigInflight: Promise<AuthConfigResponse> | null = null;\n\n/**\n * Fetch auth configuration / status from the backend\n * This is an unauthenticated endpoint used to detect bootstrap mode.\n *\n * Concurrent calls are deduplicated: only one network request is made\n * and all callers share the same promise.\n */\nexport async function fetchAuthConfig(): Promise<AuthConfigResponse> {\n if (authConfigInflight) {\n return authConfigInflight;\n }\n\n authConfigInflight = (async () => {\n const response = await fetchWithHandling(`${baseApiUrl}/api/auth/config`, {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n return handleResponse<AuthConfigResponse>(response);\n })();\n\n try {\n return await authConfigInflight;\n } finally {\n authConfigInflight = null;\n }\n}\n\nexport { AuthApiError };\n\n","import { useCallback, useEffect, useState, useRef } from \"react\";\nimport { User } from \"@rebasepro/types\";\nimport * as authApi from \"../api\";\nimport { AuthConfigResponse } from \"../api\";\nimport {\n RebaseAuthController,\n RebaseAuthControllerProps,\n AuthTokens,\n UserInfo\n} from \"../types\";\n\nconst STORAGE_KEY = \"rebase_auth\";\n\n// Buffer time before expiry to trigger refresh (2 minutes)\nconst TOKEN_REFRESH_BUFFER_MS = 2 * 60 * 1000;\n\n/**\n * Convert UserInfo from API to Rebase User type\n */\nfunction convertToUser(userInfo: UserInfo): User {\n return {\n uid: userInfo.uid,\n email: userInfo.email,\n displayName: userInfo.displayName || null,\n photoURL: userInfo.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: userInfo.roles || []\n };\n}\n\n/**\n * Storage data structure\n */\ninterface StoredAuthData {\n tokens: AuthTokens;\n user: UserInfo;\n}\n\n/**\n * Save auth data to localStorage\n */\nfunction saveAuthToStorage(tokens: AuthTokens, user: UserInfo): void {\n try {\n const data: StoredAuthData = { tokens,\nuser };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n const expiryDate = new Date(tokens.accessTokenExpiresAt);\n const expiryStr = Number.isFinite(tokens.accessTokenExpiresAt) ? expiryDate.toISOString() : \"invalid\";\n } catch (e) { /* ignore */ }\n}\n\n/**\n * Load auth data from localStorage\n */\nfunction loadAuthFromStorage(): StoredAuthData | null {\n try {\n const data = localStorage.getItem(STORAGE_KEY);\n if (data) {\n const parsed = JSON.parse(data);\n return parsed;\n }\n } catch (e) {\n console.warn(\"Failed to load auth from storage:\", e);\n }\n return null;\n}\n\n/**\n * Clear auth data from localStorage\n */\nfunction clearAuthFromStorage(): void {\n try {\n localStorage.removeItem(STORAGE_KEY);\n } catch (e) {\n console.warn(\"Failed to clear auth from storage:\", e);\n }\n}\n\n/**\n * Check if token is expired or about to expire\n */\nfunction isTokenExpiredOrNearExpiry(expiresAt: number, bufferMs: number = TOKEN_REFRESH_BUFFER_MS): boolean {\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Auth controller hook for JWT-based authentication\n * with @rebasepro/server-core\n *\n * @param props Configuration options\n * @returns RebaseAuthController instance\n */\nexport function useRebaseAuthController(\n props: RebaseAuthControllerProps = {}\n): RebaseAuthController {\n const { client, apiUrl, onSignOut, defineRolesFor } = props;\n\n const [user, setUser] = useState<User | null>(null);\n const [authLoading, setAuthLoading] = useState(false);\n const [initialLoading, setInitialLoading] = useState(true);\n const [authError, setAuthError] = useState<Error | null>(null);\n const [authProviderError, setAuthProviderError] = useState<Error | null>(null);\n const [loginSkipped, setLoginSkipped] = useState(false);\n const [extra, setExtra] = useState<unknown>(null);\n const [authConfig, setAuthConfig] = useState<AuthConfigResponse | null>(null);\n\n // Store tokens in ref for quick access, but also persist to localStorage\n const tokensRef = useRef<AuthTokens | null>(null);\n const refreshTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Track if a refresh is currently in progress to avoid concurrent refreshes\n const refreshPromiseRef = useRef<Promise<AuthTokens | null> | null>(null);\n // Track if component is mounted\n const isMountedRef = useRef(true);\n\n // Configure API URL on mount\n useEffect(() => {\n if (client) {\n authApi.setApiUrl(client.baseUrl);\n } else if (apiUrl) {\n authApi.setApiUrl(apiUrl);\n }\n }, [client, apiUrl]);\n\n // Clear session and sign out\n const clearSessionAndSignOut = useCallback(() => {\n tokensRef.current = null;\n clearAuthFromStorage();\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n refreshTimeoutRef.current = null;\n }\n setUser(null);\n setLoginSkipped(false);\n onSignOut?.();\n }, [onSignOut]);\n\n /**\n * Refresh the access token using the stored refresh token.\n * Returns the new tokens or null if refresh failed.\n */\n const refreshAccessToken = useCallback(async (): Promise<AuthTokens | null> => {\n // Prevent concurrent refreshes\n if (refreshPromiseRef.current) {\n // Wait for the current refresh to complete\n return refreshPromiseRef.current;\n }\n\n const executeRefresh = async (): Promise<AuthTokens | null> => {\n // Check if another tab has already refreshed the token\n const storedData = loadAuthFromStorage();\n if (storedData?.tokens?.accessTokenExpiresAt) {\n const storedTokens = storedData.tokens;\n // If stored token is newer and not expired\n if (!isTokenExpiredOrNearExpiry(storedTokens.accessTokenExpiresAt) && storedTokens.accessToken !== tokensRef.current?.accessToken) {\n tokensRef.current = storedTokens;\n return storedTokens;\n }\n }\n\n const currentTokens = tokensRef.current;\n if (!currentTokens?.refreshToken) {\n return null;\n }\n\n\n try {\n const response = await authApi.refreshAccessToken(currentTokens.refreshToken);\n const newTokens = response.tokens;\n\n // Update tokens immediately\n tokensRef.current = newTokens;\n\n // Persist to storage\n const latestStoredData = loadAuthFromStorage();\n if (latestStoredData) {\n saveAuthToStorage(newTokens, latestStoredData.user);\n }\n\n const newExpiryStr = Number.isFinite(newTokens.accessTokenExpiresAt) ? new Date(newTokens.accessTokenExpiresAt).toISOString() : \"invalid\";\n return newTokens;\n } catch (error: unknown) {\n\n // If it's a network error (e.g., backend restarting), we throw so callers can retry\n // instead of immediately assuming the refresh token is invalid and signing out.\n if (error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\") {\n throw error;\n }\n return null;\n } finally {\n refreshPromiseRef.current = null;\n }\n };\n\n refreshPromiseRef.current = executeRefresh();\n return refreshPromiseRef.current;\n }, []);\n\n // Schedule token refresh before expiry\n const scheduleTokenRefresh = useCallback((tokens: AuthTokens) => {\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n }\n\n // Calculate when to refresh (2 minutes before expiry)\n const expiresAt = tokens.accessTokenExpiresAt;\n const refreshAt = expiresAt - TOKEN_REFRESH_BUFFER_MS;\n const timeUntilRefresh = refreshAt - Date.now();\n\n if (timeUntilRefresh <= 0) {\n // Token already expired or about to expire - refresh now\n refreshAccessToken().then(newTokens => {\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n });\n return;\n }\n\n\n refreshTimeoutRef.current = setTimeout(async () => {\n if (!isMountedRef.current) return;\n\n try {\n const newTokens = await refreshAccessToken();\n\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n } catch (error) {\n // Network error - try again shortly instead of logging out\n if (isMountedRef.current) {\n refreshTimeoutRef.current = setTimeout(() => {\n scheduleTokenRefresh(tokens);\n }, 10000);\n }\n }\n }, timeUntilRefresh);\n }, [refreshAccessToken, clearSessionAndSignOut]);\n\n // Get auth token for API requests (with automatic refresh if needed)\n const getAuthToken = useCallback(async (): Promise<string> => {\n // If still loading, throw - the UI should show a spinner\n if (initialLoading) {\n throw new Error(\"Auth is still loading\");\n }\n\n const currentTokens = tokensRef.current;\n if (!currentTokens) {\n throw new Error(\"User is not logged in\");\n }\n\n // Check if token is expired or about to expire\n if (isTokenExpiredOrNearExpiry(currentTokens.accessTokenExpiresAt)) {\n try {\n const newTokens = await refreshAccessToken();\n if (!newTokens) {\n clearSessionAndSignOut();\n throw new Error(\"Session expired. Please login again.\");\n }\n return newTokens.accessToken;\n } catch (error: unknown) {\n // If the error was a network error during refresh, just re-throw it\n // so the user isn't logged out locally and the network request fails naturally.\n if (error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\") {\n throw error;\n }\n clearSessionAndSignOut();\n throw error;\n }\n }\n\n return currentTokens.accessToken;\n }, [initialLoading, refreshAccessToken, clearSessionAndSignOut]);\n\n // Install token getter onto client\n useEffect(() => {\n if (client) {\n client.setAuthTokenGetter(async () => {\n try { return await getAuthToken(); } catch { return null; }\n });\n if (client.setOnUnauthorized) {\n client.setOnUnauthorized(async () => {\n try {\n const newTokens = await refreshAccessToken();\n if (newTokens) return true;\n clearSessionAndSignOut();\n return false;\n } catch (e) {\n clearSessionAndSignOut();\n return false;\n }\n });\n }\n if (client.ws) {\n client.ws.setAuthTokenGetter(async () => {\n return await getAuthToken();\n });\n }\n }\n }, [client, getAuthToken, refreshAccessToken, clearSessionAndSignOut]);\n\n // Handle successful authentication\n const handleAuthSuccess = useCallback(async (userInfo: UserInfo, tokens: AuthTokens) => {\n console.log(\"[Auth] handleAuthSuccess called, user:\", userInfo.email, \"uid:\", userInfo.uid);\n tokensRef.current = tokens;\n let convertedUser = convertToUser(userInfo);\n\n // Apply custom roles if defineRolesFor provided\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(convertedUser);\n if (customRoles) {\n convertedUser = { ...convertedUser,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n // Save to localStorage for persistence\n saveAuthToStorage(tokens, userInfo);\n\n console.log(\"[Auth] Calling setUser, roles:\", convertedUser.roles);\n setUser(convertedUser);\n setAuthError(null);\n setAuthProviderError(null);\n setLoginSkipped(false);\n scheduleTokenRefresh(tokens);\n console.log(\"[Auth] handleAuthSuccess completed\");\n }, [scheduleTokenRefresh, defineRolesFor]);\n\n // Email/password login\n const emailPasswordLogin = useCallback(async (email: string, password: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.login(email, password);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Register new user\n const register = useCallback(async (email: string, password: string, displayName?: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.register(email, password, displayName);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Google login — supports legacy (token, tokenType) and code-flow payload\n const googleLogin = useCallback(async (\n tokenOrPayload: string | { code: string; redirectUri: string },\n tokenType?: \"idToken\" | \"accessToken\"\n ) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = typeof tokenOrPayload === \"string\"\n ? await authApi.googleLogin(tokenOrPayload, tokenType ?? \"idToken\")\n : await authApi.googleLogin(tokenOrPayload);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Generic OAuth login — works with any provider registered on the backend\n const oauthLogin = useCallback(async (providerId: string, payload: Record<string, unknown>) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n const response = await authApi.oauthLogin(providerId, payload);\n await handleAuthSuccess(response.user, response.tokens);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [handleAuthSuccess]);\n\n // Sign out\n const signOut = useCallback(async () => {\n try {\n if (tokensRef.current) {\n await authApi.logout(tokensRef.current.refreshToken);\n }\n } catch (error) {\n console.error(\"Logout error:\", error);\n } finally {\n clearSessionAndSignOut();\n }\n }, [clearSessionAndSignOut]);\n\n // Skip login\n const skipLogin = useCallback(() => {\n setLoginSkipped(true);\n setUser(null);\n }, []);\n\n // Forgot password - request reset email\n const forgotPassword = useCallback(async (email: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n await authApi.forgotPassword(email);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, []);\n\n // Reset password using token\n const resetPassword = useCallback(async (token: string, password: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n await authApi.resetPassword(token, password);\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, []);\n\n // Change password for authenticated user\n const changePassword = useCallback(async (oldPassword: string, newPassword: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.changePassword(tokensRef.current.accessToken, oldPassword, newPassword);\n // After password change, user needs to log in again (all sessions invalidated)\n clearSessionAndSignOut();\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [clearSessionAndSignOut]);\n\n // Update user profile\n const updateProfile = useCallback(async (displayName?: string, photoURL?: string) => {\n setAuthLoading(true);\n setAuthProviderError(null);\n\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n const response = await authApi.updateProfile(tokensRef.current.accessToken, displayName, photoURL);\n\n // Update local user state\n let convertedUser = convertToUser(response.user);\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(convertedUser);\n if (customRoles) {\n convertedUser = { ...convertedUser,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n // Update storage\n const storedData = loadAuthFromStorage();\n if (storedData) {\n saveAuthToStorage(storedData.tokens, response.user);\n }\n\n setUser(convertedUser);\n return convertedUser;\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n } finally {\n setAuthLoading(false);\n }\n }, [defineRolesFor]);\n\n // Fetch active sessions\n const fetchSessions = useCallback(async () => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n const response = await authApi.fetchSessions(tokensRef.current.accessToken, tokensRef.current.refreshToken);\n return response.sessions;\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, []);\n\n // Revoke a session\n const revokeSession = useCallback(async (sessionId: string) => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.revokeSession(tokensRef.current.accessToken, sessionId);\n // If the revoked session is the current one, the next API request will fail with 401\n // and trigger an auto-logout. Otherwise, it just removes it from the DB.\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, []);\n\n // Restore auth state from localStorage on mount\n useEffect(() => {\n isMountedRef.current = true;\n\n const restoreAuth = async () => {\n\n // Fetch auth config (needsSetup, registrationEnabled, etc.)\n try {\n const config = await authApi.fetchAuthConfig();\n if (isMountedRef.current) {\n setAuthConfig(config);\n }\n } catch (e) { /* ignore */ }\n\n const stored = loadAuthFromStorage();\n\n if (!stored) {\n setInitialLoading(false);\n return;\n }\n\n if (!stored.tokens?.refreshToken) {\n clearAuthFromStorage();\n setInitialLoading(false);\n return;\n }\n\n\n // Validate accessTokenExpiresAt is a valid number\n const expiresAt = stored.tokens.accessTokenExpiresAt;\n if (typeof expiresAt !== \"number\" || !Number.isFinite(expiresAt)) {\n clearAuthFromStorage();\n setInitialLoading(false);\n return;\n }\n\n\n // Check if access token is still valid\n if (!isTokenExpiredOrNearExpiry(stored.tokens.accessTokenExpiresAt)) {\n // Token is still valid - use it directly\n tokensRef.current = stored.tokens;\n\n let userToSet = convertToUser(stored.user);\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(userToSet);\n if (customRoles) {\n userToSet = { ...userToSet,\nroles: customRoles.map(r => r.id) };\n }\n }\n\n setUser(userToSet);\n scheduleTokenRefresh(stored.tokens);\n setInitialLoading(false);\n return;\n }\n\n // Token is expired or near expiry - refresh it\n tokensRef.current = stored.tokens; // Set so refreshAccessToken can use it\n\n try {\n const newTokens = await refreshAccessToken();\n\n if (!newTokens) {\n clearAuthFromStorage();\n tokensRef.current = null;\n setInitialLoading(false);\n return;\n }\n\n if (!isMountedRef.current) return;\n\n // Fetch fresh user data from the server\n let userToSet: User;\n try {\n const meResponse = await authApi.getCurrentUser(newTokens.accessToken);\n\n if (!isMountedRef.current) return;\n\n const freshUserInfo = meResponse.user;\n\n // Update stored data with fresh user info\n saveAuthToStorage(newTokens, freshUserInfo);\n\n userToSet = convertToUser(freshUserInfo);\n\n if (defineRolesFor) {\n const customRoles = await defineRolesFor(userToSet);\n if (!isMountedRef.current) return;\n if (customRoles) {\n userToSet = { ...userToSet,\nroles: customRoles.map(r => r.id) };\n }\n }\n } catch (meError: unknown) {\n if (!isMountedRef.current) return;\n userToSet = convertToUser(stored.user);\n }\n\n if (!isMountedRef.current) return;\n\n setUser(userToSet);\n scheduleTokenRefresh(newTokens);\n } catch (error: unknown) {\n if (!isMountedRef.current) return;\n\n // Do not clear the session entirely if it's just a temporary network outage\n if (!(error instanceof Error && (error as { code?: string }).code === \"NETWORK_ERROR\")) {\n clearAuthFromStorage();\n tokensRef.current = null;\n }\n } finally {\n if (isMountedRef.current) {\n setInitialLoading(false);\n }\n }\n };\n\n restoreAuth();\n\n return () => {\n isMountedRef.current = false;\n };\n }, [scheduleTokenRefresh, defineRolesFor, refreshAccessToken]);\n\n // Handle visibility change - refresh token when user returns to tab\n useEffect(() => {\n const handleVisibilityChange = async () => {\n if (initialLoading) return;\n\n if (document.visibilityState === \"visible\" && tokensRef.current) {\n // Check if token needs refreshing\n if (isTokenExpiredOrNearExpiry(tokensRef.current.accessTokenExpiresAt)) {\n try {\n const newTokens = await refreshAccessToken();\n\n if (newTokens && isMountedRef.current) {\n scheduleTokenRefresh(newTokens);\n } else if (!newTokens && isMountedRef.current) {\n clearSessionAndSignOut();\n }\n } catch (e) { /* ignore */ }\n }\n }\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [initialLoading, refreshAccessToken, scheduleTokenRefresh, clearSessionAndSignOut]);\n\n\n // Get currently configured API URL\n const getApiUrl = useCallback(() => {\n return authApi.getApiUrl();\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n if (refreshTimeoutRef.current) {\n clearTimeout(refreshTimeoutRef.current);\n }\n };\n }, []);\n\n // Revoke all sessions\n const revokeAllSessions = useCallback(async () => {\n try {\n if (!tokensRef.current) {\n throw new Error(\"User is not logged in\");\n }\n await authApi.revokeAllSessions(tokensRef.current.accessToken);\n clearSessionAndSignOut();\n } catch (error: unknown) {\n setAuthProviderError(error as Error);\n throw error;\n }\n }, [clearSessionAndSignOut]);\n\n return {\n user,\n authLoading,\n initialLoading,\n authError,\n authProviderError,\n loginSkipped,\n needsSetup: authConfig?.needsSetup ?? false,\n registrationEnabled: authConfig?.registrationEnabled ?? false,\n getAuthToken,\n getApiUrl,\n signOut,\n emailPasswordLogin,\n register,\n googleLogin,\n oauthLogin,\n skipLogin,\n forgotPassword,\n resetPassword,\n changePassword,\n updateProfile,\n fetchSessions,\n revokeSession,\n revokeAllSessions,\n extra,\n setExtra,\n capabilities: {\n emailPasswordLogin: true,\n googleLogin: !!(props.googleClientId),\n registration: authConfig?.registrationEnabled ?? false,\n passwordReset: true,\n sessionManagement: true,\n profileUpdate: true,\n emailVerification: false,\n enabledProviders: authConfig?.enabledProviders ?? []\n }\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Role, User } from \"@rebasepro/types\";\n\n/**\n * UserManagement interface - compatible with @rebasepro/user_management\n * Defined inline to avoid dependency on that package\n */\nexport interface UserManagement<USER extends User = User> {\n loading: boolean;\n\n users: USER[];\n saveUser: (user: USER) => Promise<USER>;\n createUser?: (user: USER) => Promise<{\n user: USER;\n invitationSent: boolean;\n temporaryPassword?: string;\n }>;\n resetPassword?: (user: USER) => Promise<{\n user: USER;\n invitationSent: boolean;\n temporaryPassword?: string;\n }>;\n deleteUser: (user: USER) => Promise<void>;\n\n roles: Role[];\n saveRole: (role: Role) => Promise<void>;\n deleteRole: (role: Role) => Promise<void>;\n\n isAdmin?: boolean;\n allowDefaultRolesCreation?: boolean;\n includeCollectionConfigPermissions?: boolean;\n defineRolesFor: (user: User) => Promise<Role[] | undefined> | Role[] | undefined;\n getUser: (uid: string) => User | null;\n\n /**\n * Search users with server-side pagination.\n * When provided, the CMS will use this for the users table\n * instead of loading all users into memory.\n */\n searchUsers?: (options: {\n search?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n orderDir?: \"asc\" | \"desc\";\n roleId?: string;\n }) => Promise<{ users: USER[]; total: number }>;\n\n usersError?: Error;\n rolesError?: Error;\n bootstrapAdmin?: () => Promise<void>;\n}\n\nexport interface BackendUserManagementConfig {\n /**\n * The Rebase Client instance\n */\n client?: any;\n\n /**\n * Base API URL for the backend (optional, extracted from client if not provided)\n */\n apiUrl?: string;\n\n /**\n * Function to get the current auth token (optional, extracted from client if not provided)\n */\n getAuthToken?: () => Promise<string>;\n\n /**\n * Current logged-in user\n */\n currentUser?: User | null;\n}\n\ninterface ApiUser {\n uid: string;\n email: string;\n displayName?: string | null;\n photoURL?: string | null;\n roles: string[];\n createdAt?: string;\n updatedAt?: string;\n}\n\ninterface ApiRole {\n id: string;\n name: string;\n isAdmin?: boolean;\n config?: Record<string, any>;\n}\n\n/**\n * Convert API user to Rebase User\n * @param apiUser - The API user object\n * @param availableRoles - Optional array of available roles to look up names\n */\nfunction convertUser(apiUser: ApiUser): User {\n return {\n uid: apiUser.uid,\n email: apiUser.email,\n displayName: apiUser.displayName || null,\n photoURL: apiUser.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: apiUser.roles,\n createdAt: apiUser.createdAt ? new Date(apiUser.createdAt) : null\n } as User;\n}\n\n/**\n * Convert API role to Rebase Role\n */\nfunction convertRole(apiRole: ApiRole): Role {\n return {\n id: apiRole.id,\n name: apiRole.name,\n isAdmin: apiRole.isAdmin ?? false,\n config: apiRole.config ?? undefined\n };\n}\n\n/**\n * Hook to manage users and roles via backend API\n * Compatible with Rebase UserManagement interface\n */\nexport function useBackendUserManagement(config: BackendUserManagementConfig): UserManagement {\n const { client, apiUrl, getAuthToken, currentUser } = config;\n\n // We no longer load ALL users into memory.\n // `users` now only holds admin/role-bearing users for getUser/defineRolesFor lookups.\n const [users, setUsers] = useState<User[]>([]);\n const [roles, setRoles] = useState<Role[]>([]);\n const [loading, setLoading] = useState(true);\n const [usersError, setUsersError] = useState<Error | undefined>();\n const [rolesError, setRolesError] = useState<Error | undefined>();\n\n // Tracks the UID for which roles+users were last successfully loaded.\n // Prevents redundant refetches on React StrictMode double-mounts.\n const lastLoadedUidRef = useRef<string | null>(null);\n\n // Ref to hold the latest apiRequest so the initial-load effect doesn't\n // re-trigger every time the callback identity changes.\n const apiRequestRef = useRef<typeof apiRequest | null>(null);\n\n /**\n * Make authenticated API request\n */\n const apiRequest = useCallback(async (\n endpoint: string,\n method = \"GET\",\n body?: Record<string, unknown>,\n retryCount = 6,\n signal?: AbortSignal\n ): Promise<any> => {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < retryCount; attempt++) {\n if (signal?.aborted) {\n const error = new Error(\"Request aborted\");\n error.name = \"AbortError\";\n throw error;\n }\n\n try {\n // Determine token provider\n const token = getAuthToken ? await getAuthToken() : (client ? await client.resolveToken() : null);\n const baseUrl = apiUrl || (client?.baseUrl ? client.baseUrl : \"\");\n\n // Use /api/admin prefix for admin endpoints\n const response = await fetch(`${baseUrl}/api/admin${endpoint}`, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { \"Authorization\": `Bearer ${token}` } : {})\n },\n body: body ? JSON.stringify(body) : undefined,\n signal\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage = \"API request failed\";\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error?.message || errorMessage;\n } catch (e) {\n errorMessage = errorText || `HTTP error ${response.status}`;\n }\n\n const error = Object.assign(new Error(errorMessage), { status: response.status });\n throw error;\n }\n\n return await response.json();\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\" || signal?.aborted) {\n throw error;\n }\n\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Retry conditions: Network errors (TypeError) OR 5xx Server Errors (Backend rebooting)\n const isNetworkError = error instanceof TypeError;\n const isServerError = typeof (error as { status?: number }).status === \"number\" && (error as { status: number }).status >= 500 && (error as { status: number }).status < 600;\n\n if (attempt < retryCount - 1 && (isNetworkError || isServerError)) {\n const delay = Math.min(1000 * Math.pow(2, attempt), 5000); // 1s, 2s, 4s...\n console.warn(`Admin API request to ${endpoint} failed, retrying in ${delay}ms...`);\n\n // Wait for delay or abort\n await new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(new Error(\"AbortError\"));\n const timer = setTimeout(resolve, delay);\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n clearTimeout(timer);\n reject(new Error(\"AbortError\"));\n }, { once: true });\n }\n }).catch(() => {}); // Catch AbortError from wait\n\n if (signal?.aborted) {\n const abortError = new Error(\"Request aborted\");\n abortError.name = \"AbortError\";\n throw abortError;\n }\n continue;\n }\n\n console.error(\"Admin API error after retries:\", error);\n throw error;\n }\n }\n throw lastError;\n }, [apiUrl, getAuthToken]);\n\n // Keep the ref in sync after every render.\n apiRequestRef.current = apiRequest;\n\n /**\n * Load roles from API\n */\n const loadRoles = useCallback(async (signal?: AbortSignal) => {\n try {\n const data = await apiRequest(\"/roles\", \"GET\", undefined, 6, signal);\n setRoles(data.roles.map(convertRole));\n setRolesError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load roles:\", error);\n setRolesError(error instanceof Error ? error : new Error(String(error)));\n }\n }, [apiRequest]);\n\n /**\n * Load users for getUser/defineRolesFor lookups and for UserSelect dropdowns.\n */\n const loadUsers = useCallback(async (signal?: AbortSignal) => {\n try {\n // Load all users to satisfy Rebase CMS UserSelect field bindings\n const data = await apiRequest(\"/users\", \"GET\", undefined, 6, signal);\n const allUsers: User[] = data.users.map((u: ApiUser) => convertUser(u));\n setUsers(allUsers);\n setUsersError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load users:\", error);\n setUsersError(error instanceof Error ? error : new Error(String(error)));\n }\n }, [apiRequest]);\n\n /**\n * Initial data load - only when user is logged in\n * Load roles first, then admin users.\n *\n * Dependencies are intentionally limited to `currentUser?.uid` so the\n * effect does NOT re-run when callback identities change. The latest\n * `apiRequest` is read via `apiRequestRef`.\n */\n useEffect(() => {\n // Don't load if no user is logged in\n if (!currentUser) {\n setLoading(false);\n return;\n }\n\n // Skip refetch if we already loaded data for this same UID\n // (e.g. React StrictMode unmounts and re-mounts with the same user).\n if (lastLoadedUidRef.current === currentUser.uid) {\n setLoading(false);\n return;\n }\n\n const abortController = new AbortController();\n\n const load = async () => {\n setLoading(true);\n const request = apiRequestRef.current!;\n\n // Load roles first\n try {\n const data = await request(\"/roles\", \"GET\", undefined, 6, abortController.signal);\n setRoles(data.roles.map(convertRole));\n setRolesError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load roles:\", error);\n setRolesError(error instanceof Error ? error : new Error(String(error)));\n\n // If the error is a permission issue (e.g. 403), skip loading\n // users — they will fail with the same error and we'd show a\n // duplicate snackbar / error message.\n const status = (error as { status?: number }).status;\n if (status === 403 || status === 401) {\n setUsersError(error instanceof Error ? error : new Error(String(error)));\n setLoading(false);\n return;\n }\n }\n\n // Then load all users if not aborted\n if (!abortController.signal.aborted) {\n try {\n const data = await request(\"/users\", \"GET\", undefined, 6, abortController.signal);\n const allUsers: User[] = data.users.map((u: ApiUser) => convertUser(u));\n setUsers(allUsers);\n setUsersError(undefined);\n } catch (error: unknown) {\n if (error instanceof Error && error.name === \"AbortError\") return;\n console.error(\"Failed to load users:\", error);\n setUsersError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n if (!abortController.signal.aborted) {\n lastLoadedUidRef.current = currentUser.uid;\n setLoading(false);\n }\n };\n load();\n\n return () => {\n abortController.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentUser?.uid]);\n\n /**\n * Search users with server-side pagination.\n * This is the primary method used by the UsersView table.\n */\n const searchUsers = useCallback(async (options: {\n search?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n orderDir?: \"asc\" | \"desc\";\n roleId?: string;\n }): Promise<{ users: User[]; total: number }> => {\n const params = new URLSearchParams();\n if (options.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options.offset !== undefined) params.set(\"offset\", String(options.offset));\n if (options.search) params.set(\"search\", options.search);\n if (options.orderBy) params.set(\"orderBy\", options.orderBy);\n if (options.orderDir) params.set(\"orderDir\", options.orderDir);\n if (options.roleId) params.set(\"role\", options.roleId);\n const qs = params.toString();\n\n const data = await apiRequest(\"/users\" + (qs ? \"?\" + qs : \"\"), \"GET\");\n return {\n users: data.users.map((u: ApiUser) => convertUser(u)),\n total: data.total\n };\n }, [apiRequest]);\n\n /**\n * Save user (create or update)\n */\n const saveUser = useCallback(async (user: User): Promise<User> => {\n const roleIds = user.roles ?? [];\n\n // Check if user exists\n const existingUser = users.find(u => u.uid === user.uid);\n\n if (existingUser) {\n // Update\n const data = await apiRequest(`/users/${user.uid}`, \"PUT\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const updated = convertUser(data.user);\n setUsers(prev => prev.map(u => u.uid === updated.uid ? updated : u));\n return updated;\n } else {\n // Create\n const data = await apiRequest(\"/users\", \"POST\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const created = convertUser(data.user);\n setUsers(prev => [...prev, created]);\n return created;\n }\n }, [apiRequest, users, roles]);\n\n /**\n * Create a new user with invitation/password generation support.\n * Returns additional info about how credentials were delivered.\n */\n const createUser = useCallback(async (user: User): Promise<{\n user: User;\n invitationSent: boolean;\n temporaryPassword?: string;\n }> => {\n const roleIds = user.roles ?? [];\n\n const data = await apiRequest(\"/users\", \"POST\", {\n email: user.email,\n displayName: user.displayName,\n roles: roleIds\n });\n const created = convertUser(data.user);\n // Add to users cache\n setUsers(prev => [...prev, created]);\n return {\n user: created,\n invitationSent: data.invitationSent ?? false,\n temporaryPassword: data.temporaryPassword\n };\n }, [apiRequest, roles]);\n\n /**\n * Reset the password for an existing user\n */\n const resetPassword = useCallback(async (user: User): Promise<{\n user: User;\n invitationSent: boolean;\n temporaryPassword?: string;\n }> => {\n const data = await apiRequest(`/users/${user.uid}/reset-password`, \"POST\");\n const updatedUser = convertUser(data.user);\n setUsers(prev => prev.map(u => u.uid === updatedUser.uid ? updatedUser : u));\n return {\n user: updatedUser,\n invitationSent: data.invitationSent ?? false,\n temporaryPassword: data.temporaryPassword\n };\n }, [apiRequest]);\n\n /**\n * Delete user\n */\n const deleteUser = useCallback(async (user: User): Promise<void> => {\n await apiRequest(`/users/${user.uid}`, \"DELETE\");\n setUsers(prev => prev.filter(u => u.uid !== user.uid));\n }, [apiRequest]);\n\n /**\n * Save role (create or update)\n */\n const saveRole = useCallback(async (role: Role): Promise<void> => {\n // Check if role exists\n const existingRole = roles.find(r => r.id === role.id);\n\n if (existingRole) {\n // Update\n const data = await apiRequest(`/roles/${role.id}`, \"PUT\", {\n name: role.name,\n isAdmin: role.isAdmin,\n config: role.config\n });\n const updated = convertRole(data.role);\n setRoles(prev => prev.map(r => r.id === updated.id ? updated : r));\n } else {\n // Create\n const data = await apiRequest(\"/roles\", \"POST\", {\n id: role.id,\n name: role.name,\n isAdmin: role.isAdmin ?? false,\n config: role.config\n });\n const created = convertRole(data.role);\n setRoles(prev => [...prev, created]);\n }\n }, [apiRequest, roles]);\n\n /**\n * Delete role\n */\n const deleteRole = useCallback(async (role: Role): Promise<void> => {\n await apiRequest(`/roles/${role.id}`, \"DELETE\");\n setRoles(prev => prev.filter(r => r.id !== role.id));\n }, [apiRequest]);\n\n /**\n * Get user by uid\n */\n const getUser = useCallback((uid: string): User | null => {\n return users.find(u => u.uid === uid) ?? null;\n }, [users]);\n\n /**\n * Define roles for a given user (for authController)\n */\n const defineRolesFor = useCallback(async (user: User): Promise<Role[] | undefined> => {\n // Find the user in our list\n const existingUser = users.find(u => u.uid === user.uid || u.email === user.email);\n if (!existingUser) return undefined;\n\n // Return roles from our cached role data (string IDs → full Role objects)\n const userRoleIds = existingUser.roles ?? [];\n return roles.filter(r => userRoleIds.includes(r.id));\n }, [users, roles]);\n\n /**\n * Check if current user is admin\n */\n const isAdmin = currentUser?.roles?.includes(\"admin\") ?? false;\n\n\n /**\n * Bootstrap default admin\n */\n const bootstrapAdmin = useCallback(async (): Promise<void> => {\n try {\n await apiRequest(\"/bootstrap\", \"POST\");\n // Reload users and roles after successful bootstrap\n const data = await apiRequest(\"/roles\");\n const loadedRoles = data.roles.map(convertRole);\n setRoles(loadedRoles);\n await loadUsers();\n } catch (error) {\n console.error(\"Failed to bootstrap admin:\", error);\n throw error;\n }\n }, [apiRequest, loadUsers]);\n\n return {\n loading,\n users,\n saveUser,\n createUser,\n resetPassword,\n deleteUser,\n roles,\n saveRole,\n deleteRole,\n isAdmin,\n allowDefaultRolesCreation: true,\n includeCollectionConfigPermissions: true,\n defineRolesFor,\n getUser,\n searchUsers,\n usersError,\n rolesError,\n bootstrapAdmin\n };\n}\n","\nimport React, { ReactNode, useEffect, useRef, useState } from \"react\";\n\nimport { Button, CircularProgress, cls, IconButton, LoadingButton, Menu, MenuItem, TextField, Typography, iconSize } from \"@rebasepro/ui\";\nimport { ArrowLeftIcon, MailIcon, MoonIcon, SunIcon, SunMoonIcon } from \"lucide-react\";\nimport { ErrorView, LanguageToggle, RebaseLogo, useModeController, useTranslation } from \"@rebasepro/core\";\n\nimport { RebaseAuthController } from \"../types\";\n\n/**\n * Props for RebaseLoginView\n */\nexport interface RebaseLoginViewProps {\n /**\n * Auth controller from useRebaseAuthController\n */\n authController: RebaseAuthController;\n\n /**\n * Path to the logo displayed in the login screen\n */\n logo?: string;\n\n /**\n * Enable the skip login button\n */\n allowSkipLogin?: boolean;\n\n /**\n * Disable the login buttons\n */\n disabled?: boolean;\n\n /**\n * Prevent users from creating new accounts\n */\n disableSignupScreen?: boolean;\n\n /**\n * Display this component when no user is found\n */\n noUserComponent?: ReactNode;\n\n /**\n * Display this component below the sign-in buttons\n */\n additionalComponent?: ReactNode;\n\n /**\n * Error message when user is not allowed access\n */\n notAllowedError?: string | Error;\n\n /**\n * Enable Google login button (requires googleClientId in hook)\n */\n googleEnabled?: boolean;\n\n /**\n * Google client ID for OAuth\n */\n googleClientId?: string;\n}\n\ntype AuthMode = \"buttons\" | \"login\" | \"register\" | \"forgot\";\n\n/**\n * Login view component for custom JWT authentication\n */\nexport function RebaseLoginView({\n logo,\n authController,\n noUserComponent,\n disableSignupScreen = false,\n disabled = false,\n notAllowedError,\n googleEnabled = false,\n googleClientId\n}: RebaseLoginViewProps) {\n\n const modeState = useModeController();\n const { mode: colorMode, setMode: setColorMode } = modeState;\n const { t } = useTranslation();\n\n const [mode, setMode] = useState<AuthMode>(\"buttons\");\n const [fadeIn, setFadeIn] = useState(false);\n const [viewVisible, setViewVisible] = useState(true);\n\n const switchMode = (newMode: AuthMode) => {\n setViewVisible(false);\n setTimeout(() => {\n setMode(newMode);\n setViewVisible(true);\n }, 150);\n };\n\n // Auto-show setup form when no users exist (bootstrap mode)\n const isBootstrapMode = authController.needsSetup;\n\n useEffect(() => {\n const timer = setTimeout(() => setFadeIn(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n function buildErrorView() {\n if (!authController.authProviderError) return null;\n if (authController.user != null) return null;\n return (\n <div className=\"w-full\">\n <ErrorView error={authController.authProviderError.message ?? authController.authProviderError}/>\n </div>\n );\n }\n\n let logoComponent;\n if (logo) {\n logoComponent = <img src={logo}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\"\n }}\n alt={\"Logo\"}/>;\n } else {\n logoComponent = <RebaseLogo/>;\n }\n\n let notAllowedMessage: string | undefined;\n if (notAllowedError) {\n if (typeof notAllowedError === \"string\") {\n notAllowedMessage = notAllowedError;\n } else if (notAllowedError instanceof Error) {\n notAllowedMessage = notAllowedError.message;\n } else {\n notAllowedMessage = \"It looks like you don't have access to the CMS, based on the specified Authenticator configuration\";\n }\n }\n\n const showRegistration = !disableSignupScreen && authController.registrationEnabled;\n\n return (\n <div\n className={cls(\n \"relative flex items-center justify-center h-screen w-screen p-4 transition-opacity duration-500 bg-white dark:bg-surface-900\",\n fadeIn ? \"opacity-100\" : \"opacity-0\"\n )}>\n\n {/* Top-right controls */}\n <div className=\"absolute top-4 right-4 flex items-center gap-1 z-10\">\n <LanguageToggle/>\n <Menu\n trigger={<IconButton\n color=\"inherit\"\n aria-label=\"Toggle theme\">\n {colorMode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : <SunIcon size={iconSize.small}/>}\n </IconButton>}>\n <MenuItem onClick={() => setColorMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setColorMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")}</MenuItem>\n <MenuItem onClick={() => setColorMode(\"system\")}><SunMoonIcon size={iconSize.smallest}/> {t(\"system_mode\")}</MenuItem>\n </Menu>\n </div>\n\n <div className=\"flex flex-col items-center w-[480px] max-w-full p-8 sm:p-10\">\n {/* Logo */}\n <div className=\"w-32 h-32 m-2 mb-6\">\n {logoComponent}\n </div>\n\n {notAllowedMessage && (\n <div className=\"p-4 w-full\">\n <ErrorView error={notAllowedMessage}/>\n </div>\n )}\n\n {mode !== \"forgot\" && buildErrorView()}\n\n <div className={cls(\n \"w-full transition-opacity duration-150\",\n viewVisible ? \"opacity-100\" : \"opacity-0\"\n )}>\n {/* Bootstrap mode: show setup form directly */}\n {isBootstrapMode && !authController.user && (\n <LoginForm\n authController={authController}\n registrationMode={true}\n onClose={() => {}}\n onForgotPassword={() => {}}\n noUserComponent={noUserComponent}\n disableSignupScreen={false}\n bootstrapMode={true}\n />\n )}\n\n {/* Normal mode */}\n {!isBootstrapMode && (\n <>\n {/* Provider buttons screen */}\n {mode === \"buttons\" && (\n <div className=\"w-full flex flex-col gap-3 mt-2\">\n <LoginButton\n disabled={disabled}\n text={\"Sign in with email\"}\n icon={<MailIcon/>}\n onClick={() => switchMode(\"login\")}\n />\n {googleEnabled && googleClientId && (\n <GoogleLoginButton\n disabled={disabled}\n googleClientId={googleClientId}\n authController={authController}\n />\n )}\n {showRegistration && (\n <div className=\"mt-2 text-center\">\n <Typography variant=\"body2\" color=\"secondary\">\n Don&apos;t have an account?{\" \"}\n <button\n type=\"button\"\n className={cls(\n \"font-semibold hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={() => switchMode(\"register\")}\n >\n Create one\n </button>\n </Typography>\n </div>\n )}\n </div>\n )}\n\n {/* Login form */}\n {mode === \"login\" && (\n <LoginForm\n authController={authController}\n registrationMode={false}\n onClose={() => switchMode(\"buttons\")}\n onForgotPassword={() => switchMode(\"forgot\")}\n noUserComponent={noUserComponent}\n disableSignupScreen={disableSignupScreen}\n switchToRegister={showRegistration ? () => switchMode(\"register\") : undefined}\n />\n )}\n\n {/* Registration form */}\n {mode === \"register\" && (\n <LoginForm\n authController={authController}\n registrationMode={true}\n onClose={() => switchMode(\"buttons\")}\n onForgotPassword={() => switchMode(\"forgot\")}\n noUserComponent={noUserComponent}\n disableSignupScreen={disableSignupScreen}\n switchToLogin={() => switchMode(\"login\")}\n />\n )}\n\n {/* Forgot password form */}\n {mode === \"forgot\" && (\n <ForgotPasswordForm\n authController={authController}\n onClose={() => switchMode(\"login\")}\n />\n )}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction LoginButton({\n icon,\n onClick,\n text,\n disabled\n}: { icon: React.ReactNode, onClick: () => void, text: string, disabled?: boolean }) {\n return (\n <Button\n disabled={disabled}\n className=\"w-full\"\n variant=\"outlined\"\n size=\"large\"\n onClick={onClick}>\n <div className=\"flex items-center justify-center w-full gap-3 py-1\">\n <span className=\"flex items-center justify-center w-5 h-5\">\n {icon}\n </span>\n <Typography variant=\"button\">{text}</Typography>\n </div>\n </Button>\n );\n}\n\nconst GoogleIcon = () => (\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\">\n <path fill=\"#4285F4\"\n d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"/>\n <path fill=\"#34A853\"\n d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/>\n <path fill=\"#FBBC05\"\n d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/>\n <path fill=\"#EA4335\"\n d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/>\n </svg>\n);\n\n/** Google Identity Services SDK — injected by the GIS <script> tag. */\ndeclare global {\n interface Window {\n google?: {\n accounts: {\n oauth2: {\n initCodeClient(config: {\n client_id: string;\n scope: string;\n ux_mode: \"popup\" | \"redirect\";\n callback: (response: { code?: string; error?: string }) => void;\n }): { requestCode(): void };\n };\n };\n };\n }\n}\n\nfunction GoogleLoginButton({\n disabled,\n googleClientId,\n authController\n}: {\n disabled?: boolean,\n googleClientId: string,\n authController: RebaseAuthController\n}) {\n const codeClientRef = useRef<{ requestCode(): void } | null>(null);\n\n useEffect(() => {\n const google = window.google;\n if (!google || codeClientRef.current) return;\n\n codeClientRef.current = google.accounts.oauth2.initCodeClient({\n client_id: googleClientId,\n scope: \"openid email profile\",\n ux_mode: \"popup\",\n callback: async (response: { code?: string; error?: string }) => {\n if (response.error || !response.code) {\n console.error(\"Google login error:\", response.error);\n return;\n }\n try {\n // Send the authorization code to the backend.\n // redirectUri \"postmessage\" is required when using popup ux_mode.\n await authController.googleLogin({\n code: response.code,\n redirectUri: \"postmessage\"\n });\n } catch (err: unknown) {\n console.error(\"Google login error:\", err);\n }\n }\n });\n }, [googleClientId, authController]);\n\n const handleClick = () => {\n if (!codeClientRef.current) {\n console.error(\"Google Sign-In not loaded\");\n return;\n }\n codeClientRef.current.requestCode();\n };\n\n return (\n <LoginButton\n disabled={disabled}\n text=\"Sign in with Google\"\n icon={<GoogleIcon/>}\n onClick={handleClick}\n />\n );\n}\n\nfunction LoginForm({\n onClose,\n onForgotPassword,\n authController,\n registrationMode,\n noUserComponent,\n disableSignupScreen,\n bootstrapMode = false,\n switchToRegister,\n switchToLogin\n}: {\n onClose: () => void,\n onForgotPassword: () => void,\n authController: RebaseAuthController,\n registrationMode: boolean,\n noUserComponent?: ReactNode,\n disableSignupScreen: boolean,\n bootstrapMode?: boolean,\n switchToRegister?: () => void,\n switchToLogin?: () => void\n}) {\n const passwordRef = useRef<HTMLInputElement | null>(null);\n\n const [email, setEmail] = useState<string>();\n const [password, setPassword] = useState<string>();\n const [displayName, setDisplayName] = useState<string>();\n\n useEffect(() => {\n if (!document) return;\n const escFunction = (event: KeyboardEvent) => {\n if (event.keyCode === 27) {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", escFunction, false);\n return () => {\n document.removeEventListener(\"keydown\", escFunction, false);\n };\n }, [onClose]);\n\n function handleEnterPassword() {\n if (email && password) {\n authController.emailPasswordLogin(email, password);\n }\n }\n\n function handleRegistration() {\n if (email && password) {\n authController.register(email, password, displayName);\n }\n }\n\n const handleSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n if (registrationMode)\n handleRegistration();\n else\n handleEnterPassword();\n };\n\n const title = bootstrapMode\n ? \"Welcome!\"\n : registrationMode\n ? \"Create account\"\n : \"Sign in\";\n\n const subtitle = bootstrapMode\n ? \"Create your admin account to get started. This account will have admin privileges.\"\n : registrationMode\n ? \"Fill in your details to create a new account\"\n : \"Enter your credentials to continue\";\n\n const buttonLabel = registrationMode ? \"Create account\" : \"Sign in\";\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col w-full gap-1 mt-2\">\n {!bootstrapMode && (\n <div className=\"w-full mb-2 -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n )}\n\n <Typography variant=\"h6\" className=\"mb-0.5\">\n {title}\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\" className=\"mb-5\">\n {subtitle}\n </Typography>\n\n {registrationMode && noUserComponent && (\n <div className=\"w-full mb-2\">\n {noUserComponent}\n </div>\n )}\n\n {registrationMode && (\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Display Name\n </Typography>\n <TextField placeholder=\"Jane Doe (optional)\"\n className=\"w-full\"\n value={displayName ?? \"\"}\n disabled={authController.initialLoading}\n type=\"text\"\n size=\"medium\"\n onChange={(event) => setDisplayName(event.target.value)}/>\n </div>\n )}\n\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Email\n </Typography>\n <TextField placeholder=\"you@example.com\"\n className=\"w-full\"\n autoFocus\n value={email ?? \"\"}\n disabled={authController.initialLoading}\n type=\"email\"\n size=\"medium\"\n onChange={(event) => setEmail(event.target.value)}/>\n </div>\n\n <div className=\"w-full mb-1\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Password\n </Typography>\n <TextField placeholder=\"••••••••\"\n className=\"w-full\"\n value={password ?? \"\"}\n disabled={authController.initialLoading}\n inputRef={passwordRef}\n type=\"password\"\n size=\"medium\"\n onChange={(event) => setPassword(event.target.value)}/>\n </div>\n\n {registrationMode && (\n <Typography variant=\"caption\" color=\"secondary\" className=\"mb-3\">\n Password must be 8+ characters with uppercase, lowercase, and a number\n </Typography>\n )}\n\n {!registrationMode && (\n <div className=\"w-full text-right mb-3\">\n <button\n type=\"button\"\n className={cls(\n \"text-xs font-medium hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={onForgotPassword}\n >\n Forgot password?\n </button>\n </div>\n )}\n\n <LoadingButton\n type=\"submit\"\n variant=\"filled\"\n color=\"primary\"\n className=\"w-full mt-1\"\n size=\"large\"\n loading={authController.authLoading}\n disabled={authController.authLoading || !email || !password}\n >\n {buttonLabel}\n </LoadingButton>\n\n {/* Switch between login/register */}\n {switchToRegister && (\n <div className=\"mt-4 text-center\">\n <Typography variant=\"body2\" color=\"secondary\">\n Don&apos;t have an account?{\" \"}\n <button\n type=\"button\"\n className={cls(\n \"font-semibold hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={switchToRegister}\n >\n Create one\n </button>\n </Typography>\n </div>\n )}\n\n {switchToLogin && (\n <div className=\"mt-4 text-center\">\n <Typography variant=\"body2\" color=\"secondary\">\n Already have an account?{\" \"}\n <button\n type=\"button\"\n className={cls(\n \"font-semibold hover:underline cursor-pointer\",\n \"text-primary-600 dark:text-primary-400\"\n )}\n onClick={switchToLogin}\n >\n Sign in\n </button>\n </Typography>\n </div>\n )}\n </form>\n );\n}\n\nfunction ForgotPasswordForm({\n onClose,\n authController\n}: {\n onClose: () => void,\n authController: RebaseAuthController\n}) {\n const [email, setEmail] = useState<string>(\"\");\n const [submitted, setSubmitted] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!document) return;\n const escFunction = (event: KeyboardEvent) => {\n if (event.keyCode === 27) {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", escFunction, false);\n return () => {\n document.removeEventListener(\"keydown\", escFunction, false);\n };\n }, [onClose]);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n setError(null);\n\n if (!email) {\n setError(\"Please enter your email address\");\n return;\n }\n\n try {\n await authController.forgotPassword(email);\n setSubmitted(true);\n } catch (err: unknown) {\n // Check for EMAIL_NOT_CONFIGURED error\n if (err instanceof Error && (err as { code?: string }).code === \"EMAIL_NOT_CONFIGURED\") {\n setError(\"Password reset is not available. Please contact your administrator.\");\n } else {\n // Still show success (security: don't reveal if email exists)\n setSubmitted(true);\n }\n }\n };\n\n if (submitted) {\n return (\n <div className=\"flex flex-col w-full gap-4 mt-2\">\n <div className=\"w-full -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n\n <div className={cls(\n \"text-center rounded-xl p-6\",\n \"bg-surface-50 dark:bg-surface-950\"\n )}>\n <div className=\"text-3xl mb-3\">📧</div>\n <Typography variant=\"subtitle1\" className=\"mb-2\">\n Check your email\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\">\n If an account exists for <strong>{email}</strong>, you&apos;ll receive a password reset link shortly.\n </Typography>\n </div>\n\n <Button onClick={onClose} variant=\"text\" className=\"mt-2\">\n Back to sign in\n </Button>\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col w-full gap-1 mt-2\">\n <div className=\"w-full mb-2 -ml-2.5\">\n <IconButton onClick={onClose}>\n <ArrowLeftIcon/>\n </IconButton>\n </div>\n\n <Typography variant=\"h6\" className=\"mb-0.5\">\n Reset password\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\" className=\"mb-5\">\n Enter your email and we&apos;ll send you a reset link.\n </Typography>\n\n {error && (\n <div className=\"w-full mb-3\">\n <ErrorView error={error}/>\n </div>\n )}\n\n <div className=\"w-full mb-3\">\n <Typography variant=\"label\" color=\"secondary\" className=\"mb-1\">\n Email\n </Typography>\n <TextField\n placeholder=\"you@example.com\"\n className=\"w-full\"\n autoFocus\n value={email}\n type=\"email\"\n size=\"medium\"\n onChange={(event) => setEmail(event.target.value)}\n />\n </div>\n\n <LoadingButton\n type=\"submit\"\n variant=\"filled\"\n color=\"primary\"\n className=\"w-full\"\n size=\"large\"\n loading={authController.authLoading}\n disabled={authController.authLoading || !email}\n >\n Send reset link\n </LoadingButton>\n </form>\n );\n}\n","import React, { useLayoutEffect, useRef } from \"react\";\nimport { useRebaseRegistryDispatch } from \"@rebasepro/core\";\nimport type { RebaseAuthConfig } from \"@rebasepro/types\";\n\n/**\n * Declarative component to configure authentication in Rebase.\n * Renders nothing — purely registers config into the RebaseRegistry.\n */\nexport function RebaseAuth({ loginView }: RebaseAuthConfig) {\n const dispatch = useRebaseRegistryDispatch();\n const registeredRef = useRef(false);\n\n useLayoutEffect(() => {\n dispatch.registerAuth({ loginView });\n registeredRef.current = true;\n return () => {\n registeredRef.current = false;\n dispatch.unregisterAuth();\n };\n }, [dispatch, loginView]);\n\n return null;\n}\n","\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport {\n useSnackbarController,\n ConfirmationDialog,\n useAuthController\n} from \"@rebasepro/core\";\nimport { AppView, EntityCollection, Role, SecurityRule, User } from \"@rebasepro/types\";\n\nimport { Button, Chip, Container, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Paper, Table, TableBody, TableCell, TableHeader, TableRow, TextField, Typography, CircularProgress, CenteredView, Tooltip, Checkbox, MultiSelect, MultiSelectItem, LoadingButton, getColorSchemeForSeed, ChipColorScheme, ChipColorKey } from \"@rebasepro/ui\";\nimport { PlusIcon, Trash2Icon } from \"lucide-react\";\nimport { UserManagement } from \"../hooks/useBackendUserManagement\";\n\ninterface AdminViewsProps {\n userManagement: UserManagement;\n apiUrl: string;\n getAuthToken: () => Promise<string>;\n collections?: EntityCollection[];\n}\n\n/**\n * Create admin views for user and role management\n */\nexport function createUserManagementAdminViews({ userManagement, apiUrl, getAuthToken, collections = [] }: AdminViewsProps): AppView[] {\n return [\n {\n slug: \"dev/users\",\n name: \"CMS Users\",\n icon: \"face\",\n view: <UsersView userManagement={userManagement} apiUrl={apiUrl} getAuthToken={getAuthToken}/>\n },\n {\n slug: \"dev/roles\",\n name: \"Roles\",\n icon: \"gpp_good\",\n view: <RolesView userManagement={userManagement} collections={collections}/>\n }\n ];\n}\n\n// ============================================\n// RoleChip Component (matches original)\n// ============================================\nfunction RoleChip({ role }: { role: Role }) {\n let colorScheme: ChipColorScheme | ChipColorKey;\n if (role.isAdmin) {\n colorScheme = \"blue\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellow\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"gray\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip colorScheme={colorScheme} key={role.id}>\n {role.name}\n </Chip>\n );\n}\n\n// ============================================\n// UsersView Component\n// ============================================\nexport function UsersView({ userManagement, apiUrl, getAuthToken }: {\n userManagement: UserManagement;\n apiUrl: string;\n getAuthToken: () => Promise<string>;\n}) {\n const { users, roles, saveUser, deleteUser, loading } = userManagement;\n const usersError = 'usersError' in userManagement ? (userManagement as { usersError?: Error }).usersError : undefined;\n const snackbarController = useSnackbarController();\n const { user: loggedInUser } = useAuthController();\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedUser, setSelectedUser] = useState<User | undefined>();\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n const [userToDelete, setUserToDelete] = useState<User | undefined>();\n const [deleteInProgress, setDeleteInProgress] = useState(false);\n const [formKey, setFormKey] = useState(0);\n const [bootstrapping, setBootstrapping] = useState(false);\n\n // Check if any admin exists\n const hasAdmin = users.some(u => u.roles?.includes(\"admin\"));\n\n const handleBootstrap = async () => {\n setBootstrapping(true);\n try {\n const token = await getAuthToken();\n const response = await fetch(`${apiUrl}/api/admin/bootstrap`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`\n }\n });\n const data = await response.json();\n if (!response.ok) {\n throw new Error(data.error?.message || \"Bootstrap failed\");\n }\n snackbarController.open({ type: \"success\",\nmessage: \"You are now an admin! Refreshing...\" });\n // Reload to get new roles\n window.location.reload();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to bootstrap admin\" });\n } finally {\n setBootstrapping(false);\n }\n };\n\n const handleAddUser = () => {\n setSelectedUser(undefined);\n setFormKey(k => k + 1);\n setDialogOpen(true);\n };\n\n const handleEditUser = (user: User) => {\n setSelectedUser(user);\n setDialogOpen(true);\n };\n\n const handleClose = () => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n };\n\n const handleDelete = async () => {\n if (!userToDelete) return;\n setDeleteInProgress(true);\n try {\n await deleteUser(userToDelete);\n snackbarController.open({ type: \"success\",\nmessage: \"User deleted successfully\" });\n setDeleteConfirmOpen(false);\n setUserToDelete(undefined);\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Error deleting user\" });\n } finally {\n setDeleteInProgress(false);\n }\n };\n\n if (loading) {\n return <CenteredView><CircularProgress/></CenteredView>;\n }\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n {/* Bootstrap warning when no admins */}\n {!hasAdmin && loggedInUser && (\n <div className=\"bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 rounded p-4 flex items-center justify-between\">\n <div>\n <Typography variant=\"label\" className=\"text-yellow-800 dark:text-yellow-200\">\n No admin users exist. You can make yourself an admin.\n </Typography>\n </div>\n <Button\n onClick={handleBootstrap}\n disabled={bootstrapping}\n >\n {bootstrapping ? <CircularProgress size=\"small\"/> : \"Make me admin\"}\n </Button>\n </div>\n )}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\" className=\"grow\" component=\"h4\">\n Users\n </Typography>\n <Button startIcon={<PlusIcon/>} onClick={handleAddUser}>\n Add user\n </Button>\n </div>\n\n <div className=\"overflow-auto\">\n <Table className=\"w-full\">\n <TableHeader>\n <TableCell header className=\"truncate w-16\"></TableCell>\n <TableCell header>Email</TableCell>\n <TableCell header>Name</TableCell>\n <TableCell header>Roles</TableCell>\n </TableHeader>\n <TableBody>\n {users.map(user => (\n <TableRow key={user.uid} onClick={() => handleEditUser(user)}>\n <TableCell style={{ width: \"64px\" }}>\n <Tooltip asChild title=\"Delete this user\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setUserToDelete(user);\n setDeleteConfirmOpen(true);\n }}>\n <Trash2Icon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className=\"font-medium\">{user.displayName}</TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-2\">\n {user.roles?.map((roleId: string) => {\n const role = roles.find(r => r.id === roleId);\n return role ? <RoleChip key={roleId} role={role}/> : <span key={roleId}>{roleId}</span>;\n })}\n </div>\n </TableCell>\n </TableRow>\n ))}\n\n {users.length === 0 && (\n <TableRow>\n <TableCell colspan={4}>\n <CenteredView className=\"flex flex-col gap-4 my-8 items-center\">\n <Typography variant=\"label\">\n {usersError\n ? \"You don't have permission to view users\"\n : \"There are no users yet\"}\n </Typography>\n {usersError && (\n <Typography variant=\"caption\" className=\"text-surface-500\">\n Contact an administrator if you need access to this section.\n </Typography>\n )}\n </CenteredView>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n\n {/* User Edit Dialog */}\n <UserDetailsForm\n key={selectedUser?.uid ?? `new-${formKey}`}\n open={dialogOpen}\n user={selectedUser}\n roles={roles}\n saveUser={saveUser}\n handleClose={handleClose}\n />\n\n {/* Delete Confirmation */}\n <ConfirmationDialog\n open={deleteConfirmOpen}\n loading={deleteInProgress}\n onAccept={handleDelete}\n onCancel={() => { setDeleteConfirmOpen(false); setUserToDelete(undefined); }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}\n />\n </Container>\n );\n}\n\n// ============================================\n// UserDetailsForm Component (matches original)\n// ============================================\nfunction UserDetailsForm({\n open,\n user: userProp,\n roles,\n saveUser,\n handleClose\n}: {\n open: boolean;\n user?: User;\n roles: Role[];\n saveUser: (user: User) => Promise<User>;\n handleClose: () => void;\n}) {\n const snackbarController = useSnackbarController();\n const isNewUser = !userProp;\n\n const [displayName, setDisplayName] = useState(userProp?.displayName || \"\");\n const [email, setEmail] = useState(userProp?.email || \"\");\n const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>(\n userProp?.roles || [\"editor\"]\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<{ displayName?: string; email?: string; roles?: string }>({});\n const [submitCount, setSubmitCount] = useState(0);\n\n const validate = () => {\n const newErrors: typeof errors = {};\n if (!displayName) newErrors.displayName = \"Required\";\n if (!email) newErrors.email = \"Required\";\n else if (!/\\S+@\\S+\\.\\S+/.test(email)) newErrors.email = \"Invalid email\";\n if (selectedRoleIds.length === 0) newErrors.roles = \"At least one role is required\";\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setSubmitCount(c => c + 1);\n\n if (!validate()) return;\n\n setIsSubmitting(true);\n try {\n const userToSave: User = {\n uid: userProp?.uid || crypto.randomUUID(),\n email,\n displayName: displayName || null,\n photoURL: userProp?.photoURL || null,\n providerId: \"custom\",\n isAnonymous: false,\n roles: selectedRoleIds\n };\n await saveUser(userToSave);\n handleClose();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to save user\" });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const dirty = isNewUser ||\n displayName !== (userProp?.displayName || \"\") ||\n email !== (userProp?.email || \"\") ||\n JSON.stringify(selectedRoleIds.sort()) !== JSON.stringify((userProp?.roles || []).sort());\n\n return (\n <Dialog open={open} onOpenChange={(open) => !open ? handleClose() : undefined} maxWidth=\"4xl\">\n <form onSubmit={handleSubmit} autoComplete=\"off\" noValidate\n style={{ display: \"flex\",\nflexDirection: \"column\",\nposition: \"relative\",\nheight: \"100%\" }}>\n\n <DialogTitle variant=\"h4\" gutterBottom={false}>\n User\n </DialogTitle>\n\n <DialogContent className=\"h-full grow\">\n <div className=\"grid grid-cols-12 gap-4\">\n <div className=\"col-span-12\">\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && errors.displayName ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12\">\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n label=\"Email\"\n disabled={!isNewUser}\n />\n <FieldCaption>\n {submitCount > 0 && errors.email ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12\">\n <MultiSelect\n className=\"w-full\"\n label=\"Roles\"\n value={selectedRoleIds}\n onValueChange={(value: string[]) => setSelectedRoleIds(value)}\n >\n {roles.map(role => (\n <MultiSelectItem key={role.id} value={role.id}>\n <RoleChip role={role}/>\n </MultiSelectItem>\n ))}\n </MultiSelect>\n </div>\n </div>\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Dialog>\n );\n}\n\n// ============================================\n// RolesView Component\n// ============================================\nexport function RolesView({ userManagement, collections = [] }: { userManagement: UserManagement, collections?: EntityCollection[] }) {\n const { roles, saveRole, deleteRole, loading, allowDefaultRolesCreation } = userManagement;\n const rolesError = 'rolesError' in userManagement ? (userManagement as { rolesError?: Error }).rolesError : undefined;\n const snackbarController = useSnackbarController();\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n const [roleToDelete, setRoleToDelete] = useState<Role | undefined>();\n const [deleteInProgress, setDeleteInProgress] = useState(false);\n\n const handleAddRole = () => {\n setSelectedRole(undefined);\n setDialogOpen(true);\n };\n\n const handleEditRole = (role: Role) => {\n setSelectedRole(role);\n setDialogOpen(true);\n };\n\n const handleClose = () => {\n setDialogOpen(false);\n setSelectedRole(undefined);\n };\n\n const handleDelete = async () => {\n if (!roleToDelete) return;\n setDeleteInProgress(true);\n try {\n await deleteRole(roleToDelete);\n snackbarController.open({ type: \"success\",\nmessage: \"Role deleted successfully\" });\n setDeleteConfirmOpen(false);\n setRoleToDelete(undefined);\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Error deleting role\" });\n } finally {\n setDeleteInProgress(false);\n }\n };\n\n const createDefaultRoles = () => {\n const defaultRoles: Role[] = [\n { id: \"admin\",\nname: \"Admin\",\nisAdmin: true },\n { id: \"editor\",\nname: \"Editor\",\nisAdmin: false },\n { id: \"viewer\",\nname: \"Viewer\",\nisAdmin: false }\n ];\n defaultRoles.forEach(role => saveRole(role));\n };\n\n if (loading) {\n return <CenteredView><CircularProgress/></CenteredView>;\n }\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\" className=\"grow\" component=\"h4\">\n Roles\n </Typography>\n <Button startIcon={<PlusIcon/>} onClick={handleAddRole}>\n Add role\n </Button>\n </div>\n\n <div className=\"w-full overflow-auto\">\n <Table className=\"w-full\">\n <TableHeader>\n <TableCell header className=\"w-16\"></TableCell>\n <TableCell header>Role</TableCell>\n <TableCell header className=\"items-center\">Is Admin</TableCell>\n </TableHeader>\n <TableBody>\n {roles.map(role => {\n return (\n <TableRow key={role.id} onClick={() => handleEditRole(role)}>\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin && (\n <Tooltip asChild title=\"Delete this role\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setRoleToDelete(role);\n setDeleteConfirmOpen(true);\n }}>\n <Trash2Icon/>\n </IconButton>\n </Tooltip>\n )}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className=\"items-center\">\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n </TableRow>\n );\n })}\n\n {roles.length === 0 && (\n <TableRow>\n <TableCell colspan={4}>\n <CenteredView className=\"flex flex-col gap-4 my-8 items-center\">\n <Typography variant=\"label\">\n {rolesError\n ? \"You don't have permission to view roles\"\n : \"You don\\u0026apos;t have any roles yet.\"}\n </Typography>\n {rolesError && (\n <Typography variant=\"caption\" className=\"text-surface-500\">\n Contact an administrator if you need access to this section.\n </Typography>\n )}\n {!rolesError && allowDefaultRolesCreation && (\n <Button onClick={createDefaultRoles}>\n Create default roles\n </Button>\n )}\n </CenteredView>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n\n {/* Role Edit Dialog */}\n <RoleDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n saveRole={saveRole}\n handleClose={handleClose}\n collections={collections}\n />\n\n {/* Delete Confirmation */}\n <ConfirmationDialog\n open={deleteConfirmOpen}\n loading={deleteInProgress}\n onAccept={handleDelete}\n onCancel={() => { setDeleteConfirmOpen(false); setRoleToDelete(undefined); }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}\n />\n </Container>\n );\n}\n\n// ============================================\n// RoleDetailsForm Component\n// ============================================\nfunction RoleDetailsForm({\n open,\n role: roleProp,\n saveRole,\n handleClose,\n collections = []\n}: {\n open: boolean;\n role?: Role;\n saveRole: (role: Role) => Promise<void>;\n handleClose: () => void;\n collections?: EntityCollection[];\n}) {\n const snackbarController = useSnackbarController();\n const isNewRole = !roleProp;\n\n const [roleId, setRoleId] = useState(roleProp?.id || \"\");\n const [roleName, setRoleName] = useState(roleProp?.name || \"\");\n const [isAdmin, setIsAdmin] = useState(roleProp?.isAdmin ?? false);\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<{ id?: string; name?: string }>({});\n const [submitCount, setSubmitCount] = useState(0);\n\n const validate = () => {\n const newErrors: typeof errors = {};\n if (!roleId) newErrors.id = \"Required\";\n if (!roleName) newErrors.name = \"Required\";\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setSubmitCount(c => c + 1);\n\n if (!validate()) return;\n\n setIsSubmitting(true);\n try {\n await saveRole({\n id: roleId,\n name: roleName,\n isAdmin\n });\n handleClose();\n } catch (error: unknown) {\n snackbarController.open({ type: \"error\",\nmessage: error instanceof Error ? error.message : \"Failed to save role\" });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={(open) => !open ? handleClose() : undefined} maxWidth=\"6xl\">\n <form onSubmit={handleSubmit} autoComplete=\"off\" noValidate\n style={{ display: \"flex\",\nflexDirection: \"column\",\nposition: \"relative\",\nheight: \"100%\" }}>\n\n <DialogTitle variant=\"h4\" gutterBottom={false}>\n Role\n </DialogTitle>\n\n <DialogContent className=\"h-full grow overflow-y-auto\">\n <div className=\"grid grid-cols-12 gap-4\">\n <div className=\"col-span-12 sm:col-span-4\">\n <TextField\n name=\"id\"\n required\n error={submitCount > 0 && Boolean(errors.id)}\n value={roleId}\n onChange={(e) => setRoleId(e.target.value)}\n label=\"Role ID\"\n disabled={!isNewRole}\n />\n <FieldCaption>\n {submitCount > 0 && errors.id ? errors.id : \"Unique identifier for this role\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12 sm:col-span-4\">\n <TextField\n name=\"name\"\n required\n error={submitCount > 0 && Boolean(errors.name)}\n value={roleName}\n onChange={(e) => setRoleName(e.target.value)}\n label=\"Role Name\"\n />\n <FieldCaption>\n {submitCount > 0 && errors.name ? errors.name : \"Display name for this role\"}\n </FieldCaption>\n </div>\n\n <div className=\"col-span-12 sm:col-span-4 flex items-start pt-2\">\n <label className=\"flex items-center gap-2 cursor-pointer mt-3\">\n <Checkbox\n checked={isAdmin}\n onCheckedChange={(checked) => setIsAdmin(Boolean(checked))}\n />\n <span className=\"font-medium\">Is Admin</span>\n </label>\n </div>\n\n {/* Permissions matrix */}\n <div className=\"col-span-12\">\n <CollectionPermissionsMatrix roleId={roleId} isAdmin={isAdmin} collections={collections}/>\n </div>\n </div>\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n type=\"submit\"\n loading={isSubmitting}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Dialog>\n );\n}\n\n// ============================================\n// CollectionPermissionsMatrix Component\n// ============================================\nconst CRUD_OPS = [\n { op: \"select\" as const,\nlabel: \"Read\" },\n { op: \"insert\" as const,\nlabel: \"Create\" },\n { op: \"update\" as const,\nlabel: \"Edit\" },\n { op: \"delete\" as const,\nlabel: \"Delete\" }\n];\n\n/** Inline check: does roleId have access for this operation on these securityRules? */\nfunction hasRoleAccess(\n rules: SecurityRule[] | undefined,\n roleId: string,\n op: \"select\" | \"insert\" | \"update\" | \"delete\"\n): boolean {\n if (!rules || rules.length === 0) return true; // no rules = unrestricted\n const applicable = rules.filter(r =>\n r.operation === op || r.operation === \"all\" ||\n r.operations?.includes(op) || r.operations?.includes(\"all\")\n );\n if (applicable.length === 0) return false;\n const forRole = applicable.filter(r =>\n !r.roles || r.roles.length === 0 || r.roles.includes(roleId) || r.roles.includes(\"public\")\n );\n if (forRole.length === 0) return false;\n // Restrictive rules: any failing one denies immediately\n for (const r of forRole) {\n if ((r.mode ?? \"permissive\") === \"restrictive\") return false;\n }\n return forRole.some(r => (r.mode ?? \"permissive\") === \"permissive\");\n}\n\nfunction PermCell({ granted }: { granted: boolean }) {\n return (\n <span className={granted\n ? \"text-green-500 dark:text-green-400 text-base select-none\"\n : \"text-surface-300 dark:text-surface-600 text-base select-none\"}\n >\n {granted ? \"✓\" : \"✗\"}\n </span>\n );\n}\n\nfunction CollectionPermissionsMatrix({ roleId, isAdmin, collections }: { roleId: string; isAdmin: boolean; collections: EntityCollection[] }) {\n if (!collections || collections.length === 0) {\n return (\n <div className=\"mt-4\">\n <Typography variant=\"label\" className=\"text-surface-400\">No collections configured</Typography>\n </div>\n );\n }\n\n const topLevel = collections;\n\n return (\n <div className=\"mt-6\">\n <Typography variant=\"label\" className=\"mb-2 block text-surface-600 dark:text-surface-400 uppercase tracking-wide text-xs\">\n Collection permissions\n </Typography>\n <div className=\"rounded-lg border border-surface-200 dark:border-surface-700 overflow-hidden\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableCell header>Collection</TableCell>\n {CRUD_OPS.map(({ op, label }) => (\n <TableCell key={op} header className=\"text-center w-24\">{label}</TableCell>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {topLevel.map((collection) => {\n const extCol = collection as EntityCollection & { securityRules?: SecurityRule[] };\n const noRules = !extCol.securityRules || extCol.securityRules.length === 0;\n return (\n <TableRow key={collection.slug}>\n <TableCell>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{collection.name}</span>\n {noRules && !isAdmin && (\n <Tooltip title=\"No security rules — unrestricted\">\n <Chip className=\"text-xs\" colorScheme=\"yellow\">No rules</Chip>\n </Tooltip>\n )}\n </div>\n <span className=\"text-xs text-surface-400 font-mono\">{collection.slug}</span>\n </TableCell>\n {CRUD_OPS.map(({ op }) => (\n <TableCell key={op} className=\"text-center\">\n <PermCell granted={isAdmin || hasRoleAccess(extCol.securityRules, roleId, op)}/>\n </TableCell>\n ))}\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n {!roleId && (\n <Typography variant=\"caption\" className=\"mt-2 text-surface-400 italic\">\n Enter a role ID above to preview permissions\n </Typography>\n )}\n </div>\n );\n}\n\n// ============================================\n// Internal Components\n// ============================================\nfunction FieldCaption({ children }: React.PropsWithChildren) {\n return (\n <Typography variant=\"caption\" className=\"text-surface-500 mt-1.5 ml-1 block\">\n {children}\n </Typography>\n );\n}\n"],"names":["authApi.setApiUrl","refreshAccessToken","authApi.refreshAccessToken","authApi.login","register","authApi.register","googleLogin","authApi.googleLogin","oauthLogin","authApi.oauthLogin","authApi.logout","forgotPassword","authApi.forgotPassword","resetPassword","authApi.resetPassword","changePassword","authApi.changePassword","updateProfile","authApi.updateProfile","fetchSessions","authApi.fetchSessions","revokeSession","authApi.revokeSession","authApi.fetchAuthConfig","authApi.getCurrentUser","getApiUrl","authApi.getApiUrl","revokeAllSessions","authApi.revokeAllSessions","open"],"mappings":"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"}