@habeetat/sdk-react 0.2.1-dev.20260618083959.3cb5192 → 0.2.1-dev.20260619123920.2f9dafc

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 CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as _habeetat_sdk_core from '@habeetat/sdk-core';
3
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';
4
+ export { BillingScope, PlatformConfig, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkGroupContext, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext, fetchPlatformConfig } from '@habeetat/sdk-core';
5
5
  import * as react from 'react';
6
6
  import { ReactNode } from 'react';
7
7
 
8
8
  interface LogtoConfig {
9
- /** Logto endpoint (e.g. https://iam.yourdomain.com) */
10
- endpoint: string;
11
- /** OIDC application ID registered in Logto */
9
+ /** Logto endpoint (e.g. https://iam.yourdomain.com). Optional when
10
+ * `configDiscoveryUrl` is set — it is then discovered at runtime. */
11
+ endpoint?: string;
12
+ /** OIDC application ID registered in Logto (always required — app-specific). */
12
13
  appId: string;
13
14
  /** API resources to request access tokens for */
14
15
  resources?: string[];
@@ -18,8 +19,17 @@ interface LogtoConfig {
18
19
  interface HabeetatProviderProps {
19
20
  /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */
20
21
  logto: LogtoConfig;
21
- /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */
22
- platformUrl: string;
22
+ /** Platform SDK base URL (e.g. https://api.yourdomain.com). Optional when
23
+ * `configDiscoveryUrl` is set — it is then discovered at runtime (`apiBase`). */
24
+ platformUrl?: string;
25
+ /**
26
+ * If set, the provider fetches `/.well-known/habeetat` from this URL (the
27
+ * platform's api base or apex domain) at startup and self-configures any of
28
+ * `logto.endpoint` / `logto.resources` / `platformUrl` not explicitly provided.
29
+ * Lets a vendor SPA drop all build-time `VITE_*` platform URLs — only its own
30
+ * `logto.appId` (+ optional `tenantSlug`) remains app-specific.
31
+ */
32
+ configDiscoveryUrl?: string;
23
33
  /** API resource identifier for access-token requests; defaults to platformUrl */
24
34
  logtoResource?: string;
25
35
  /** App slug registered in Habeetat */
@@ -51,29 +61,31 @@ interface HabeetatProviderProps {
51
61
  /**
52
62
  * HabeetatProvider — single provider for Habeetat auth + SDK context.
53
63
  *
54
- * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer
55
- * need to install or import that package in your application.
64
+ * Either supply the platform URLs explicitly (`logto.endpoint` + `platformUrl`),
65
+ * or set `configDiscoveryUrl` to the platform's api base / apex domain and the
66
+ * provider fetches `/.well-known/habeetat` at startup to self-configure them —
67
+ * so a vendor SPA needs no build-time `VITE_*` platform URLs (only its own
68
+ * `logto.appId` remains app-specific).
56
69
  *
57
- * @example
70
+ * @example Explicit
58
71
  * ```tsx
59
- * import { HabeetatProvider } from '@habeetat/sdk-react';
72
+ * <HabeetatProvider
73
+ * logto={{ endpoint: 'https://iam.example.com', appId: 'abc123' }}
74
+ * platformUrl="https://api.example.com"
75
+ * tenantSlug="acme"
76
+ * ><App /></HabeetatProvider>
77
+ * ```
60
78
  *
79
+ * @example Self-configuring
80
+ * ```tsx
61
81
  * <HabeetatProvider
62
- * logto={{
63
- * endpoint: 'https://iam.example.com',
64
- * appId: 'abc123',
65
- * resources: ['https://api.example.com/api'],
66
- * }}
67
- * platformUrl="https://api.example.com/sdk/v1"
82
+ * logto={{ appId: 'abc123' }}
83
+ * configDiscoveryUrl="https://api.acme.example.com"
68
84
  * tenantSlug="acme"
69
- * autoSignIn
70
- * callbackPath="/callback"
71
- * >
72
- * <App />
73
- * </HabeetatProvider>
85
+ * ><App /></HabeetatProvider>
74
86
  * ```
75
87
  */
76
- declare function HabeetatProvider({ logto, platformUrl, logtoResource, appId, appName, tenantSlug, autoSignIn, callbackPath, loadingFallback, logging, postLogoutRedirectPath, children, }: HabeetatProviderProps): react_jsx_runtime.JSX.Element;
88
+ declare function HabeetatProvider(props: HabeetatProviderProps): react_jsx_runtime.JSX.Element;
77
89
 
78
90
  /**
79
91
  * Habeetat SDK state
package/dist/index.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as _habeetat_sdk_core from '@habeetat/sdk-core';
3
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';
4
+ export { BillingScope, PlatformConfig, PlatformUser, SdkAvailablePlan, SdkContext, SdkFeaturesState, SdkGroupContext, SdkPlan, SdkPlanBillingOption, SdkPlanDisplayFeature, SdkSubscription, SdkTenantContext, SdkUserContext, fetchPlatformConfig } from '@habeetat/sdk-core';
5
5
  import * as react from 'react';
6
6
  import { ReactNode } from 'react';
7
7
 
8
8
  interface LogtoConfig {
9
- /** Logto endpoint (e.g. https://iam.yourdomain.com) */
10
- endpoint: string;
11
- /** OIDC application ID registered in Logto */
9
+ /** Logto endpoint (e.g. https://iam.yourdomain.com). Optional when
10
+ * `configDiscoveryUrl` is set — it is then discovered at runtime. */
11
+ endpoint?: string;
12
+ /** OIDC application ID registered in Logto (always required — app-specific). */
12
13
  appId: string;
13
14
  /** API resources to request access tokens for */
14
15
  resources?: string[];
@@ -18,8 +19,17 @@ interface LogtoConfig {
18
19
  interface HabeetatProviderProps {
19
20
  /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */
20
21
  logto: LogtoConfig;
21
- /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */
22
- platformUrl: string;
22
+ /** Platform SDK base URL (e.g. https://api.yourdomain.com). Optional when
23
+ * `configDiscoveryUrl` is set — it is then discovered at runtime (`apiBase`). */
24
+ platformUrl?: string;
25
+ /**
26
+ * If set, the provider fetches `/.well-known/habeetat` from this URL (the
27
+ * platform's api base or apex domain) at startup and self-configures any of
28
+ * `logto.endpoint` / `logto.resources` / `platformUrl` not explicitly provided.
29
+ * Lets a vendor SPA drop all build-time `VITE_*` platform URLs — only its own
30
+ * `logto.appId` (+ optional `tenantSlug`) remains app-specific.
31
+ */
32
+ configDiscoveryUrl?: string;
23
33
  /** API resource identifier for access-token requests; defaults to platformUrl */
24
34
  logtoResource?: string;
25
35
  /** App slug registered in Habeetat */
@@ -51,29 +61,31 @@ interface HabeetatProviderProps {
51
61
  /**
52
62
  * HabeetatProvider — single provider for Habeetat auth + SDK context.
53
63
  *
54
- * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer
55
- * need to install or import that package in your application.
64
+ * Either supply the platform URLs explicitly (`logto.endpoint` + `platformUrl`),
65
+ * or set `configDiscoveryUrl` to the platform's api base / apex domain and the
66
+ * provider fetches `/.well-known/habeetat` at startup to self-configure them —
67
+ * so a vendor SPA needs no build-time `VITE_*` platform URLs (only its own
68
+ * `logto.appId` remains app-specific).
56
69
  *
57
- * @example
70
+ * @example Explicit
58
71
  * ```tsx
59
- * import { HabeetatProvider } from '@habeetat/sdk-react';
72
+ * <HabeetatProvider
73
+ * logto={{ endpoint: 'https://iam.example.com', appId: 'abc123' }}
74
+ * platformUrl="https://api.example.com"
75
+ * tenantSlug="acme"
76
+ * ><App /></HabeetatProvider>
77
+ * ```
60
78
  *
79
+ * @example Self-configuring
80
+ * ```tsx
61
81
  * <HabeetatProvider
62
- * logto={{
63
- * endpoint: 'https://iam.example.com',
64
- * appId: 'abc123',
65
- * resources: ['https://api.example.com/api'],
66
- * }}
67
- * platformUrl="https://api.example.com/sdk/v1"
82
+ * logto={{ appId: 'abc123' }}
83
+ * configDiscoveryUrl="https://api.acme.example.com"
68
84
  * tenantSlug="acme"
69
- * autoSignIn
70
- * callbackPath="/callback"
71
- * >
72
- * <App />
73
- * </HabeetatProvider>
85
+ * ><App /></HabeetatProvider>
74
86
  * ```
75
87
  */
76
- declare function HabeetatProvider({ logto, platformUrl, logtoResource, appId, appName, tenantSlug, autoSignIn, callbackPath, loadingFallback, logging, postLogoutRedirectPath, children, }: HabeetatProviderProps): react_jsx_runtime.JSX.Element;
88
+ declare function HabeetatProvider(props: HabeetatProviderProps): react_jsx_runtime.JSX.Element;
77
89
 
78
90
  /**
79
91
  * Habeetat SDK state
package/dist/index.js CHANGED
@@ -335,7 +335,7 @@ function HabeetatInner({
335
335
  }
336
336
  return /* @__PURE__ */ jsxRuntime.jsx(HabeetatContext.Provider, { value: contextValue, children });
337
337
  }
338
- function HabeetatProvider({
338
+ function HabeetatProviderResolved({
339
339
  logto,
340
340
  platformUrl,
341
341
  logtoResource,
@@ -373,6 +373,52 @@ function HabeetatProvider({
373
373
  }
374
374
  ) });
375
375
  }
376
+ function HabeetatProvider(props) {
377
+ const { configDiscoveryUrl, logto, platformUrl, loadingFallback } = props;
378
+ if (!configDiscoveryUrl && (!logto.endpoint || !platformUrl)) {
379
+ throw new Error(
380
+ "HabeetatProvider: provide both `platformUrl` and `logto.endpoint`, or set `configDiscoveryUrl` to discover them at runtime."
381
+ );
382
+ }
383
+ const needsDiscovery = !!configDiscoveryUrl && (!logto.endpoint || !platformUrl);
384
+ const [resolved, setResolved] = react.useState(
385
+ needsDiscovery ? null : {
386
+ endpoint: logto.endpoint,
387
+ platformUrl,
388
+ resources: logto.resources
389
+ }
390
+ );
391
+ const [discoveryError, setDiscoveryError] = react.useState(null);
392
+ react.useEffect(() => {
393
+ if (!needsDiscovery || !configDiscoveryUrl) return;
394
+ let cancelled = false;
395
+ sdkCore.fetchPlatformConfig(configDiscoveryUrl).then((cfg) => {
396
+ if (cancelled) return;
397
+ setResolved({
398
+ endpoint: logto.endpoint ?? cfg.logtoEndpoint,
399
+ platformUrl: platformUrl ?? cfg.apiBase,
400
+ resources: logto.resources ?? [cfg.apiResource]
401
+ });
402
+ }).catch((err) => {
403
+ if (!cancelled) {
404
+ setDiscoveryError(err instanceof Error ? err : new Error(String(err)));
405
+ }
406
+ });
407
+ return () => {
408
+ cancelled = true;
409
+ };
410
+ }, [needsDiscovery, configDiscoveryUrl]);
411
+ if (discoveryError) throw discoveryError;
412
+ if (!resolved) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loadingFallback ?? null });
413
+ return /* @__PURE__ */ jsxRuntime.jsx(
414
+ HabeetatProviderResolved,
415
+ {
416
+ ...props,
417
+ platformUrl: resolved.platformUrl,
418
+ logto: { ...logto, endpoint: resolved.endpoint, resources: resolved.resources ?? logto.resources }
419
+ }
420
+ );
421
+ }
376
422
  function useHabeetat() {
377
423
  const context = react.useContext(HabeetatContext);
378
424
  if (!context) {
@@ -906,6 +952,10 @@ function RequireFeature({ flag, children, fallback = null }) {
906
952
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
907
953
  }
908
954
 
955
+ Object.defineProperty(exports, "fetchPlatformConfig", {
956
+ enumerable: true,
957
+ get: function () { return sdkCore.fetchPlatformConfig; }
958
+ });
909
959
  exports.HabeetatContext = HabeetatContext;
910
960
  exports.HabeetatProvider = HabeetatProvider;
911
961
  exports.RequireFeature = RequireFeature;
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/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":"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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 { 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"]}
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","fetchPlatformConfig","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, fetchPlatformConfig } 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). Optional when\n * `configDiscoveryUrl` is set — it is then discovered at runtime. */\n endpoint?: string;\n /** OIDC application ID registered in Logto (always required — app-specific). */\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). Optional when\n * `configDiscoveryUrl` is set — it is then discovered at runtime (`apiBase`). */\n platformUrl?: string;\n /**\n * If set, the provider fetches `/.well-known/habeetat` from this URL (the\n * platform's api base or apex domain) at startup and self-configures any of\n * `logto.endpoint` / `logto.resources` / `platformUrl` not explicitly provided.\n * Lets a vendor SPA drop all build-time `VITE_*` platform URLs — only its own\n * `logto.appId` (+ optional `tenantSlug`) remains app-specific.\n */\n configDiscoveryUrl?: 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 */\n/** Props after config-discovery has resolved the infrastructure URLs. */\ntype ResolvedProviderProps = Omit<\n HabeetatProviderProps,\n 'platformUrl' | 'logto' | 'configDiscoveryUrl'\n> & {\n platformUrl: string;\n logto: LogtoConfig & { endpoint: string };\n};\n\nfunction HabeetatProviderResolved({\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}: ResolvedProviderProps) {\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\n// ---------------------------------------------------------------------------\n// Public provider — optionally self-configures via config-discovery, then\n// delegates to HabeetatProviderResolved with concrete infrastructure URLs.\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Either supply the platform URLs explicitly (`logto.endpoint` + `platformUrl`),\n * or set `configDiscoveryUrl` to the platform's api base / apex domain and the\n * provider fetches `/.well-known/habeetat` at startup to self-configure them —\n * so a vendor SPA needs no build-time `VITE_*` platform URLs (only its own\n * `logto.appId` remains app-specific).\n *\n * @example Explicit\n * ```tsx\n * <HabeetatProvider\n * logto={{ endpoint: 'https://iam.example.com', appId: 'abc123' }}\n * platformUrl=\"https://api.example.com\"\n * tenantSlug=\"acme\"\n * ><App /></HabeetatProvider>\n * ```\n *\n * @example Self-configuring\n * ```tsx\n * <HabeetatProvider\n * logto={{ appId: 'abc123' }}\n * configDiscoveryUrl=\"https://api.acme.example.com\"\n * tenantSlug=\"acme\"\n * ><App /></HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider(props: HabeetatProviderProps) {\n const { configDiscoveryUrl, logto, platformUrl, loadingFallback } = props;\n\n if (!configDiscoveryUrl && (!logto.endpoint || !platformUrl)) {\n throw new Error(\n 'HabeetatProvider: provide both `platformUrl` and `logto.endpoint`, or set ' +\n '`configDiscoveryUrl` to discover them at runtime.',\n );\n }\n\n const needsDiscovery = !!configDiscoveryUrl && (!logto.endpoint || !platformUrl);\n\n const [resolved, setResolved] = useState<\n { endpoint: string; platformUrl: string; resources?: string[] } | null\n >(\n needsDiscovery\n ? null\n : {\n endpoint: logto.endpoint as string,\n platformUrl: platformUrl as string,\n resources: logto.resources,\n },\n );\n const [discoveryError, setDiscoveryError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!needsDiscovery || !configDiscoveryUrl) return;\n let cancelled = false;\n fetchPlatformConfig(configDiscoveryUrl)\n .then((cfg) => {\n if (cancelled) return;\n setResolved({\n endpoint: logto.endpoint ?? cfg.logtoEndpoint,\n platformUrl: platformUrl ?? cfg.apiBase,\n resources: logto.resources ?? [cfg.apiResource],\n });\n })\n .catch((err) => {\n if (!cancelled) {\n setDiscoveryError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n return () => {\n cancelled = true;\n };\n // logto.* / platformUrl are captured once at startup; re-discovery is intentional only on URL change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [needsDiscovery, configDiscoveryUrl]);\n\n // Surface discovery failure to the nearest error boundary.\n if (discoveryError) throw discoveryError;\n\n if (!resolved) return <>{loadingFallback ?? null}</>;\n\n return (\n <HabeetatProviderResolved\n {...props}\n platformUrl={resolved.platformUrl}\n logto={{ ...logto, endpoint: resolved.endpoint, resources: resolved.resources ?? logto.resources }}\n />\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
@@ -1,6 +1,7 @@
1
- import { createContext, useRef, useContext, useCallback, useState, useEffect, useMemo } from 'react';
2
- import { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';
3
- import { SDK_ENDPOINTS } from '@habeetat/sdk-core';
1
+ import { createContext, useState, useEffect, useContext, useCallback, useRef, useMemo } from 'react';
2
+ import { useLogto, LogtoProvider, useHandleSignInCallback } from '@logto/react';
3
+ import { fetchPlatformConfig, SDK_ENDPOINTS } from '@habeetat/sdk-core';
4
+ export { fetchPlatformConfig } from '@habeetat/sdk-core';
4
5
  import { jsx, Fragment } from 'react/jsx-runtime';
5
6
 
6
7
  // src/provider/HabeetatProvider.tsx
@@ -333,7 +334,7 @@ function HabeetatInner({
333
334
  }
334
335
  return /* @__PURE__ */ jsx(HabeetatContext.Provider, { value: contextValue, children });
335
336
  }
336
- function HabeetatProvider({
337
+ function HabeetatProviderResolved({
337
338
  logto,
338
339
  platformUrl,
339
340
  logtoResource,
@@ -371,6 +372,52 @@ function HabeetatProvider({
371
372
  }
372
373
  ) });
373
374
  }
375
+ function HabeetatProvider(props) {
376
+ const { configDiscoveryUrl, logto, platformUrl, loadingFallback } = props;
377
+ if (!configDiscoveryUrl && (!logto.endpoint || !platformUrl)) {
378
+ throw new Error(
379
+ "HabeetatProvider: provide both `platformUrl` and `logto.endpoint`, or set `configDiscoveryUrl` to discover them at runtime."
380
+ );
381
+ }
382
+ const needsDiscovery = !!configDiscoveryUrl && (!logto.endpoint || !platformUrl);
383
+ const [resolved, setResolved] = useState(
384
+ needsDiscovery ? null : {
385
+ endpoint: logto.endpoint,
386
+ platformUrl,
387
+ resources: logto.resources
388
+ }
389
+ );
390
+ const [discoveryError, setDiscoveryError] = useState(null);
391
+ useEffect(() => {
392
+ if (!needsDiscovery || !configDiscoveryUrl) return;
393
+ let cancelled = false;
394
+ fetchPlatformConfig(configDiscoveryUrl).then((cfg) => {
395
+ if (cancelled) return;
396
+ setResolved({
397
+ endpoint: logto.endpoint ?? cfg.logtoEndpoint,
398
+ platformUrl: platformUrl ?? cfg.apiBase,
399
+ resources: logto.resources ?? [cfg.apiResource]
400
+ });
401
+ }).catch((err) => {
402
+ if (!cancelled) {
403
+ setDiscoveryError(err instanceof Error ? err : new Error(String(err)));
404
+ }
405
+ });
406
+ return () => {
407
+ cancelled = true;
408
+ };
409
+ }, [needsDiscovery, configDiscoveryUrl]);
410
+ if (discoveryError) throw discoveryError;
411
+ if (!resolved) return /* @__PURE__ */ jsx(Fragment, { children: loadingFallback ?? null });
412
+ return /* @__PURE__ */ jsx(
413
+ HabeetatProviderResolved,
414
+ {
415
+ ...props,
416
+ platformUrl: resolved.platformUrl,
417
+ logto: { ...logto, endpoint: resolved.endpoint, resources: resolved.resources ?? logto.resources }
418
+ }
419
+ );
420
+ }
374
421
  function useHabeetat() {
375
422
  const context = useContext(HabeetatContext);
376
423
  if (!context) {
@@ -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/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":";;;;;;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,GAAkB,cAAoC,mBAAmB;ACxBtF,SAAS,eAAA,CAAgB,EAAE,eAAA,EAAgB,EAAyB;AAClE,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,uBAAA,CAAwB,MAAM;AAClD,IAAA,MAAA,CAAO,SAAS,IAAA,GAAO,GAAA;AAAA,EACzB,CAAC,CAAA;AAED,EAAA,IAAI,SAAA,EAAW,OAAO,eAAA,mBAAkB,GAAA,CAAA,QAAA,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,GAAI,QAAA,EAAS;AAEhJ,EAAA,MAAM,gBAAgB,aAAA,IAAiB,WAAA;AACvC,EAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,EAAA,MAAM,UAAA,GAAa,OAAO,KAAK,CAAA;AAE/B,EAAA,MAAM,eAAA,GAAkB,OAAO,KAAK,CAAA;AAEpC,EAAA,MAAM,iBAAA,GAAoB,OAAO,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,EAAA,SAAA,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,GAAI,QAAA,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,GAAS,OAAA,CAAQ,MAAM,WAAA,CAAY,OAAA,CAAQ,OAAO,EAAE,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAG1E,EAAA,MAAM,iBAAA,GAAoB,OAAO,cAAc,CAAA;AAC/C,EAAA,iBAAA,CAAkB,OAAA,GAAU,cAAA;AAE5B,EAAA,MAAM,YAAA,GAAe,WAAA;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,GAAc,OAAO,YAAY,CAAA;AACvC,EAAA,WAAA,CAAY,OAAA,GAAU,YAAA;AAEtB,EAAA,MAAM,cAAA,GAAiB,YAAY,YAAY;AAC7C,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,OAAA,CAAoB,cAAc,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,GAAkB,YAAY,YAAY;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,OAAA,CAA0B,cAAc,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,GAAsB,YAAY,YAAY;AAClD,IAAA,IAAI;AACF,MAAA,MAAM,YAAA,GAAe,MAAM,WAAA,CAAY,OAAA,CAAyB,cAAc,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,GAA0B,WAAA,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,GAAG,aAAA,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,GAAgB,WAAA;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,GAAmB,WAAA;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,GAAoB,WAAA;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,GAAmB,WAAA;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,GAAY,WAAA;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,GAAW,YAAY,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,EAAA,SAAA,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,CAAoB,aAAA,CAAc,OAAO,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,UACvE,YAAY,OAAA,CAA0B,aAAA,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,cACnC,aAAA,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/B,aAAA,CAAc;AAAA,WAChB,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,QAEpB,CAAA,MAAO;AAEL,UAAA,YAAA,GAAe,MAAM,WAAA,CAAY,OAAA;AAAA,YAC/B,aAAA,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,gBACnC,aAAA,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,GAAqC,OAAA;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,uBAAO,GAAA,CAAC,mBAAgB,eAAA,EAAkC,CAAA;AAAA,EAC5D;AAGA,EAAA,2BACG,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,iBAAiB,MAAA,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,uBACE,GAAA,CAAC,aAAA,EAAA,EAAc,MAAA,EAAQ,WAAA,EACrB,QAAA,kBAAA,GAAA;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,GAAU,WAAW,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,GAAUA,WAAAA;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,GAAIC,QAAAA,CAA6B,EAAE,CAAA;AACzD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,SAAS,IAAI,CAAA;AAC/C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,UAAA,GAAaC,OAAO,KAAK,CAAA;AAE/B,EAAA,MAAM,UAAA,GAAaF,YAAY,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,CAAIG,cAAc,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,EAAAC,UAAU,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,GAAUJ,YAAY,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,GAAIK,QAAAA,EAAS;AAChD,EAAA,OAAO,EAAE,iBAAiB,SAAA,EAAU;AACtC;ACPO,SAAS,SAAA,GAAoD;AAClE,EAAA,MAAM,EAAE,MAAA,EAAO,GAAIA,QAAAA,EAAS;AAC5B,EAAA,OAAO,MAAA;AACT;ACHO,SAAS,UAAA,GAAgE;AAC9E,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAIC,UAAAA,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,EAAGH,cAAc,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,GAAIG,WAAW,eAAe,CAAA;AAE9B,EAAA,MAAM,SAAA,GAAYJ,OAAoC,IAAI,CAAA;AAG1D,EAAA,MAAM,YAAA,GAAeK,OAAAA;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,EAAAH,UAAU,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,GAAMJ,WAAAA;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,WAAAA;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,WAAAA;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,WAAAA;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,WAAAA;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,YAAY,YAAY;AACpC,IAAA,MAAM,SAAA,CAAU,SAAS,KAAA,EAAM;AAAA,EACjC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAOO,OAAAA;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,GAAQP,WAAAA,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,GAAIM,WAAW,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,WAAW,eAAe,CAAA;AAChE,EAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAAU,EAAC;AAEnC,EAAA,MAAM,SAAA,GAAYN,WAAAA;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,WAAAA;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,GAAoBE,OAAO,cAAc,CAAA;AAC/C,EAAA,iBAAA,CAAkB,OAAA,GAAU,cAAA;AAE5B,EAAAE,UAAU,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,GAAIH,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,SAAuB,IAAI,CAAA;AAErD,EAAA,MAAM,aAAA,GAAgBD,WAAAA,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,GAAIC,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,SAAuB,IAAI,CAAA;AAErD,EAAA,MAAM,UAAA,GAAaD,WAAAA,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,uBAAOQ,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,GAAAA,CAAAC,QAAAA,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,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AACrB","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"]}
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, fetchPlatformConfig } 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). Optional when\n * `configDiscoveryUrl` is set — it is then discovered at runtime. */\n endpoint?: string;\n /** OIDC application ID registered in Logto (always required — app-specific). */\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). Optional when\n * `configDiscoveryUrl` is set — it is then discovered at runtime (`apiBase`). */\n platformUrl?: string;\n /**\n * If set, the provider fetches `/.well-known/habeetat` from this URL (the\n * platform's api base or apex domain) at startup and self-configures any of\n * `logto.endpoint` / `logto.resources` / `platformUrl` not explicitly provided.\n * Lets a vendor SPA drop all build-time `VITE_*` platform URLs — only its own\n * `logto.appId` (+ optional `tenantSlug`) remains app-specific.\n */\n configDiscoveryUrl?: 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 */\n/** Props after config-discovery has resolved the infrastructure URLs. */\ntype ResolvedProviderProps = Omit<\n HabeetatProviderProps,\n 'platformUrl' | 'logto' | 'configDiscoveryUrl'\n> & {\n platformUrl: string;\n logto: LogtoConfig & { endpoint: string };\n};\n\nfunction HabeetatProviderResolved({\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}: ResolvedProviderProps) {\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\n// ---------------------------------------------------------------------------\n// Public provider — optionally self-configures via config-discovery, then\n// delegates to HabeetatProviderResolved with concrete infrastructure URLs.\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Either supply the platform URLs explicitly (`logto.endpoint` + `platformUrl`),\n * or set `configDiscoveryUrl` to the platform's api base / apex domain and the\n * provider fetches `/.well-known/habeetat` at startup to self-configure them —\n * so a vendor SPA needs no build-time `VITE_*` platform URLs (only its own\n * `logto.appId` remains app-specific).\n *\n * @example Explicit\n * ```tsx\n * <HabeetatProvider\n * logto={{ endpoint: 'https://iam.example.com', appId: 'abc123' }}\n * platformUrl=\"https://api.example.com\"\n * tenantSlug=\"acme\"\n * ><App /></HabeetatProvider>\n * ```\n *\n * @example Self-configuring\n * ```tsx\n * <HabeetatProvider\n * logto={{ appId: 'abc123' }}\n * configDiscoveryUrl=\"https://api.acme.example.com\"\n * tenantSlug=\"acme\"\n * ><App /></HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider(props: HabeetatProviderProps) {\n const { configDiscoveryUrl, logto, platformUrl, loadingFallback } = props;\n\n if (!configDiscoveryUrl && (!logto.endpoint || !platformUrl)) {\n throw new Error(\n 'HabeetatProvider: provide both `platformUrl` and `logto.endpoint`, or set ' +\n '`configDiscoveryUrl` to discover them at runtime.',\n );\n }\n\n const needsDiscovery = !!configDiscoveryUrl && (!logto.endpoint || !platformUrl);\n\n const [resolved, setResolved] = useState<\n { endpoint: string; platformUrl: string; resources?: string[] } | null\n >(\n needsDiscovery\n ? null\n : {\n endpoint: logto.endpoint as string,\n platformUrl: platformUrl as string,\n resources: logto.resources,\n },\n );\n const [discoveryError, setDiscoveryError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!needsDiscovery || !configDiscoveryUrl) return;\n let cancelled = false;\n fetchPlatformConfig(configDiscoveryUrl)\n .then((cfg) => {\n if (cancelled) return;\n setResolved({\n endpoint: logto.endpoint ?? cfg.logtoEndpoint,\n platformUrl: platformUrl ?? cfg.apiBase,\n resources: logto.resources ?? [cfg.apiResource],\n });\n })\n .catch((err) => {\n if (!cancelled) {\n setDiscoveryError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n return () => {\n cancelled = true;\n };\n // logto.* / platformUrl are captured once at startup; re-discovery is intentional only on URL change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [needsDiscovery, configDiscoveryUrl]);\n\n // Surface discovery failure to the nearest error boundary.\n if (discoveryError) throw discoveryError;\n\n if (!resolved) return <>{loadingFallback ?? null}</>;\n\n return (\n <HabeetatProviderResolved\n {...props}\n platformUrl={resolved.platformUrl}\n logto={{ ...logto, endpoint: resolved.endpoint, resources: resolved.resources ?? logto.resources }}\n />\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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@habeetat/sdk-react",
3
- "version": "0.2.1-dev.20260618083959.3cb5192",
3
+ "version": "0.2.1-dev.20260619123920.2f9dafc",
4
4
  "description": "Habeetat Platform SDK for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",