@habeetat/sdk-react 0.2.1-dev.20260608104910.8a516ec → 0.2.1-dev.20260618083959.3cb5192
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _habeetat_sdk_core from '@habeetat/sdk-core';
|
|
3
|
-
import { SdkContext, SdkFeaturesState, SdkSubscription, SdkAvailablePlan, LogLevel, SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';
|
|
4
|
-
export { BillingScope, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext } from '@habeetat/sdk-core';
|
|
3
|
+
import { SdkContext, SdkFeaturesState, SdkSubscription, SdkAvailablePlan, LogLevel, SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext, SdkGroupContext } from '@habeetat/sdk-core';
|
|
4
|
+
export { BillingScope, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkGroupContext, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext } from '@habeetat/sdk-core';
|
|
5
5
|
import * as react from 'react';
|
|
6
6
|
import { ReactNode } from 'react';
|
|
7
7
|
|
|
@@ -425,6 +425,28 @@ interface UseUserReturn {
|
|
|
425
425
|
*/
|
|
426
426
|
declare function useUser(): UseUserReturn;
|
|
427
427
|
|
|
428
|
+
interface UseGroupsReturn {
|
|
429
|
+
/** Groups the current user belongs to in the active tenant */
|
|
430
|
+
groups: SdkGroupContext[];
|
|
431
|
+
/** True if the user belongs to the group with the given key */
|
|
432
|
+
isInGroup: (key: string) => boolean;
|
|
433
|
+
/** True if the user belongs to any of the given group keys */
|
|
434
|
+
hasAnyGroup: (keys: string[]) => boolean;
|
|
435
|
+
isLoading: boolean;
|
|
436
|
+
error: Error | null;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Hook exposing the current user's groups, sourced from the already-loaded
|
|
440
|
+
* SDK context (no extra network request) — twin of `usePermissions`.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```tsx
|
|
444
|
+
* const { groups, isInGroup } = useGroups();
|
|
445
|
+
* if (isInGroup('finance')) { ... }
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
declare function useGroups(): UseGroupsReturn;
|
|
449
|
+
|
|
428
450
|
/**
|
|
429
451
|
* Minimal interface for an object with request interceptors.
|
|
430
452
|
* Compatible with Axios, ky, and similar HTTP clients.
|
|
@@ -560,4 +582,4 @@ interface RequireFeatureProps {
|
|
|
560
582
|
*/
|
|
561
583
|
declare function RequireFeature({ flag, children, fallback }: RequireFeatureProps): react_jsx_runtime.JSX.Element;
|
|
562
584
|
|
|
563
|
-
export { type AuthState, type BillingPortalParams, type CheckoutParams, type FrontendLoggerConfig, HabeetatContext, type HabeetatContextValue, HabeetatProvider, type HabeetatProviderProps, type HabeetatState, type LogtoConfig, RequireFeature, RequirePermission, type UseAnalyticsReturn, type UseBillingPortalReturn, type UseCheckoutReturn, type UseLoggerReturn, type UsePlansReturn, type UseUserReturn, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
|
585
|
+
export { type AuthState, type BillingPortalParams, type CheckoutParams, type FrontendLoggerConfig, HabeetatContext, type HabeetatContextValue, HabeetatProvider, type HabeetatProviderProps, type HabeetatState, type LogtoConfig, RequireFeature, RequirePermission, type UseAnalyticsReturn, type UseBillingPortalReturn, type UseCheckoutReturn, type UseGroupsReturn, type UseLoggerReturn, type UsePlansReturn, type UseUserReturn, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useGroups, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _habeetat_sdk_core from '@habeetat/sdk-core';
|
|
3
|
-
import { SdkContext, SdkFeaturesState, SdkSubscription, SdkAvailablePlan, LogLevel, SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';
|
|
4
|
-
export { BillingScope, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext } from '@habeetat/sdk-core';
|
|
3
|
+
import { SdkContext, SdkFeaturesState, SdkSubscription, SdkAvailablePlan, LogLevel, SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext, SdkGroupContext } from '@habeetat/sdk-core';
|
|
4
|
+
export { BillingScope, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkGroupContext, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext } from '@habeetat/sdk-core';
|
|
5
5
|
import * as react from 'react';
|
|
6
6
|
import { ReactNode } from 'react';
|
|
7
7
|
|
|
@@ -425,6 +425,28 @@ interface UseUserReturn {
|
|
|
425
425
|
*/
|
|
426
426
|
declare function useUser(): UseUserReturn;
|
|
427
427
|
|
|
428
|
+
interface UseGroupsReturn {
|
|
429
|
+
/** Groups the current user belongs to in the active tenant */
|
|
430
|
+
groups: SdkGroupContext[];
|
|
431
|
+
/** True if the user belongs to the group with the given key */
|
|
432
|
+
isInGroup: (key: string) => boolean;
|
|
433
|
+
/** True if the user belongs to any of the given group keys */
|
|
434
|
+
hasAnyGroup: (keys: string[]) => boolean;
|
|
435
|
+
isLoading: boolean;
|
|
436
|
+
error: Error | null;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Hook exposing the current user's groups, sourced from the already-loaded
|
|
440
|
+
* SDK context (no extra network request) — twin of `usePermissions`.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```tsx
|
|
444
|
+
* const { groups, isInGroup } = useGroups();
|
|
445
|
+
* if (isInGroup('finance')) { ... }
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
declare function useGroups(): UseGroupsReturn;
|
|
449
|
+
|
|
428
450
|
/**
|
|
429
451
|
* Minimal interface for an object with request interceptors.
|
|
430
452
|
* Compatible with Axios, ky, and similar HTTP clients.
|
|
@@ -560,4 +582,4 @@ interface RequireFeatureProps {
|
|
|
560
582
|
*/
|
|
561
583
|
declare function RequireFeature({ flag, children, fallback }: RequireFeatureProps): react_jsx_runtime.JSX.Element;
|
|
562
584
|
|
|
563
|
-
export { type AuthState, type BillingPortalParams, type CheckoutParams, type FrontendLoggerConfig, HabeetatContext, type HabeetatContextValue, HabeetatProvider, type HabeetatProviderProps, type HabeetatState, type LogtoConfig, RequireFeature, RequirePermission, type UseAnalyticsReturn, type UseBillingPortalReturn, type UseCheckoutReturn, type UseLoggerReturn, type UsePlansReturn, type UseUserReturn, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
|
585
|
+
export { type AuthState, type BillingPortalParams, type CheckoutParams, type FrontendLoggerConfig, HabeetatContext, type HabeetatContextValue, HabeetatProvider, type HabeetatProviderProps, type HabeetatState, type LogtoConfig, RequireFeature, RequirePermission, type UseAnalyticsReturn, type UseBillingPortalReturn, type UseCheckoutReturn, type UseGroupsReturn, type UseLoggerReturn, type UsePlansReturn, type UseUserReturn, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useGroups, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
package/dist/index.js
CHANGED
|
@@ -734,6 +734,19 @@ function useUser() {
|
|
|
734
734
|
error
|
|
735
735
|
};
|
|
736
736
|
}
|
|
737
|
+
function useGroups() {
|
|
738
|
+
const { context, isLoading, error } = react.useContext(HabeetatContext);
|
|
739
|
+
const groups = context?.groups ?? [];
|
|
740
|
+
const isInGroup = react.useCallback(
|
|
741
|
+
(key) => groups.some((g) => g.key === key),
|
|
742
|
+
[groups]
|
|
743
|
+
);
|
|
744
|
+
const hasAnyGroup = react.useCallback(
|
|
745
|
+
(keys) => groups.some((g) => keys.includes(g.key)),
|
|
746
|
+
[groups]
|
|
747
|
+
);
|
|
748
|
+
return { groups, isInGroup, hasAnyGroup, isLoading, error };
|
|
749
|
+
}
|
|
737
750
|
function useHttpInterceptor(httpClient) {
|
|
738
751
|
const { getAccessToken } = useHabeetat();
|
|
739
752
|
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
@@ -902,6 +915,7 @@ exports.useAuth = useAuth;
|
|
|
902
915
|
exports.useBillingPortal = useBillingPortal;
|
|
903
916
|
exports.useCheckout = useCheckout;
|
|
904
917
|
exports.useFeatures = useFeatures;
|
|
918
|
+
exports.useGroups = useGroups;
|
|
905
919
|
exports.useHabeetat = useHabeetat;
|
|
906
920
|
exports.useHttpInterceptor = useHttpInterceptor;
|
|
907
921
|
exports.useLogger = useLogger;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["createContext","useHandleSignInCallback","jsx","Fragment","useLogto","useRef","useEffect","useState","useMemo","useCallback","SDK_ENDPOINTS","LogtoProvider","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n return;\n }\n // If activated (free plan), no redirect needed — caller can handle\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { startCheckout, isLoading, error };\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface BillingPortalParams {\n /**\n * URL to return to after the user exits the Stripe Customer Portal.\n * Defaults to `window.location.origin + '/profile'`.\n */\n returnUrl?: string;\n}\n\nexport interface UseBillingPortalReturn {\n /** Open the Stripe Customer Portal. Redirects the browser on success. */\n openPortal: (params?: BillingPortalParams) => Promise<void>;\n /** Whether a portal session creation is in progress */\n isLoading: boolean;\n /** Error from the last portal attempt */\n error: Error | null;\n}\n\n/**\n * Hook for opening the Stripe Customer Portal via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `POST /users/:userId/billing/portal`\n * - TENANT scope (B2B): calls `POST /tenants/:tenantSlug/billing/portal`\n *\n * On success, redirects the browser to the Stripe Customer Portal URL.\n *\n * @example\n * ```tsx\n * const { openPortal, isLoading, error } = useBillingPortal();\n *\n * const handleManageBilling = () => {\n * openPortal({ returnUrl: `${window.location.origin}/profile` });\n * };\n * ```\n */\nexport function useBillingPortal(): UseBillingPortalReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const openPortal = useCallback(async (params?: BillingPortalParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const returnUrl = params?.returnUrl ?? `${window.location.origin}/profile`;\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/billing/portal`;\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/billing/portal`;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ returnUrl }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Billing portal failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { portalUrl?: string; url?: string };\n const portalUrl = data.portalUrl ?? data.url;\n\n if (portalUrl) {\n window.location.href = portalUrl;\n }\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { openPortal, isLoading, error };\n}\n","import { type ReactNode } from 'react';\nimport { usePermissions } from '../hooks/usePermissions';\n\ninterface RequirePermissionProps {\n permission: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if user has the required permission\n */\nexport function RequirePermission({ permission, children, fallback = null }: RequirePermissionProps) {\n const { hasPermission } = usePermissions();\n \n if (!hasPermission(permission)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n","import { type ReactNode } from 'react';\nimport { useFeatures } from '../hooks/useFeatures';\n\ninterface RequireFeatureProps {\n flag: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if the feature flag is enabled\n */\nexport function RequireFeature({ flag, children, fallback = null }: RequireFeatureProps) {\n const { isEnabled } = useFeatures();\n \n if (!isEnabled(flag)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useGroups.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["createContext","useHandleSignInCallback","jsx","Fragment","useLogto","useRef","useEffect","useState","useMemo","useCallback","SDK_ENDPOINTS","LogtoProvider","useContext"],"mappings":";;;;;;;;AAmEA,IAAM,mBAAA,GAA4C;AAAA,EAChD,SAAA,EAAW,IAAA;AAAA,EACX,KAAA,EAAO,IAAA;AAAA,EACP,OAAA,EAAS,IAAA;AAAA,EACT,QAAA,EAAU,IAAA;AAAA,EACV,YAAA,EAAc,IAAA;AAAA,EACd,gBAAA,EAAkB,IAAA;AAAA,EAClB,yBAAA,EAA2B,IAAA;AAAA,EAC3B,qBAAA,EAAuB,IAAA;AAAA,EACvB,gBAAgB,YAAY;AAAA,EAAC,CAAA;AAAA,EAC7B,iBAAiB,YAAY;AAAA,EAAC,CAAA;AAAA,EAC9B,qBAAqB,YAAY;AAAA,EAAC,CAAA;AAAA,EAClC,yBAAyB,YAAY;AAAA,EAAC,CAAA;AAAA,EACtC,eAAe,MAAM,KAAA;AAAA,EACrB,kBAAkB,MAAM,KAAA;AAAA,EACxB,mBAAmB,MAAM,KAAA;AAAA,EACzB,kBAAkB,MAAM,KAAA;AAAA,EACxB,gBAAgB,YAAY,IAAA;AAAA,EAC5B,WAAA,EAAa,IAAA;AAAA,EACb,SAAS,YAAY;AAAA,EAAC;AACxB,CAAA;AAKO,IAAM,eAAA,GAAkBA,oBAAoC,mBAAmB;ACxBtF,SAAS,eAAA,CAAgB,EAAE,eAAA,EAAgB,EAAyB;AAClE,EAAA,MAAM,EAAE,SAAA,EAAU,GAAIC,+BAAA,CAAwB,MAAM;AAClD,IAAA,MAAA,CAAO,SAAS,IAAA,GAAO,GAAA;AAAA,EACzB,CAAC,CAAA;AAED,EAAA,IAAI,SAAA,EAAW,OAAO,eAAA,mBAAkBC,cAAA,CAAAC,mBAAA,EAAA,EAAG,2BAAgB,CAAA,GAAM,IAAA;AACjE,EAAA,OAAO,IAAA;AACT;AAuBA,SAAS,aAAA,CAAc;AAAA,EACrB,WAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,sBAAA;AAAA,EACA;AACF,CAAA,EAAe;AACb,EAAA,MAAM,EAAE,eAAA,EAAiB,SAAA,EAAW,YAAA,EAAc,cAAA,EAAgB,MAAA,EAAQ,cAAA,EAAgB,KAAA,EAAO,UAAA,EAAY,OAAA,EAAS,YAAA,EAAa,GAAIC,gBAAA,EAAS;AAEhJ,EAAA,MAAM,gBAAgB,aAAA,IAAiB,WAAA;AACvC,EAAA,MAAM,YAAA,GAAeC,aAAO,KAAK,CAAA;AACjC,EAAA,MAAM,UAAA,GAAaA,aAAO,KAAK,CAAA;AAE/B,EAAA,MAAM,eAAA,GAAkBA,aAAO,KAAK,CAAA;AAEpC,EAAA,MAAM,iBAAA,GAAoBA,aAAO,CAAC,CAAA;AAClC,EAAA,MAAM,oBAAA,GAAuB,CAAA;AAE7B,EAAA,MAAM,aACJ,OAAO,MAAA,KAAW,WAAA,IAClB,MAAA,CAAO,SAAS,QAAA,KAAa,YAAA;AAG/B,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,UAAA,IAAc,YAAA,IAAgB,eAAA,IAAmB,CAAC,cAAc,YAAA,CAAa,OAAA;AAC/E,MAAA;AACF,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,IAAA,MAAM,WAAA,GACJ,OAAO,MAAA,KAAW,WAAA,GACd,CAAA,EAAG,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,GACxC,YAAA;AACN,IAAA,MAAA,CAAO,WAAW,CAAA;AAAA,EACpB,CAAA,EAAG,CAAC,UAAA,EAAY,YAAA,EAAc,iBAAiB,UAAA,EAAY,MAAA,EAAQ,YAAY,CAAC,CAAA;AAIhF,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,cAAA,CAAwB;AAAA,IAChD,SAAA,EAAW,IAAA;AAAA,IACX,KAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAS,IAAA;AAAA,IACT,QAAA,EAAU,IAAA;AAAA,IACV,YAAA,EAAc,IAAA;AAAA,IACd,gBAAA,EAAkB,IAAA;AAAA,IAClB,yBAAA,EAA2B,IAAA;AAAA,IAC3B,qBAAA,EAAuB;AAAA,GACxB,CAAA;AAED,EAAA,MAAM,MAAA,GAASC,aAAA,CAAQ,MAAM,WAAA,CAAY,OAAA,CAAQ,OAAO,EAAE,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAG1E,EAAA,MAAM,iBAAA,GAAoBH,aAAO,cAAc,CAAA;AAC/C,EAAA,iBAAA,CAAkB,OAAA,GAAU,cAAA;AAE5B,EAAA,MAAM,YAAA,GAAeI,iBAAA;AAAA,IACnB,OAAW,QAAA,KAAiC;AAC1C,MAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,QAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,MAChD;AACA,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQ,MAAM,iBAAA,CAAkB,OAAA,CAAQ,aAAa,CAAA;AAAA,MACvD,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,GAAG,CAAA,CAAE,CAAA;AAAA,MACtD;AACA,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAEvD,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAA,EAAU,MAAM,CAAA;AACpC,MAAA,IAAI,UAAA,EAAY,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,cAAc,UAAU,CAAA;AAC7D,MAAA,IAAI,KAAA,EAAO,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,SAAS,KAAK,CAAA;AAE9C,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,QAC3C,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,UAC9B,cAAA,EAAgB;AAAA;AAClB,OACD,CAAA;AACD,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,WAAA,EAAc,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AACjE,MAAA,OAAO,SAAS,IAAA,EAAK;AAAA,IACvB,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,aAAA,EAAe,UAAA,EAAY,KAAK;AAAA,GAC3C;AAEA,EAAA,MAAM,WAAA,GAAcJ,aAAO,YAAY,CAAA;AACvC,EAAA,WAAA,CAAY,OAAA,GAAU,YAAA;AAEtB,EAAA,MAAM,cAAA,GAAiBI,kBAAY,YAAY;AAC7C,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,OAAA,CAAoBC,sBAAc,OAAO,CAAA;AAC3E,MAAA,QAAA,CAAS,CAAC,UAAU,EAAE,GAAG,MAAM,OAAA,EAAS,KAAA,EAAO,MAAK,CAAE,CAAA;AAAA,IACxD,SAAS,KAAA,EAAO;AACd,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU,EAAE,GAAG,IAAA,EAAM,OAAsB,CAAE,CAAA;AAAA,IACzD;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,eAAA,GAAkBD,kBAAY,YAAY;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,OAAA,CAA0BC,sBAAc,QAAQ,CAAA;AACnF,MAAA,QAAA,CAAS,CAAC,UAAU,EAAE,GAAG,MAAM,QAAA,EAAU,KAAA,EAAO,MAAK,CAAE,CAAA;AAAA,IACzD,SAAS,KAAA,EAAO;AACd,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU,EAAE,GAAG,IAAA,EAAM,OAAsB,CAAE,CAAA;AAAA,IACzD;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,mBAAA,GAAsBD,kBAAY,YAAY;AAClD,IAAA,IAAI;AACF,MAAA,MAAM,YAAA,GAAe,MAAM,WAAA,CAAY,OAAA,CAAyBC,sBAAc,YAAY,CAAA;AAC1F,MAAA,QAAA,CAAS,CAAC,UAAU,EAAE,GAAG,MAAM,YAAA,EAAc,KAAA,EAAO,MAAK,CAAE,CAAA;AAAA,IAC7D,SAAS,KAAA,EAAO;AACd,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU,EAAE,GAAG,IAAA,EAAM,OAAsB,CAAE,CAAA;AAAA,IACzD;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,uBAAA,GAA0BD,iBAAA,CAAY,OAAO,MAAA,KAAoB;AACrE,IAAA,QAAA,CAAS,CAAC,UAAU,EAAE,GAAG,MAAM,yBAAA,EAA2B,IAAA,EAAM,qBAAA,EAAuB,IAAA,EAAK,CAAE,CAAA;AAC9F,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,MAAA,IAAI,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,MAAM,CAAA;AACtC,MAAA,MAAM,WAAA,GAAc,OAAO,QAAA,EAAS;AACpC,MAAA,MAAM,QAAA,GAAW,GAAGC,qBAAA,CAAc,iBAAiB,GAAG,WAAA,GAAc,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAC1F,MAAA,MAAM,gBAAA,GAAmB,MAAM,WAAA,CAAY,OAAA,CAAyB,QAAQ,CAAA;AAC5E,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,QAClB,GAAG,IAAA;AAAA,QACH,gBAAA;AAAA,QACA,yBAAA,EAA2B,KAAA;AAAA,QAC3B,qBAAA,EAAuB;AAAA,OACzB,CAAE,CAAA;AAAA,IACJ,SAAS,GAAA,EAAK;AAEZ,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,QAClB,GAAG,IAAA;AAAA,QACH,yBAAA,EAA2B,KAAA;AAAA,QAC3B,qBAAA,EAAuB;AAAA,OACzB,CAAE,CAAA;AAAA,IACJ;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgBD,iBAAA;AAAA,IACpB,CAAC,UAAA,KAAuB,KAAA,CAAM,SAAS,WAAA,EAAa,QAAA,CAAS,UAAU,CAAA,IAAK,KAAA;AAAA,IAC5E,CAAC,KAAA,CAAM,OAAA,EAAS,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,gBAAA,GAAmBA,iBAAA;AAAA,IACvB,CAAC,WAAA,KAA0B,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,KAAA,CAAM,OAAA,EAAS,WAAA,EAAa,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,IAC1F,CAAC,KAAA,CAAM,OAAA,EAAS,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,iBAAA,GAAoBA,iBAAA;AAAA,IACxB,CAAC,WAAA,KAA0B,WAAA,CAAY,KAAA,CAAM,CAAC,CAAA,KAAM,KAAA,CAAM,OAAA,EAAS,WAAA,EAAa,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,IAC3F,CAAC,KAAA,CAAM,OAAA,EAAS,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,gBAAA,GAAmBA,iBAAA;AAAA,IACvB,CAAC,GAAA,KAAgB,KAAA,CAAM,QAAA,EAAU,QAAA,GAAW,GAAG,CAAA,IAAK,KAAA;AAAA,IACpD,CAAC,KAAA,CAAM,QAAA,EAAU,QAAQ;AAAA,GAC3B;AAEA,EAAA,MAAM,SAAA,GAAYA,iBAAA;AAAA,IAChB,OAAO,qBAAA,KAAmC;AACxC,MAAA,MAAM,GAAA,GAAM,0BACN,sBAAA,GACA,CAAA,EAAG,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,sBAAsB,CAAA,CAAA,GAClD,MAAA,CAAA;AACN,MAAA,MAAM,aAAa,GAAG,CAAA;AAAA,IACxB,CAAA;AAAA,IACA,CAAC,cAAc,sBAAsB;AAAA,GACvC;AAEA,EAAA,MAAM,QAAA,GAAWA,kBAAY,YAAoC;AAC/D,IAAA,IAAI,eAAA,CAAgB,SAAS,OAAO,IAAA;AAKpC,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC5B,QAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,QAAA,IAAI;AAAE,UAAA,MAAM,cAAA,EAAe;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAoB;AAC1D,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,WAAA,GACJ,OAAO,MAAA,KAAW,WAAA,GACd,CAAA,EAAG,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,GACxC,YAAA;AACN,UAAA,MAAA,CAAO,WAAW,CAAA;AAAA,QACpB;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAS,MAAM,iBAAA,CAAkB,OAAA,CAAQ,aAAa,CAAA,IAAM,IAAA;AAElE,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,iBAAA,CAAkB,OAAA,GAAU,CAAA;AAC5B,QAAA,OAAO,KAAA;AAAA,MACT;AAIA,MAAA,iBAAA,CAAkB,OAAA,IAAW,CAAA;AAC7B,MAAA,IAAI,iBAAA,CAAkB,OAAA,IAAW,oBAAA,IAAwB,CAAC,gBAAgB,OAAA,EAAS;AACjF,QAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,QAAA,IAAI;AAAE,UAAA,MAAM,cAAA,EAAe;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAoB;AAC1D,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,WAAA,GACJ,OAAO,MAAA,KAAW,WAAA,GACd,CAAA,EAAG,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,GACxC,YAAA;AACN,UAAA,MAAA,CAAO,WAAW,CAAA;AAAA,QACpB;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,GAAA,EAAK;AAEZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,MAAM,eACJ,OAAA,CAAQ,QAAA,CAAS,eAAe,CAAA,IAChC,OAAA,CAAQ,SAAS,0BAA0B,CAAA;AAE7C,MAAA,IAAI,YAAA,IAAgB,CAAC,eAAA,CAAgB,OAAA,EAAS;AAC5C,QAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,QAAA,IAAI;AAAE,UAAA,MAAM,cAAA,EAAe;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAoB;AAC1D,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,WAAA,GACJ,OAAO,MAAA,KAAW,WAAA,GACd,CAAA,EAAG,OAAO,QAAA,CAAS,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,GACxC,YAAA;AACN,UAAA,MAAA,CAAO,WAAW,CAAA;AAAA,QACpB;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA,EAAG,CAAC,aAAA,EAAe,UAAA,EAAY,cAAc,MAAA,EAAQ,cAAA,EAAgB,UAAU,CAAC,CAAA;AAGhF,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,YAAA,IAAgB,CAAC,eAAA,IAAmB,UAAA,CAAW,OAAA,EAAS;AAC5D,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAErB,IAAA,MAAM,WAAW,YAAY;AAC3B,MAAA,QAAA,CAAS,CAAC,UAAU,EAAE,GAAG,MAAM,SAAA,EAAW,IAAA,EAAM,yBAAA,EAA2B,IAAA,EAAK,CAAE,CAAA;AAClF,MAAA,IAAI;AAEF,QAAA,MAAM,CAAC,OAAA,EAAS,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UAC5C,YAAY,OAAA,CAAoBI,qBAAA,CAAc,OAAO,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,UACvE,YAAY,OAAA,CAA0BA,qBAAA,CAAc,QAAQ,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI;AAAA,SAC/E,CAAA;AAED,QAAA,MAAM,YAAA,GAAe,SAAS,GAAA,EAAK,YAAA;AACnC,QAAA,MAAM,MAAA,GAAS,SAAS,IAAA,EAAM,EAAA;AAG9B,QAAA,IAAI,YAAA,GAAuC,IAAA;AAC3C,QAAA,IAAI,gBAAA,GAA2C,IAAA;AAC/C,QAAA,IAAI,qBAAA,GAAsC,IAAA;AAE1C,QAAA,IAAI,YAAA,KAAiB,UAAU,MAAA,EAAQ;AAErC,UAAA,IAAI;AACF,YAAA,gBAAA,GAAmB,MAAM,WAAA,CAAY,OAAA;AAAA,cACnCA,qBAAA,CAAc;AAAA,aAChB;AAAA,UACF,SAAS,GAAA,EAAK;AACZ,YAAA,qBAAA,GAAwB,GAAA;AAAA,UAC1B;AAAA,QACF,CAAA,MAAA,IAAW,iBAAiB,QAAA,EAAU;AAEpC,UAAA,YAAA,GAAe,MAAM,WAAA,CAAY,OAAA;AAAA,YAC/BA,qBAAA,CAAc;AAAA,WAChB,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,QAEpB,CAAA,MAAO;AAEL,UAAA,YAAA,GAAe,MAAM,WAAA,CAAY,OAAA;AAAA,YAC/BA,qBAAA,CAAc;AAAA,WAChB,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAClB,UAAA,IAAI,MAAA,EAAQ;AACV,YAAA,IAAI;AACF,cAAA,gBAAA,GAAmB,MAAM,WAAA,CAAY,OAAA;AAAA,gBACnCA,qBAAA,CAAc;AAAA,eAChB;AAAA,YACF,SAAS,GAAA,EAAK;AACZ,cAAA,qBAAA,GAAwB,GAAA;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAEA,QAAA,QAAA,CAAS;AAAA,UACP,SAAA,EAAW,KAAA;AAAA,UACX,KAAA,EAAO,IAAA;AAAA,UACP,OAAA;AAAA,UACA,QAAA;AAAA,UACA,YAAA;AAAA,UACA,gBAAA;AAAA,UACA,yBAAA,EAA2B,KAAA;AAAA,UAC3B;AAAA,SACD,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,UAClB,GAAG,IAAA;AAAA,UACH,SAAA,EAAW,KAAA;AAAA,UACX,yBAAA,EAA2B,KAAA;AAAA,UAC3B;AAAA,SACF,CAAE,CAAA;AAAA,MACJ;AAAA,IACF,CAAA;AAEA,IAAA,QAAA,EAAS;AAAA,EACX,CAAA,EAAG,CAAC,YAAA,EAAc,eAAe,CAAC,CAAA;AAElC,EAAA,MAAM,YAAA,GAAqCF,aAAA;AAAA,IACzC,OAAO;AAAA,MACL,GAAG,KAAA;AAAA,MACH,cAAA;AAAA,MACA,eAAA;AAAA,MACA,mBAAA;AAAA,MACA,uBAAA;AAAA,MACA,aAAA;AAAA,MACA,gBAAA;AAAA,MACA,iBAAA;AAAA,MACA,gBAAA;AAAA,MACA,cAAA,EAAgB,QAAA;AAAA,MAChB,WAAA,EAAa,MAAA;AAAA,MACb,OAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA,EAAc,OAAA;AAAA,MACd,OAAA,EAAS;AAAA,KACX,CAAA;AAAA,IACA;AAAA,MACE,KAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,mBAAA;AAAA,MACA,uBAAA;AAAA,MACA,aAAA;AAAA,MACA,gBAAA;AAAA,MACA,iBAAA;AAAA,MACA,gBAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA;AACF,GACF;AAGA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,uBAAON,cAAA,CAAC,mBAAgB,eAAA,EAAkC,CAAA;AAAA,EAC5D;AAGA,EAAA,sCACG,eAAA,CAAgB,QAAA,EAAhB,EAAyB,KAAA,EAAO,cAC9B,QAAA,EACH,CAAA;AAEJ;AA+BO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,KAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA,GAAa,KAAA;AAAA,EACb,YAAA,GAAe,WAAA;AAAA,EACf,eAAA;AAAA,EACA,OAAA;AAAA,EACA,sBAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,iBAAiBG,YAAA,CAAO;AAAA,IAC5B,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,GAAI,KAAA,CAAM,SAAA,IAAa,EAAE,SAAA,EAAW,MAAM,SAAA,EAAU;AAAA,IACpD,GAAI,KAAA,CAAM,MAAA,IAAU,EAAE,MAAA,EAAQ,MAAM,MAAA;AAAO,GAC5C,CAAA;AACD,EAAA,MAAM,cAAc,cAAA,CAAe,OAAA;AAEnC,EAAA,uBACEH,cAAA,CAACS,qBAAA,EAAA,EAAc,MAAA,EAAQ,WAAA,EACrB,QAAA,kBAAAT,cAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,WAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA,eAAA;AAAA,MACA,OAAA;AAAA,MACA,sBAAA;AAAA,MAEC;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;ACpgBO,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAUU,iBAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AAEA,EAAA,OAAO,OAAA;AACT;;;ACFO,SAAS,cAAA,GAAiB;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAS,aAAA,EAAe,gBAAA,EAAkB,iBAAA,KAAsB,WAAA,EAAY;AAEpF,EAAA,OAAO;AAAA;AAAA,IAEL,WAAA,EAAa,OAAA,EAAS,WAAA,IAAe,EAAC;AAAA;AAAA,IAEtC,KAAA,EAAO,OAAA,EAAS,KAAA,IAAS,EAAC;AAAA;AAAA,IAE1B,aAAA;AAAA;AAAA,IAEA,gBAAA;AAAA;AAAA,IAEA;AAAA,GACF;AACF;;;ACrBO,SAAS,WAAA,GAAc;AAC5B,EAAA,MAAM,EAAE,QAAA,EAAU,gBAAA,EAAkB,eAAA,KAAoB,WAAA,EAAY;AAEpE,EAAA,OAAO;AAAA;AAAA,IAEL,QAAA,EAAU,QAAA,EAAU,QAAA,IAAY,EAAC;AAAA;AAAA,IAEjC,QAAQ,QAAA,EAAU,MAAA;AAAA;AAAA,IAElB,UAAU,QAAA,EAAU,QAAA;AAAA;AAAA,IAEpB,SAAA,EAAW,gBAAA;AAAA;AAAA,IAEX,OAAA,EAAS;AAAA,GACX;AACF;;;AC5BO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,EAAE,YAAA,EAAc,mBAAA,EAAoB,GAAI,WAAA,EAAY;AAE1D,EAAA,OAAO;AAAA;AAAA,IAEL,YAAA;AAAA;AAAA,IAEA,MAAM,YAAA,EAAc,IAAA;AAAA;AAAA,IAEpB,MAAA,EAAQ,YAAA,EAAc,MAAA,IAAU,EAAC;AAAA;AAAA,IAEjC,KAAA,EAAO,YAAA,EAAc,KAAA,IAAS,EAAC;AAAA;AAAA,IAE/B,QAAQ,YAAA,EAAc,MAAA;AAAA;AAAA,IAEtB,QAAA,EAAU,YAAA,EAAc,MAAA,KAAW,QAAA,IAAY,cAAc,MAAA,KAAW,OAAA;AAAA;AAAA,IAExE,UAAA,EAAY,cAAc,MAAA,KAAW,OAAA;AAAA;AAAA,IAErC,UAAA,EAAY,CAAC,GAAA,EAAa,SAAA,GAAY,CAAA,KAAe;AACnD,MAAA,MAAM,KAAA,GAAQ,YAAA,EAAc,MAAA,GAAS,GAAG,CAAA;AACxC,MAAA,MAAM,OAAA,GAAU,YAAA,EAAc,KAAA,GAAQ,GAAG,CAAA,IAAK,CAAA;AAC9C,MAAA,IAAI,KAAA,KAAU,QAAW,OAAO,IAAA;AAChC,MAAA,OAAO,UAAU,SAAA,IAAa,KAAA;AAAA,IAChC,CAAA;AAAA;AAAA,IAEA,OAAA,EAAS;AAAA,GACX;AACF;ACfO,SAAS,mBAAA,GAAsB;AACpC,EAAA,MAAM;AAAA,IACJ,gBAAA;AAAA,IACA,OAAA;AAAA,IACA,uBAAA;AAAA,IACA,yBAAA;AAAA,IACA;AAAA,MACE,WAAA,EAAY;AAEhB,EAAA,MAAM,MAAA,GAAS,SAAS,IAAA,EAAM,EAAA;AAE9B,EAAA,MAAM,OAAA,GAAUH,iBAAAA;AAAA,IACd,CAAC,KAAA,KAAmB,uBAAA,CAAwB,KAAK,CAAA;AAAA,IACjD,CAAC,uBAAuB;AAAA,GAC1B;AAEA,EAAA,OAAO;AAAA;AAAA,IAEL,YAAA,EAAc,gBAAA;AAAA;AAAA,IAEd,MAAM,gBAAA,EAAkB,IAAA;AAAA;AAAA,IAExB,MAAA,EAAQ,gBAAA,EAAkB,MAAA,IAAU,EAAC;AAAA;AAAA,IAErC,KAAA,EAAO,gBAAA,EAAkB,KAAA,IAAS,EAAC;AAAA;AAAA,IAEnC,QAAQ,gBAAA,EAAkB,MAAA;AAAA;AAAA,IAE1B,QAAA,EAAU,gBAAA,EAAkB,MAAA,KAAW,QAAA,IAAY,kBAAkB,MAAA,KAAW,OAAA;AAAA;AAAA,IAEhF,UAAA,EAAY,kBAAkB,MAAA,KAAW,OAAA;AAAA;AAAA,IAEzC,eAAA,EAAiB,gBAAA,KAAqB,IAAA,IAAQ,gBAAA,KAAqB,MAAA;AAAA;AAAA,IAEnE,UAAA,EAAY,CAAC,GAAA,EAAa,SAAA,GAAY,CAAA,KAAe;AACnD,MAAA,MAAM,KAAA,GAAQ,gBAAA,EAAkB,MAAA,GAAS,GAAG,CAAA;AAC5C,MAAA,MAAM,OAAA,GAAU,gBAAA,EAAkB,KAAA,GAAQ,GAAG,CAAA,IAAK,CAAA;AAClD,MAAA,IAAI,KAAA,KAAU,QAAW,OAAO,IAAA;AAChC,MAAA,OAAO,UAAU,SAAA,IAAa,KAAA;AAAA,IAChC,CAAA;AAAA;AAAA,IAEA,OAAA;AAAA;AAAA,IAEA,MAAA;AAAA;AAAA,IAEA,SAAA,EAAW,yBAAA;AAAA;AAAA,IAEX,KAAA,EAAO;AAAA,GACT;AACF;AC/CO,SAAS,QAAA,GAA2B;AACzC,EAAA,MAAM,EAAE,WAAA,EAAa,KAAA,EAAM,GAAI,WAAA,EAAY;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIF,cAAAA,CAA6B,EAAE,CAAA;AACzD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAS,IAAI,CAAA;AAC/C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,UAAA,GAAaF,aAAO,KAAK,CAAA;AAE/B,EAAA,MAAM,UAAA,GAAaI,kBAAY,YAAY;AACzC,IAAA,IAAI,CAAC,WAAA,IAAe,CAAC,KAAA,EAAO;AAC5B,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,IAAI,GAAA,CAAIC,sBAAc,KAAA,CAAM,KAAK,GAAG,WAAW,CAAA;AAC3D,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AAC3C,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAC7E,MAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA,IACf,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAA,YAAe,QAAQ,GAAA,GAAM,IAAI,MAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,IAC9D,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,CAAA,EAAG,CAAC,WAAA,EAAa,KAAK,CAAC,CAAA;AAEvB,EAAAJ,gBAAU,MAAM;AACd,IAAA,IAAI,WAAW,OAAA,EAAS;AACxB,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,IAAA,UAAA,EAAW;AAAA,EACb,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,MAAM,OAAA,GAAUG,kBAAY,YAAY;AACtC,IAAA,UAAA,CAAW,OAAA,GAAU,KAAA;AACrB,IAAA,MAAM,UAAA,EAAW;AAAA,EACnB,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,OAAA,EAAQ;AAC5C;AC9CO,SAAS,OAAA,GAAqB;AACnC,EAAA,MAAM,EAAE,eAAA,EAAiB,SAAA,EAAU,GAAIL,gBAAAA,EAAS;AAChD,EAAA,OAAO,EAAE,iBAAiB,SAAA,EAAU;AACtC;ACPO,SAAS,SAAA,GAAoD;AAClE,EAAA,MAAM,EAAE,MAAA,EAAO,GAAIA,gBAAAA,EAAS;AAC5B,EAAA,OAAO,MAAA;AACT;ACHO,SAAS,UAAA,GAAgE;AAC9E,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAIQ,gBAAAA,CAAW,eAAe,CAAA;AAC9C,EAAA,OAAO,OAAA;AACT;ACNA,IAAM,kBAAA,GAA+C;AAAA,EACnD,KAAA,EAAO,CAAA;AAAA,EACP,IAAA,EAAM,CAAA;AAAA,EACN,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO;AACT,CAAA;AA6BO,IAAM,uBAAN,MAA2B;AAAA,EAOhC,WAAA,CACmB,MAAA,EACA,cAAA,EACA,iBAAA,EAMjB,MAAA,EACA;AATiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AACA,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AATnB,IAAA,IAAA,CAAQ,SAAqB,EAAC;AAC9B,IAAA,IAAA,CAAQ,UAAA,GAAoD,IAAA;AAgB1D,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,IAAA;AAClC,IAAA,IAAA,CAAK,QAAA,GAAW,kBAAA,CAAmB,MAAA,EAAQ,KAAA,IAAS,OAAO,CAAA;AAC3D,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,EAAA;AAEtC,IAAA,MAAM,QAAA,GAAW,QAAQ,aAAA,IAAiB,GAAA;AAC1C,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,QAAA,GAAW,CAAA,EAAG;AAChC,MAAA,IAAA,CAAK,aAAa,WAAA,CAAY,MAAM,IAAA,CAAK,KAAA,IAAS,QAAQ,CAAA;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,GAAA,CAAI,KAAA,EAAiB,OAAA,EAAiB,OAAA,EAAyC;AAC7E,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACnB,IAAA,IAAI,kBAAA,CAAmB,KAAK,CAAA,GAAI,IAAA,CAAK,QAAA,EAAU;AAE/C,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,MACf,KAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA,EAAU,KAAK,iBAAA,CAAkB,QAAA;AAAA,MACjC,OAAA,EAAS;AAAA,QACP,GAAG,OAAA;AAAA,QACH,GAAI,KAAK,iBAAA,CAAkB,KAAA,IAAS,EAAE,KAAA,EAAO,IAAA,CAAK,kBAAkB,KAAA,EAAM;AAAA,QAC1E,GAAI,KAAK,iBAAA,CAAkB,MAAA,IAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,kBAAkB,MAAA;AAAO,OAC/E;AAAA,MACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,MAAA,EAAQ,UAAA;AAAA,MACR,WAAA,EAAa,KAAK,iBAAA,CAAkB;AAAA,KACrC,CAAA;AAED,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,IAAA,CAAK,SAAA,EAAW;AACxC,MAAA,IAAA,CAAK,KAAA,EAAM;AAAA,IACb;AAAA,EACF;AAAA,EAEA,KAAA,CAAM,SAAiB,OAAA,EAAyC;AAC9D,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAAA,EACpC;AAAA,EAEA,IAAA,CAAK,SAAiB,OAAA,EAAyC;AAC7D,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,EACnC;AAAA,EAEA,IAAA,CAAK,SAAiB,OAAA,EAAyC;AAC7D,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,EACnC;AAAA,EAEA,KAAA,CAAM,SAAiB,OAAA,EAAyC;AAC9D,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAE9B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA;AAEpC,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,cAAA,EAAe;AACxC,MAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,MAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAGF,sBAAc,UAAU,CAAA,CAAA;AACrD,MAAA,MAAM,MAAM,GAAA,EAAK;AAAA,QACf,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,UAC9B,cAAA,EAAgB;AAAA,SAClB;AAAA,QACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,SAAS;AAAA,OACvC,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB;AACA,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACb;AACF,CAAA;;;AC3GO,SAAS,UAAU,MAAA,EAAgD;AACxE,EAAA,MAAM;AAAA,IACJ,WAAA;AAAA,IACA,cAAA;AAAA,IACA,OAAA,EAAS,UAAA;AAAA,IACT;AAAA,GACF,GAAIE,iBAAW,eAAe,CAAA;AAE9B,EAAA,MAAM,SAAA,GAAYP,aAAoC,IAAI,CAAA;AAG1D,EAAA,MAAM,YAAA,GAAeG,aAAAA;AAAA,IACnB,OAAO;AAAA,MACL,OAAA,EAAS,MAAA,EAAQ,OAAA,IAAW,YAAA,EAAc,OAAA,IAAW,IAAA;AAAA,MACrD,KAAA,EAAO,MAAA,EAAQ,KAAA,IAAS,YAAA,EAAc,KAAA,IAAS,OAAA;AAAA,MAC/C,WAAW,MAAA,EAAQ,SAAA;AAAA,MACnB,eAAe,MAAA,EAAQ;AAAA,KACzB,CAAA;AAAA,IACA,CAAC,QAAQ,YAAY;AAAA,GACvB;AAGA,EAAAF,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,WAAA,EAAa;AAElB,IAAA,SAAA,CAAU,SAAS,OAAA,EAAQ;AAC3B,IAAA,SAAA,CAAU,UAAU,IAAI,oBAAA;AAAA,MACtB,WAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,QACE,QAAA,EAAU,YAAY,MAAA,EAAQ,EAAA;AAAA,QAC9B,KAAA,EAAO,YAAY,GAAA,EAAK,EAAA;AAAA,QACxB,MAAA,EAAQ,YAAY,IAAA,EAAM;AAAA,OAC5B;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,CAAU,SAAS,OAAA,EAAQ;AAC3B,MAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AAAA,IACtB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,WAAA,EAAa,cAAA,EAAgB,YAAY,MAAA,EAAQ,EAAA,EAAI,UAAA,EAAY,GAAA,EAAK,EAAA,EAAI,UAAA,EAAY,IAAA,EAAM,EAAA,EAAI,YAAY,CAAC,CAAA;AAEjH,EAAA,MAAM,GAAA,GAAMG,iBAAAA;AAAA,IACV,CAAC,KAAA,EAAiB,OAAA,EAAiB,OAAA,KAAsC;AACvE,MAAA,SAAA,CAAU,OAAA,EAAS,GAAA,CAAI,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAAA,IAChD,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,KAAA,GAAQA,iBAAAA;AAAA,IACZ,CAAC,SAAiB,OAAA,KAAsC;AACtD,MAAA,SAAA,CAAU,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA;AAAA,IAC3C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,IAAA,GAAOA,iBAAAA;AAAA,IACX,CAAC,SAAiB,OAAA,KAAsC;AACtD,MAAA,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,IAAA,GAAOA,iBAAAA;AAAA,IACX,CAAC,SAAiB,OAAA,KAAsC;AACtD,MAAA,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,KAAA,GAAQA,iBAAAA;AAAA,IACZ,CAAC,SAAiB,OAAA,KAAsC;AACtD,MAAA,SAAA,CAAU,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA;AAAA,IAC3C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,KAAA,GAAQA,kBAAY,YAAY;AACpC,IAAA,MAAM,SAAA,CAAU,SAAS,KAAA,EAAM;AAAA,EACjC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAOD,aAAAA;AAAA,IACL,OAAO,EAAE,GAAA,EAAK,OAAO,IAAA,EAAM,IAAA,EAAM,OAAO,KAAA,EAAM,CAAA;AAAA,IAC9C,CAAC,GAAA,EAAK,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,OAAO,KAAK;AAAA,GACvC;AACF;ACjGO,SAAS,YAAA,GAAmC;AACjD,EAAA,MAAM,EAAE,cAAA,EAAgB,WAAA,EAAa,OAAA,EAAS,UAAA,KAAe,WAAA,EAAY;AAEzE,EAAA,MAAM,KAAA,GAAQC,iBAAAA,CAAY,OAAO,MAAA,KAAgD;AAC/E,IAAA,IAAI,CAAC,WAAA,IAAe,CAAC,UAAA,EAAY;AAEjC,IAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,EAAe;AACnC,IAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,IAAA,MAAM,YAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,MAAA,GAAS,CAAC,MAAM,CAAA;AAE1D,IAAA,MAAM,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA,gBAAA,CAAA,EAAoB;AAAA,MAC5C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,QAC9B,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,QAAA,EAAU,UAAA;AAAA,QACV,GAAI,OAAA,IAAW,EAAE,KAAA,EAAO,OAAA,EAAQ;AAAA,QAChC,MAAA,EAAQ;AAAA,OACT;AAAA,KACF,CAAA;AAAA,EACH,GAAG,CAAC,cAAA,EAAgB,WAAA,EAAa,OAAA,EAAS,UAAU,CAAC,CAAA;AAErD,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;ACTO,SAAS,OAAA,GAAyB;AACvC,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,KAAA,EAAM,GAAIG,iBAAW,eAAe,CAAA;AAEhE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAS,IAAA,IAAQ,IAAA;AAAA,IACvB,MAAA,EAAQ,SAAS,MAAA,IAAU,IAAA;AAAA,IAC3B,YAAA,EAAc,SAAS,YAAA,IAAgB,IAAA;AAAA,IACvC,GAAA,EAAK,SAAS,GAAA,IAAO,IAAA;AAAA,IACrB,WAAA,EAAa,OAAA,EAAS,WAAA,IAAe,EAAC;AAAA,IACtC,KAAA,EAAO,OAAA,EAAS,KAAA,IAAS,EAAC;AAAA,IAC1B,MAAA,EAAQ,OAAA,EAAS,MAAA,IAAU,EAAC;AAAA,IAC5B,SAAA;AAAA,IACA;AAAA,GACF;AACF;AC9BO,SAAS,SAAA,GAA6B;AAC3C,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,KAAA,EAAM,GAAIA,iBAAW,eAAe,CAAA;AAChE,EAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAAU,EAAC;AAEnC,EAAA,MAAM,SAAA,GAAYH,iBAAAA;AAAA,IAChB,CAAC,QAAgB,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,GAAG,CAAA;AAAA,IACjD,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,WAAA,GAAcA,iBAAAA;AAAA,IAClB,CAAC,IAAA,KAAmB,MAAA,CAAO,IAAA,CAAK,CAAC,MAAM,IAAA,CAAK,QAAA,CAAS,CAAA,CAAE,GAAG,CAAC,CAAA;AAAA,IAC3D,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,WAAA,EAAa,WAAW,KAAA,EAAM;AAC5D;ACHO,SAAS,mBAAmB,UAAA,EAA8C;AAC/E,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,WAAA,EAAY;AACvC,EAAA,MAAM,iBAAA,GAAoBJ,aAAO,cAAc,CAAA;AAC/C,EAAA,iBAAA,CAAkB,OAAA,GAAU,cAAA;AAE5B,EAAAC,gBAAU,MAAM;AACd,IAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,YAAA,CAAa,OAAA,CAAQ,GAAA;AAAA,MACpD,OAAO,MAAA,KAAoC;AACzC,QAAA,IAAI;AACF,UAAA,MAAM,KAAA,GAAQ,MAAM,iBAAA,CAAkB,OAAA,EAAQ;AAC9C,UAAA,IAAI,KAAA,EAAO;AACT,YAAA,MAAM,OAAA,GAAW,MAAA,CAAO,OAAA,IAAW,EAAC;AACpC,YAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA;AAC1C,YAAA,MAAA,CAAO,OAAA,GAAU,OAAA;AAAA,UACnB;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAGR;AACA,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,KACF;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,YAAA,CAAa,OAAA,CAAQ,KAAA,CAAM,aAAa,CAAA;AAAA,IACrD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AACjB;ACfO,SAAS,WAAA,GAAiC;AAC/C,EAAA,MAAM,EAAE,cAAA,EAAgB,OAAA,EAAS,WAAA,EAAa,UAAA,KAAe,WAAA,EAAY;AACzE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIC,eAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AAErD,EAAA,MAAM,aAAA,GAAgBE,iBAAAA,CAAY,OAAO,MAAA,KAA2B;AAClE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,QAAA,CAAS,IAAI,KAAA,CAAM,6BAA6B,CAAC,CAAA;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,EAAe;AACnC,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAGvD,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,OAAA,CAAQ,eAAA,EAAiB,EAAE,CAAA;AAEvD,MAAA,MAAM,YAAA,GAAe,SAAS,GAAA,EAAK,YAAA;AACnC,MAAA,MAAM,MAAA,GAAS,SAAS,IAAA,EAAM,EAAA;AAE9B,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI,IAAA;AAEJ,MAAA,IAAI,YAAA,KAAiB,YAAY,UAAA,EAAY;AAC3C,QAAA,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,SAAA,EAAY,kBAAA,CAAmB,UAAU,CAAC,CAAA,uBAAA,CAAA;AAC1D,QAAA,IAAA,GAAO;AAAA,UACL,KAAA,EAAO,SAAS,GAAA,EAAK,EAAA;AAAA,UACrB,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,OAAO,MAAA,CAAO;AAAA,SAChB;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,wBAAwB,CAAA;AACrD,QAAA,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,OAAA,EAAU,kBAAA,CAAmB,MAAM,CAAC,CAAA,uBAAA,CAAA;AACpD,QAAA,IAAA,GAAO;AAAA,UACL,KAAA,EAAO,SAAS,GAAA,EAAK,EAAA;AAAA,UACrB,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,OAAO,MAAA,CAAO,KAAA;AAAA,UACd,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,WAAW,MAAA,CAAO;AAAA,SACpB;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAChC,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,SAChC;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,OAC1B,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACtD,QAAA,MAAM,IAAI,KAAA;AAAA,UACP,OAAA,CAAmC,OAAA,IAAW,CAAA,iBAAA,EAAoB,QAAA,CAAS,MAAM,CAAA;AAAA,SACpF;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,MAAA,IAAI,KAAK,WAAA,EAAa;AACpB,QAAA,MAAA,CAAO,QAAA,CAAS,OAAO,IAAA,CAAK,WAAA;AAC5B,QAAA;AAAA,MACF;AAAA,IAEF,SAAS,GAAA,EAAc;AACrB,MAAA,MAAM,UAAA,GAAa,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACrE,MAAA,QAAA,CAAS,UAAU,CAAA;AAAA,IACrB,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,cAAA,EAAgB,OAAA,EAAS,WAAA,EAAa,UAAU,CAAC,CAAA;AAErD,EAAA,OAAO,EAAE,aAAA,EAAe,SAAA,EAAW,KAAA,EAAM;AAC3C;AC5FO,SAAS,gBAAA,GAA2C;AACzD,EAAA,MAAM,EAAE,cAAA,EAAgB,OAAA,EAAS,WAAA,EAAa,UAAA,KAAe,WAAA,EAAY;AACzE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIF,eAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AAErD,EAAA,MAAM,UAAA,GAAaE,iBAAAA,CAAY,OAAO,MAAA,KAAiC;AACrE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,QAAA,CAAS,IAAI,KAAA,CAAM,6BAA6B,CAAC,CAAA;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,EAAe;AACnC,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAGvD,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,OAAA,CAAQ,eAAA,EAAiB,EAAE,CAAA;AAEvD,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA,IAAa,CAAA,EAAG,MAAA,CAAO,SAAS,MAAM,CAAA,QAAA,CAAA;AAChE,MAAA,MAAM,YAAA,GAAe,SAAS,GAAA,EAAK,YAAA;AACnC,MAAA,MAAM,MAAA,GAAS,SAAS,IAAA,EAAM,EAAA;AAE9B,MAAA,IAAI,GAAA;AAEJ,MAAA,IAAI,YAAA,KAAiB,YAAY,UAAA,EAAY;AAC3C,QAAA,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,SAAA,EAAY,kBAAA,CAAmB,UAAU,CAAC,CAAA,eAAA,CAAA;AAAA,MAC5D,CAAA,MAAO;AAEL,QAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,wBAAwB,CAAA;AACrD,QAAA,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,OAAA,EAAU,kBAAA,CAAmB,MAAM,CAAC,CAAA,eAAA,CAAA;AAAA,MACtD;AAEA,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAChC,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,SAChC;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,WAAW;AAAA,OACnC,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACtD,QAAA,MAAM,IAAI,KAAA;AAAA,UACP,OAAA,CAAmC,OAAA,IAAW,CAAA,uBAAA,EAA0B,QAAA,CAAS,MAAM,CAAA;AAAA,SAC1F;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,GAAA;AAEzC,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAA,CAAO,SAAS,IAAA,GAAO,SAAA;AAAA,MACzB;AAAA,IACF,SAAS,GAAA,EAAc;AACrB,MAAA,MAAM,UAAA,GAAa,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACrE,MAAA,QAAA,CAAS,UAAU,CAAA;AAAA,IACrB,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,cAAA,EAAgB,OAAA,EAAS,WAAA,EAAa,UAAU,CAAC,CAAA;AAErD,EAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,KAAA,EAAM;AACxC;AC5FO,SAAS,kBAAkB,EAAE,UAAA,EAAY,QAAA,EAAU,QAAA,GAAW,MAAK,EAA2B;AACnG,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,cAAA,EAAe;AAEzC,EAAA,IAAI,CAAC,aAAA,CAAc,UAAU,CAAA,EAAG;AAC9B,IAAA,uBAAOP,cAAAA,CAAAC,mBAAAA,EAAA,EAAG,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAAA,CAAAC,mBAAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AACrB;ACRO,SAAS,eAAe,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,GAAW,MAAK,EAAwB;AACvF,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,WAAA,EAAY;AAElC,EAAA,IAAI,CAAC,SAAA,CAAU,IAAI,CAAA,EAAG;AACpB,IAAA,uBAAOD,cAAAA,CAAAC,mBAAAA,EAAA,EAAG,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAAA,CAAAC,mBAAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AACrB","file":"index.js","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useContext, useCallback } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkGroupContext } from '@habeetat/sdk-core';\n\nexport interface UseGroupsReturn {\n /** Groups the current user belongs to in the active tenant */\n groups: SdkGroupContext[];\n /** True if the user belongs to the group with the given key */\n isInGroup: (key: string) => boolean;\n /** True if the user belongs to any of the given group keys */\n hasAnyGroup: (keys: string[]) => boolean;\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook exposing the current user's groups, sourced from the already-loaded\n * SDK context (no extra network request) — twin of `usePermissions`.\n *\n * @example\n * ```tsx\n * const { groups, isInGroup } = useGroups();\n * if (isInGroup('finance')) { ... }\n * ```\n */\nexport function useGroups(): UseGroupsReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n const groups = context?.groups ?? [];\n\n const isInGroup = useCallback(\n (key: string) => groups.some((g) => g.key === key),\n [groups],\n );\n\n const hasAnyGroup = useCallback(\n (keys: string[]) => groups.some((g) => keys.includes(g.key)),\n [groups],\n );\n\n return { groups, isInGroup, hasAnyGroup, isLoading, error };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n return;\n }\n // If activated (free plan), no redirect needed — caller can handle\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { startCheckout, isLoading, error };\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface BillingPortalParams {\n /**\n * URL to return to after the user exits the Stripe Customer Portal.\n * Defaults to `window.location.origin + '/profile'`.\n */\n returnUrl?: string;\n}\n\nexport interface UseBillingPortalReturn {\n /** Open the Stripe Customer Portal. Redirects the browser on success. */\n openPortal: (params?: BillingPortalParams) => Promise<void>;\n /** Whether a portal session creation is in progress */\n isLoading: boolean;\n /** Error from the last portal attempt */\n error: Error | null;\n}\n\n/**\n * Hook for opening the Stripe Customer Portal via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `POST /users/:userId/billing/portal`\n * - TENANT scope (B2B): calls `POST /tenants/:tenantSlug/billing/portal`\n *\n * On success, redirects the browser to the Stripe Customer Portal URL.\n *\n * @example\n * ```tsx\n * const { openPortal, isLoading, error } = useBillingPortal();\n *\n * const handleManageBilling = () => {\n * openPortal({ returnUrl: `${window.location.origin}/profile` });\n * };\n * ```\n */\nexport function useBillingPortal(): UseBillingPortalReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const openPortal = useCallback(async (params?: BillingPortalParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const returnUrl = params?.returnUrl ?? `${window.location.origin}/profile`;\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/billing/portal`;\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/billing/portal`;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ returnUrl }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Billing portal failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { portalUrl?: string; url?: string };\n const portalUrl = data.portalUrl ?? data.url;\n\n if (portalUrl) {\n window.location.href = portalUrl;\n }\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { openPortal, isLoading, error };\n}\n","import { type ReactNode } from 'react';\nimport { usePermissions } from '../hooks/usePermissions';\n\ninterface RequirePermissionProps {\n permission: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if user has the required permission\n */\nexport function RequirePermission({ permission, children, fallback = null }: RequirePermissionProps) {\n const { hasPermission } = usePermissions();\n \n if (!hasPermission(permission)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n","import { type ReactNode } from 'react';\nimport { useFeatures } from '../hooks/useFeatures';\n\ninterface RequireFeatureProps {\n flag: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if the feature flag is enabled\n */\nexport function RequireFeature({ flag, children, fallback = null }: RequireFeatureProps) {\n const { isEnabled } = useFeatures();\n \n if (!isEnabled(flag)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -732,6 +732,19 @@ function useUser() {
|
|
|
732
732
|
error
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
|
+
function useGroups() {
|
|
736
|
+
const { context, isLoading, error } = useContext(HabeetatContext);
|
|
737
|
+
const groups = context?.groups ?? [];
|
|
738
|
+
const isInGroup = useCallback(
|
|
739
|
+
(key) => groups.some((g) => g.key === key),
|
|
740
|
+
[groups]
|
|
741
|
+
);
|
|
742
|
+
const hasAnyGroup = useCallback(
|
|
743
|
+
(keys) => groups.some((g) => keys.includes(g.key)),
|
|
744
|
+
[groups]
|
|
745
|
+
);
|
|
746
|
+
return { groups, isInGroup, hasAnyGroup, isLoading, error };
|
|
747
|
+
}
|
|
735
748
|
function useHttpInterceptor(httpClient) {
|
|
736
749
|
const { getAccessToken } = useHabeetat();
|
|
737
750
|
const getAccessTokenRef = useRef(getAccessToken);
|
|
@@ -891,6 +904,6 @@ function RequireFeature({ flag, children, fallback = null }) {
|
|
|
891
904
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
892
905
|
}
|
|
893
906
|
|
|
894
|
-
export { HabeetatContext, HabeetatProvider, RequireFeature, RequirePermission, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
|
907
|
+
export { HabeetatContext, HabeetatProvider, RequireFeature, RequirePermission, useAnalytics, useAuth, useBillingPortal, useCheckout, useFeatures, useGroups, useHabeetat, useHttpInterceptor, useLogger, usePermissions, usePlans, useSignIn, useSignOut, useSubscription, useUser, useUserSubscription };
|
|
895
908
|
//# sourceMappingURL=index.mjs.map
|
|
896
909
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["useCallback","useState","useRef","SDK_ENDPOINTS","useEffect","useLogto","useContext","useMemo","jsx","Fragment"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n return;\n }\n // If activated (free plan), no redirect needed — caller can handle\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { startCheckout, isLoading, error };\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface BillingPortalParams {\n /**\n * URL to return to after the user exits the Stripe Customer Portal.\n * Defaults to `window.location.origin + '/profile'`.\n */\n returnUrl?: string;\n}\n\nexport interface UseBillingPortalReturn {\n /** Open the Stripe Customer Portal. Redirects the browser on success. */\n openPortal: (params?: BillingPortalParams) => Promise<void>;\n /** Whether a portal session creation is in progress */\n isLoading: boolean;\n /** Error from the last portal attempt */\n error: Error | null;\n}\n\n/**\n * Hook for opening the Stripe Customer Portal via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `POST /users/:userId/billing/portal`\n * - TENANT scope (B2B): calls `POST /tenants/:tenantSlug/billing/portal`\n *\n * On success, redirects the browser to the Stripe Customer Portal URL.\n *\n * @example\n * ```tsx\n * const { openPortal, isLoading, error } = useBillingPortal();\n *\n * const handleManageBilling = () => {\n * openPortal({ returnUrl: `${window.location.origin}/profile` });\n * };\n * ```\n */\nexport function useBillingPortal(): UseBillingPortalReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const openPortal = useCallback(async (params?: BillingPortalParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const returnUrl = params?.returnUrl ?? `${window.location.origin}/profile`;\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/billing/portal`;\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/billing/portal`;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ returnUrl }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Billing portal failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { portalUrl?: string; url?: string };\n const portalUrl = data.portalUrl ?? data.url;\n\n if (portalUrl) {\n window.location.href = portalUrl;\n }\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { openPortal, isLoading, error };\n}\n","import { type ReactNode } from 'react';\nimport { usePermissions } from '../hooks/usePermissions';\n\ninterface RequirePermissionProps {\n permission: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if user has the required permission\n */\nexport function RequirePermission({ permission, children, fallback = null }: RequirePermissionProps) {\n const { hasPermission } = usePermissions();\n \n if (!hasPermission(permission)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n","import { type ReactNode } from 'react';\nimport { useFeatures } from '../hooks/useFeatures';\n\ninterface RequireFeatureProps {\n flag: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if the feature flag is enabled\n */\nexport function RequireFeature({ flag, children, fallback = null }: RequireFeatureProps) {\n const { isEnabled } = useFeatures();\n \n if (!isEnabled(flag)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useGroups.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["useCallback","useState","useRef","SDK_ENDPOINTS","useEffect","useLogto","useContext","useMemo","jsx","Fragment"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useContext, useCallback } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkGroupContext } from '@habeetat/sdk-core';\n\nexport interface UseGroupsReturn {\n /** Groups the current user belongs to in the active tenant */\n groups: SdkGroupContext[];\n /** True if the user belongs to the group with the given key */\n isInGroup: (key: string) => boolean;\n /** True if the user belongs to any of the given group keys */\n hasAnyGroup: (keys: string[]) => boolean;\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook exposing the current user's groups, sourced from the already-loaded\n * SDK context (no extra network request) — twin of `usePermissions`.\n *\n * @example\n * ```tsx\n * const { groups, isInGroup } = useGroups();\n * if (isInGroup('finance')) { ... }\n * ```\n */\nexport function useGroups(): UseGroupsReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n const groups = context?.groups ?? [];\n\n const isInGroup = useCallback(\n (key: string) => groups.some((g) => g.key === key),\n [groups],\n );\n\n const hasAnyGroup = useCallback(\n (keys: string[]) => groups.some((g) => keys.includes(g.key)),\n [groups],\n );\n\n return { groups, isInGroup, hasAnyGroup, isLoading, error };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n return;\n }\n // If activated (free plan), no redirect needed — caller can handle\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { startCheckout, isLoading, error };\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface BillingPortalParams {\n /**\n * URL to return to after the user exits the Stripe Customer Portal.\n * Defaults to `window.location.origin + '/profile'`.\n */\n returnUrl?: string;\n}\n\nexport interface UseBillingPortalReturn {\n /** Open the Stripe Customer Portal. Redirects the browser on success. */\n openPortal: (params?: BillingPortalParams) => Promise<void>;\n /** Whether a portal session creation is in progress */\n isLoading: boolean;\n /** Error from the last portal attempt */\n error: Error | null;\n}\n\n/**\n * Hook for opening the Stripe Customer Portal via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `POST /users/:userId/billing/portal`\n * - TENANT scope (B2B): calls `POST /tenants/:tenantSlug/billing/portal`\n *\n * On success, redirects the browser to the Stripe Customer Portal URL.\n *\n * @example\n * ```tsx\n * const { openPortal, isLoading, error } = useBillingPortal();\n *\n * const handleManageBilling = () => {\n * openPortal({ returnUrl: `${window.location.origin}/profile` });\n * };\n * ```\n */\nexport function useBillingPortal(): UseBillingPortalReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const openPortal = useCallback(async (params?: BillingPortalParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const returnUrl = params?.returnUrl ?? `${window.location.origin}/profile`;\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/billing/portal`;\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/billing/portal`;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ returnUrl }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Billing portal failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { portalUrl?: string; url?: string };\n const portalUrl = data.portalUrl ?? data.url;\n\n if (portalUrl) {\n window.location.href = portalUrl;\n }\n } catch (err: unknown) {\n const finalError = err instanceof Error ? err : new Error(String(err));\n setError(finalError);\n } finally {\n setIsLoading(false);\n }\n }, [getAccessToken, context, platformUrl, tenantSlug]);\n\n return { openPortal, isLoading, error };\n}\n","import { type ReactNode } from 'react';\nimport { usePermissions } from '../hooks/usePermissions';\n\ninterface RequirePermissionProps {\n permission: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if user has the required permission\n */\nexport function RequirePermission({ permission, children, fallback = null }: RequirePermissionProps) {\n const { hasPermission } = usePermissions();\n \n if (!hasPermission(permission)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n","import { type ReactNode } from 'react';\nimport { useFeatures } from '../hooks/useFeatures';\n\ninterface RequireFeatureProps {\n flag: string;\n children: ReactNode;\n fallback?: ReactNode;\n}\n\n/**\n * Component that renders children only if the feature flag is enabled\n */\nexport function RequireFeature({ flag, children, fallback = null }: RequireFeatureProps) {\n const { isEnabled } = useFeatures();\n \n if (!isEnabled(flag)) {\n return <>{fallback}</>;\n }\n \n return <>{children}</>;\n}\n"]}
|
package/package.json
CHANGED