@habeetat/sdk-react 0.2.0-dev.20260521144805.4f68772 → 0.2.1-dev.20260606080502.37cebd8

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/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  Habeetat Platform SDK for React applications.
4
4
 
5
+
5
6
  ## Installation
6
7
 
7
8
  ```bash
package/dist/index.d.mts CHANGED
@@ -91,6 +91,10 @@ interface HabeetatState {
91
91
  subscription: SdkSubscription | null;
92
92
  /** User subscription info (USER scope - B2C) */
93
93
  userSubscription: SdkSubscription | null;
94
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
95
+ isUserSubscriptionLoading: boolean;
96
+ /** Error from the most recent user subscription fetch, or null if successful */
97
+ userSubscriptionError: Error | null;
94
98
  }
95
99
  /**
96
100
  * Habeetat SDK context value
@@ -246,6 +250,17 @@ declare function useSubscription(): {
246
250
  /**
247
251
  * Hook for USER-scoped subscription (B2C SaaS model).
248
252
  * Returns the subscription tied to the individual user, not the tenant.
253
+ *
254
+ * @example
255
+ * ```tsx
256
+ * function SubscriptionBadge() {
257
+ * const { plan, isLoading, error, refresh } = useUserSubscription();
258
+ *
259
+ * if (isLoading) return <Spinner />;
260
+ * if (error) return <RetryButton onRetry={refresh} />;
261
+ * return <PlanBadge plan={plan} />;
262
+ * }
263
+ * ```
249
264
  */
250
265
  declare function useUserSubscription(): {
251
266
  /** Current user subscription */
@@ -270,6 +285,10 @@ declare function useUserSubscription(): {
270
285
  refresh: (appId?: string) => Promise<void>;
271
286
  /** Current user ID */
272
287
  userId: string | undefined;
288
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
289
+ isLoading: boolean;
290
+ /** Error from the most recent fetch attempt, or null if successful */
291
+ error: Error | null;
273
292
  };
274
293
 
275
294
  interface UsePlansReturn {
package/dist/index.d.ts CHANGED
@@ -91,6 +91,10 @@ interface HabeetatState {
91
91
  subscription: SdkSubscription | null;
92
92
  /** User subscription info (USER scope - B2C) */
93
93
  userSubscription: SdkSubscription | null;
94
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
95
+ isUserSubscriptionLoading: boolean;
96
+ /** Error from the most recent user subscription fetch, or null if successful */
97
+ userSubscriptionError: Error | null;
94
98
  }
95
99
  /**
96
100
  * Habeetat SDK context value
@@ -246,6 +250,17 @@ declare function useSubscription(): {
246
250
  /**
247
251
  * Hook for USER-scoped subscription (B2C SaaS model).
248
252
  * Returns the subscription tied to the individual user, not the tenant.
253
+ *
254
+ * @example
255
+ * ```tsx
256
+ * function SubscriptionBadge() {
257
+ * const { plan, isLoading, error, refresh } = useUserSubscription();
258
+ *
259
+ * if (isLoading) return <Spinner />;
260
+ * if (error) return <RetryButton onRetry={refresh} />;
261
+ * return <PlanBadge plan={plan} />;
262
+ * }
263
+ * ```
249
264
  */
250
265
  declare function useUserSubscription(): {
251
266
  /** Current user subscription */
@@ -270,6 +285,10 @@ declare function useUserSubscription(): {
270
285
  refresh: (appId?: string) => Promise<void>;
271
286
  /** Current user ID */
272
287
  userId: string | undefined;
288
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
289
+ isLoading: boolean;
290
+ /** Error from the most recent fetch attempt, or null if successful */
291
+ error: Error | null;
273
292
  };
274
293
 
275
294
  interface UsePlansReturn {
package/dist/index.js CHANGED
@@ -13,6 +13,8 @@ var defaultContextValue = {
13
13
  features: null,
14
14
  subscription: null,
15
15
  userSubscription: null,
16
+ isUserSubscriptionLoading: true,
17
+ userSubscriptionError: null,
16
18
  refreshContext: async () => {
17
19
  },
18
20
  refreshFeatures: async () => {
@@ -72,7 +74,9 @@ function HabeetatInner({
72
74
  context: null,
73
75
  features: null,
74
76
  subscription: null,
75
- userSubscription: null
77
+ userSubscription: null,
78
+ isUserSubscriptionLoading: true,
79
+ userSubscriptionError: null
76
80
  });
77
81
  const apiUrl = react.useMemo(() => platformUrl.replace(/\/$/, ""), [platformUrl]);
78
82
  const getAccessTokenRef = react.useRef(getAccessToken);
@@ -130,14 +134,25 @@ function HabeetatInner({
130
134
  }
131
135
  }, []);
132
136
  const refreshUserSubscription = react.useCallback(async (_appId) => {
137
+ setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));
133
138
  try {
134
139
  const params = new URLSearchParams();
135
140
  if (_appId) params.set("appId", _appId);
136
141
  const queryString = params.toString();
137
142
  const endpoint = `${sdkCore.SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ""}`;
138
143
  const userSubscription = await fetchApiRef.current(endpoint);
139
- setState((prev) => ({ ...prev, userSubscription, error: null }));
140
- } catch {
144
+ setState((prev) => ({
145
+ ...prev,
146
+ userSubscription,
147
+ isUserSubscriptionLoading: false,
148
+ userSubscriptionError: null
149
+ }));
150
+ } catch (err) {
151
+ setState((prev) => ({
152
+ ...prev,
153
+ isUserSubscriptionLoading: false,
154
+ userSubscriptionError: err
155
+ }));
141
156
  }
142
157
  }, []);
143
158
  const hasPermission = react.useCallback(
@@ -219,7 +234,7 @@ function HabeetatInner({
219
234
  if (logtoLoading || !isAuthenticated || hasFetched.current) return;
220
235
  hasFetched.current = true;
221
236
  const fetchAll = async () => {
222
- setState((prev) => ({ ...prev, isLoading: true }));
237
+ setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));
223
238
  try {
224
239
  const [context, features] = await Promise.all([
225
240
  fetchApiRef.current(sdkCore.SDK_ENDPOINTS.CONTEXT).catch(() => null),
@@ -229,10 +244,15 @@ function HabeetatInner({
229
244
  const userId = context?.user?.id;
230
245
  let subscription = null;
231
246
  let userSubscription = null;
247
+ let userSubscriptionError = null;
232
248
  if (billingScope === "USER" && userId) {
233
- userSubscription = await fetchApiRef.current(
234
- sdkCore.SDK_ENDPOINTS.USER_SUBSCRIPTION
235
- ).catch(() => null);
249
+ try {
250
+ userSubscription = await fetchApiRef.current(
251
+ sdkCore.SDK_ENDPOINTS.USER_SUBSCRIPTION
252
+ );
253
+ } catch (err) {
254
+ userSubscriptionError = err;
255
+ }
236
256
  } else if (billingScope === "TENANT") {
237
257
  subscription = await fetchApiRef.current(
238
258
  sdkCore.SDK_ENDPOINTS.SUBSCRIPTION
@@ -242,14 +262,32 @@ function HabeetatInner({
242
262
  sdkCore.SDK_ENDPOINTS.SUBSCRIPTION
243
263
  ).catch(() => null);
244
264
  if (userId) {
245
- userSubscription = await fetchApiRef.current(
246
- sdkCore.SDK_ENDPOINTS.USER_SUBSCRIPTION
247
- ).catch(() => null);
265
+ try {
266
+ userSubscription = await fetchApiRef.current(
267
+ sdkCore.SDK_ENDPOINTS.USER_SUBSCRIPTION
268
+ );
269
+ } catch (err) {
270
+ userSubscriptionError = err;
271
+ }
248
272
  }
249
273
  }
250
- setState({ isLoading: false, error: null, context, features, subscription, userSubscription });
274
+ setState({
275
+ isLoading: false,
276
+ error: null,
277
+ context,
278
+ features,
279
+ subscription,
280
+ userSubscription,
281
+ isUserSubscriptionLoading: false,
282
+ userSubscriptionError
283
+ });
251
284
  } catch (error) {
252
- setState((prev) => ({ ...prev, isLoading: false, error }));
285
+ setState((prev) => ({
286
+ ...prev,
287
+ isLoading: false,
288
+ isUserSubscriptionLoading: false,
289
+ error
290
+ }));
253
291
  }
254
292
  };
255
293
  fetchAll();
@@ -392,9 +430,9 @@ function useSubscription() {
392
430
  /** Subscription status */
393
431
  status: subscription?.status,
394
432
  /** Check if subscription is active */
395
- isActive: subscription?.status === "active" || subscription?.status === "trialing" || subscription?.status === "trial",
433
+ isActive: subscription?.status === "active" || subscription?.status === "trial",
396
434
  /** Check if in trial */
397
- isTrialing: subscription?.status === "trialing" || subscription?.status === "trial",
435
+ isTrialing: subscription?.status === "trial",
398
436
  /** Check limit */
399
437
  checkLimit: (key, increment = 0) => {
400
438
  const limit = subscription?.limits?.[key];
@@ -407,7 +445,13 @@ function useSubscription() {
407
445
  };
408
446
  }
409
447
  function useUserSubscription() {
410
- const { userSubscription, context, refreshUserSubscription } = useHabeetat();
448
+ const {
449
+ userSubscription,
450
+ context,
451
+ refreshUserSubscription,
452
+ isUserSubscriptionLoading,
453
+ userSubscriptionError
454
+ } = useHabeetat();
411
455
  const userId = context?.user?.id;
412
456
  const refresh = react.useCallback(
413
457
  (appId) => refreshUserSubscription(appId),
@@ -425,9 +469,9 @@ function useUserSubscription() {
425
469
  /** Subscription status */
426
470
  status: userSubscription?.status,
427
471
  /** Check if subscription is active */
428
- isActive: userSubscription?.status === "active" || userSubscription?.status === "trialing" || userSubscription?.status === "trial",
472
+ isActive: userSubscription?.status === "active" || userSubscription?.status === "trial",
429
473
  /** Check if in trial */
430
- isTrialing: userSubscription?.status === "trialing" || userSubscription?.status === "trial",
474
+ isTrialing: userSubscription?.status === "trial",
431
475
  /** Whether the user has any subscription */
432
476
  hasSubscription: userSubscription !== null && userSubscription !== void 0,
433
477
  /** Check limit against user subscription */
@@ -440,7 +484,11 @@ function useUserSubscription() {
440
484
  /** Refresh the user subscription */
441
485
  refresh,
442
486
  /** Current user ID */
443
- userId
487
+ userId,
488
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
489
+ isLoading: isUserSubscriptionLoading,
490
+ /** Error from the most recent fetch attempt, or null if successful */
491
+ error: userSubscriptionError
444
492
  };
445
493
  }
446
494
  function usePlans() {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["createContext","useHandleSignInCallback","jsx","Fragment","useLogto","useRef","useEffect","useState","useMemo","useCallback","SDK_ENDPOINTS","LogtoProvider","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n}\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 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 });\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 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) => ({ ...prev, userSubscription, error: null }));\n } catch {\n // User subscription is optional — don't propagate errors\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 }));\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\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n ).catch(() => null);\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 } 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 userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n ).catch(() => null);\n }\n }\n\n setState({ isLoading: false, error: null, context, features, subscription, userSubscription });\n } catch (error) {\n setState((prev) => ({ ...prev, isLoading: false, error: error as Error }));\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 === 'trialing' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trialing' || 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 */\nexport function useUserSubscription() {\n const { userSubscription, context, refreshUserSubscription } = 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 === 'trialing' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trialing' || 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 };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n }\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/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["createContext","useHandleSignInCallback","jsx","Fragment","useLogto","useRef","useEffect","useState","useMemo","useCallback","SDK_ENDPOINTS","LogtoProvider","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n }\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
@@ -11,6 +11,8 @@ var defaultContextValue = {
11
11
  features: null,
12
12
  subscription: null,
13
13
  userSubscription: null,
14
+ isUserSubscriptionLoading: true,
15
+ userSubscriptionError: null,
14
16
  refreshContext: async () => {
15
17
  },
16
18
  refreshFeatures: async () => {
@@ -70,7 +72,9 @@ function HabeetatInner({
70
72
  context: null,
71
73
  features: null,
72
74
  subscription: null,
73
- userSubscription: null
75
+ userSubscription: null,
76
+ isUserSubscriptionLoading: true,
77
+ userSubscriptionError: null
74
78
  });
75
79
  const apiUrl = useMemo(() => platformUrl.replace(/\/$/, ""), [platformUrl]);
76
80
  const getAccessTokenRef = useRef(getAccessToken);
@@ -128,14 +132,25 @@ function HabeetatInner({
128
132
  }
129
133
  }, []);
130
134
  const refreshUserSubscription = useCallback(async (_appId) => {
135
+ setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));
131
136
  try {
132
137
  const params = new URLSearchParams();
133
138
  if (_appId) params.set("appId", _appId);
134
139
  const queryString = params.toString();
135
140
  const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ""}`;
136
141
  const userSubscription = await fetchApiRef.current(endpoint);
137
- setState((prev) => ({ ...prev, userSubscription, error: null }));
138
- } catch {
142
+ setState((prev) => ({
143
+ ...prev,
144
+ userSubscription,
145
+ isUserSubscriptionLoading: false,
146
+ userSubscriptionError: null
147
+ }));
148
+ } catch (err) {
149
+ setState((prev) => ({
150
+ ...prev,
151
+ isUserSubscriptionLoading: false,
152
+ userSubscriptionError: err
153
+ }));
139
154
  }
140
155
  }, []);
141
156
  const hasPermission = useCallback(
@@ -217,7 +232,7 @@ function HabeetatInner({
217
232
  if (logtoLoading || !isAuthenticated || hasFetched.current) return;
218
233
  hasFetched.current = true;
219
234
  const fetchAll = async () => {
220
- setState((prev) => ({ ...prev, isLoading: true }));
235
+ setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));
221
236
  try {
222
237
  const [context, features] = await Promise.all([
223
238
  fetchApiRef.current(SDK_ENDPOINTS.CONTEXT).catch(() => null),
@@ -227,10 +242,15 @@ function HabeetatInner({
227
242
  const userId = context?.user?.id;
228
243
  let subscription = null;
229
244
  let userSubscription = null;
245
+ let userSubscriptionError = null;
230
246
  if (billingScope === "USER" && userId) {
231
- userSubscription = await fetchApiRef.current(
232
- SDK_ENDPOINTS.USER_SUBSCRIPTION
233
- ).catch(() => null);
247
+ try {
248
+ userSubscription = await fetchApiRef.current(
249
+ SDK_ENDPOINTS.USER_SUBSCRIPTION
250
+ );
251
+ } catch (err) {
252
+ userSubscriptionError = err;
253
+ }
234
254
  } else if (billingScope === "TENANT") {
235
255
  subscription = await fetchApiRef.current(
236
256
  SDK_ENDPOINTS.SUBSCRIPTION
@@ -240,14 +260,32 @@ function HabeetatInner({
240
260
  SDK_ENDPOINTS.SUBSCRIPTION
241
261
  ).catch(() => null);
242
262
  if (userId) {
243
- userSubscription = await fetchApiRef.current(
244
- SDK_ENDPOINTS.USER_SUBSCRIPTION
245
- ).catch(() => null);
263
+ try {
264
+ userSubscription = await fetchApiRef.current(
265
+ SDK_ENDPOINTS.USER_SUBSCRIPTION
266
+ );
267
+ } catch (err) {
268
+ userSubscriptionError = err;
269
+ }
246
270
  }
247
271
  }
248
- setState({ isLoading: false, error: null, context, features, subscription, userSubscription });
272
+ setState({
273
+ isLoading: false,
274
+ error: null,
275
+ context,
276
+ features,
277
+ subscription,
278
+ userSubscription,
279
+ isUserSubscriptionLoading: false,
280
+ userSubscriptionError
281
+ });
249
282
  } catch (error) {
250
- setState((prev) => ({ ...prev, isLoading: false, error }));
283
+ setState((prev) => ({
284
+ ...prev,
285
+ isLoading: false,
286
+ isUserSubscriptionLoading: false,
287
+ error
288
+ }));
251
289
  }
252
290
  };
253
291
  fetchAll();
@@ -390,9 +428,9 @@ function useSubscription() {
390
428
  /** Subscription status */
391
429
  status: subscription?.status,
392
430
  /** Check if subscription is active */
393
- isActive: subscription?.status === "active" || subscription?.status === "trialing" || subscription?.status === "trial",
431
+ isActive: subscription?.status === "active" || subscription?.status === "trial",
394
432
  /** Check if in trial */
395
- isTrialing: subscription?.status === "trialing" || subscription?.status === "trial",
433
+ isTrialing: subscription?.status === "trial",
396
434
  /** Check limit */
397
435
  checkLimit: (key, increment = 0) => {
398
436
  const limit = subscription?.limits?.[key];
@@ -405,7 +443,13 @@ function useSubscription() {
405
443
  };
406
444
  }
407
445
  function useUserSubscription() {
408
- const { userSubscription, context, refreshUserSubscription } = useHabeetat();
446
+ const {
447
+ userSubscription,
448
+ context,
449
+ refreshUserSubscription,
450
+ isUserSubscriptionLoading,
451
+ userSubscriptionError
452
+ } = useHabeetat();
409
453
  const userId = context?.user?.id;
410
454
  const refresh = useCallback(
411
455
  (appId) => refreshUserSubscription(appId),
@@ -423,9 +467,9 @@ function useUserSubscription() {
423
467
  /** Subscription status */
424
468
  status: userSubscription?.status,
425
469
  /** Check if subscription is active */
426
- isActive: userSubscription?.status === "active" || userSubscription?.status === "trialing" || userSubscription?.status === "trial",
470
+ isActive: userSubscription?.status === "active" || userSubscription?.status === "trial",
427
471
  /** Check if in trial */
428
- isTrialing: userSubscription?.status === "trialing" || userSubscription?.status === "trial",
472
+ isTrialing: userSubscription?.status === "trial",
429
473
  /** Whether the user has any subscription */
430
474
  hasSubscription: userSubscription !== null && userSubscription !== void 0,
431
475
  /** Check limit against user subscription */
@@ -438,7 +482,11 @@ function useUserSubscription() {
438
482
  /** Refresh the user subscription */
439
483
  refresh,
440
484
  /** Current user ID */
441
- userId
485
+ userId,
486
+ /** Whether the user subscription is currently being fetched (initial load or refresh) */
487
+ isLoading: isUserSubscriptionLoading,
488
+ /** Error from the most recent fetch attempt, or null if successful */
489
+ error: userSubscriptionError
442
490
  };
443
491
  }
444
492
  function usePlans() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context/HabeetatContext.ts","../src/provider/HabeetatProvider.tsx","../src/hooks/useHabeetat.ts","../src/hooks/usePermissions.ts","../src/hooks/useFeatures.ts","../src/hooks/useSubscription.ts","../src/hooks/useUserSubscription.ts","../src/hooks/usePlans.ts","../src/hooks/useAuth.ts","../src/hooks/useSignIn.ts","../src/hooks/useSignOut.ts","../src/logger/HabeetatLoggerClient.ts","../src/hooks/useLogger.ts","../src/hooks/useAnalytics.ts","../src/hooks/useUser.ts","../src/hooks/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["useCallback","useState","useRef","SDK_ENDPOINTS","useEffect","useLogto","useContext","useMemo","jsx","Fragment"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n}\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 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 });\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 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) => ({ ...prev, userSubscription, error: null }));\n } catch {\n // User subscription is optional — don't propagate errors\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 }));\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\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n ).catch(() => null);\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 } 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 userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n ).catch(() => null);\n }\n }\n\n setState({ isLoading: false, error: null, context, features, subscription, userSubscription });\n } catch (error) {\n setState((prev) => ({ ...prev, isLoading: false, error: error as Error }));\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 === 'trialing' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trialing' || 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 */\nexport function useUserSubscription() {\n const { userSubscription, context, refreshUserSubscription } = 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 === 'trialing' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trialing' || 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 };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n }\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/useHttpInterceptor.ts","../src/hooks/useCheckout.ts","../src/hooks/useBillingPortal.ts","../src/components/RequirePermission.tsx","../src/components/RequireFeature.tsx"],"names":["useCallback","useState","useRef","SDK_ENDPOINTS","useEffect","useLogto","useContext","useMemo","jsx","Fragment"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext } from 'react';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\n\n/**\n * Habeetat SDK state\n */\nexport interface HabeetatState {\n /** Whether the SDK is loading initial data */\n isLoading: boolean;\n /** Error if any occurred */\n error: Error | null;\n /** SDK context (user, tenant, permissions) */\n context: SdkContext | null;\n /** Feature flags */\n features: SdkFeaturesState | null;\n /** Subscription info (TENANT scope) */\n subscription: SdkSubscription | null;\n /** User subscription info (USER scope - B2C) */\n userSubscription: SdkSubscription | null;\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isUserSubscriptionLoading: boolean;\n /** Error from the most recent user subscription fetch, or null if successful */\n userSubscriptionError: Error | null;\n}\n\n/**\n * Habeetat SDK context value\n */\nexport interface HabeetatContextValue extends HabeetatState {\n /** Refresh context from server */\n refreshContext: () => Promise<void>;\n /** Refresh features from server */\n refreshFeatures: () => Promise<void>;\n /** Refresh subscription from server (TENANT scope) */\n refreshSubscription: () => Promise<void>;\n /** Refresh user subscription from server (USER scope) */\n refreshUserSubscription: (appId?: string) => Promise<void>;\n /** Check if user has permission */\n hasPermission: (permission: string) => boolean;\n /** Check if user has any of the permissions */\n hasAnyPermission: (permissions: string[]) => boolean;\n /** Check if user has all permissions */\n hasAllPermissions: (permissions: string[]) => boolean;\n /** Check if feature is enabled */\n isFeatureEnabled: (key: string) => boolean;\n /** Get access token for API calls */\n getAccessToken: () => Promise<string | null>;\n /** Platform SDK API base URL (for internal use by useLogger) */\n platformUrl: string | null;\n /** App name for analytics tracking */\n appName?: string;\n /** Current app ID */\n appId?: string;\n /** Current tenant slug */\n tenantSlug?: string;\n /** Logger configuration */\n loggerConfig?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Sign out the current user.\n * - No args + postLogoutRedirectPath configured → redirects to origin + path\n * - Explicit URI → uses that URI\n * - No args + no path → Logto default behavior */\n signOut: (postLogoutRedirectUri?: string) => Promise<void>;\n}\n\n/**\n * Default context value\n */\nconst defaultContextValue: HabeetatContextValue = {\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n refreshContext: async () => {},\n refreshFeatures: async () => {},\n refreshSubscription: async () => {},\n refreshUserSubscription: async () => {},\n hasPermission: () => false,\n hasAnyPermission: () => false,\n hasAllPermissions: () => false,\n isFeatureEnabled: () => false,\n getAccessToken: async () => null,\n platformUrl: null,\n signOut: async () => {},\n};\n\n/**\n * Habeetat React Context\n */\nexport const HabeetatContext = createContext<HabeetatContextValue>(defaultContextValue);\n","import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport { LogtoProvider, useLogto, useHandleSignInCallback } from '@logto/react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkContext, SdkFeaturesState, SdkSubscription } from '@habeetat/sdk-core';\nimport { HabeetatContext, type HabeetatContextValue, type HabeetatState } from '../context/HabeetatContext';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LogtoConfig {\n /** Logto endpoint (e.g. https://iam.yourdomain.com) */\n endpoint: string;\n /** OIDC application ID registered in Logto */\n appId: string;\n /** API resources to request access tokens for */\n resources?: string[];\n /** Additional OIDC scopes */\n scopes?: string[];\n}\n\nexport interface HabeetatProviderProps {\n /** Logto OIDC configuration — replaces the need for a separate LogtoProvider */\n logto: LogtoConfig;\n /** Platform SDK base URL (e.g. https://api.yourdomain.com/sdk/v1) */\n platformUrl: string;\n /** API resource identifier for access-token requests; defaults to platformUrl */\n logtoResource?: string;\n /** App slug registered in Habeetat */\n appId?: string;\n /** App name used as app_id when tracking analytics events */\n appName?: string;\n /** Tenant slug */\n tenantSlug?: string;\n /**\n * Redirect to Logto automatically when the user is not authenticated.\n * A ref guard prevents redirect loops.\n */\n autoSignIn?: boolean;\n /** Path that handles the OIDC callback (default: '/callback') */\n callbackPath?: string;\n /** Rendered while auth state is loading */\n loadingFallback?: ReactNode;\n /** Centralized logging configuration */\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n /** Path portion of the post-logout redirect URI (e.g., \"/backoffice\").\n * When set, signOut() with no arguments will redirect to\n * `window.location.origin + postLogoutRedirectPath`. */\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Callback handler — isolated so useHandleSignInCallback can be called\n// without breaking hooks rules in the main inner component\n// ---------------------------------------------------------------------------\n\ninterface CallbackHandlerProps {\n loadingFallback?: ReactNode;\n}\n\nfunction CallbackHandler({ loadingFallback }: CallbackHandlerProps) {\n const { isLoading } = useHandleSignInCallback(() => {\n window.location.href = '/';\n });\n\n if (isLoading) return loadingFallback ? <>{loadingFallback}</> : null;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Inner provider — runs inside LogtoProvider so it can call useLogto().\n// Merges auth gating and SDK data into a single component that NEVER\n// unmounts the context provider, preventing infinite mount/unmount loops\n// caused by Logto loading-state flicker.\n// ---------------------------------------------------------------------------\n\ninterface InnerProps {\n platformUrl: string;\n logtoResource?: string;\n appId?: string;\n appName?: string;\n tenantSlug?: string;\n autoSignIn?: boolean;\n callbackPath: string;\n loadingFallback?: ReactNode;\n logging?: { enabled?: boolean; level?: import('@habeetat/sdk-core').LogLevel };\n postLogoutRedirectPath?: string;\n children: ReactNode;\n}\n\nfunction HabeetatInner({\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn,\n callbackPath,\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: InnerProps) {\n const { isAuthenticated, isLoading: logtoLoading, getAccessToken, signIn, clearAllTokens, error: logtoError, signOut: logtoSignOut } = useLogto();\n\n const tokenResource = logtoResource ?? platformUrl;\n const signInCalled = useRef(false);\n const hasFetched = useRef(false);\n /** Guard to prevent infinite re-sign-in loops when the refresh token is invalid */\n const isRecoveringRef = useRef(false);\n /** Tracks consecutive null-token returns to detect silent refresh failures */\n const tokenFailCountRef = useRef(0);\n const TOKEN_FAIL_THRESHOLD = 2;\n\n const isCallback =\n typeof window !== 'undefined' &&\n window.location.pathname === callbackPath;\n\n // Auto sign-in redirect\n useEffect(() => {\n if (isCallback || logtoLoading || isAuthenticated || !autoSignIn || signInCalled.current)\n return;\n signInCalled.current = true;\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }, [isCallback, logtoLoading, isAuthenticated, autoSignIn, signIn, callbackPath]);\n\n // --- SDK data state (always mounted, never torn down) ---\n\n const [state, setState] = useState<HabeetatState>({\n isLoading: true,\n error: null,\n context: null,\n features: null,\n subscription: null,\n userSubscription: null,\n isUserSubscriptionLoading: true,\n userSubscriptionError: null,\n });\n\n const apiUrl = useMemo(() => platformUrl.replace(/\\/$/, ''), [platformUrl]);\n\n // Keep a stable ref to getAccessToken so the fetch helpers always use the latest version\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n const fetchApiImpl = useCallback(\n async <T,>(endpoint: string): Promise<T> => {\n if (isRecoveringRef.current) {\n throw new Error('Session recovery in progress');\n }\n let token: string | undefined;\n try {\n token = await getAccessTokenRef.current(tokenResource);\n } catch (err) {\n throw new Error(`Failed to get access token: ${err}`);\n }\n if (!token) throw new Error('No access token available');\n\n const url = new URL(endpoint, apiUrl);\n if (tenantSlug) url.searchParams.set('tenantSlug', tenantSlug);\n if (appId) url.searchParams.set('appId', appId);\n\n const response = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) throw new Error(`API error: ${response.status}`);\n return response.json() as Promise<T>;\n },\n [apiUrl, tokenResource, tenantSlug, appId],\n );\n\n const fetchApiRef = useRef(fetchApiImpl);\n fetchApiRef.current = fetchApiImpl;\n\n const refreshContext = useCallback(async () => {\n try {\n const context = await fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT);\n setState((prev) => ({ ...prev, context, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshFeatures = useCallback(async () => {\n try {\n const features = await fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES);\n setState((prev) => ({ ...prev, features, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshSubscription = useCallback(async () => {\n try {\n const subscription = await fetchApiRef.current<SdkSubscription>(SDK_ENDPOINTS.SUBSCRIPTION);\n setState((prev) => ({ ...prev, subscription, error: null }));\n } catch (error) {\n setState((prev) => ({ ...prev, error: error as Error }));\n }\n }, []);\n\n const refreshUserSubscription = useCallback(async (_appId?: string) => {\n setState((prev) => ({ ...prev, isUserSubscriptionLoading: true, userSubscriptionError: null }));\n try {\n const params = new URLSearchParams();\n if (_appId) params.set('appId', _appId);\n const queryString = params.toString();\n const endpoint = `${SDK_ENDPOINTS.USER_SUBSCRIPTION}${queryString ? `?${queryString}` : ''}`;\n const userSubscription = await fetchApiRef.current<SdkSubscription>(endpoint);\n setState((prev) => ({\n ...prev,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError: null,\n }));\n } catch (err) {\n // Preserve stale userSubscription — only update loading/error state\n setState((prev) => ({\n ...prev,\n isUserSubscriptionLoading: false,\n userSubscriptionError: err as Error,\n }));\n }\n }, []);\n\n const hasPermission = useCallback(\n (permission: string) => state.context?.permissions?.includes(permission) ?? false,\n [state.context?.permissions],\n );\n\n const hasAnyPermission = useCallback(\n (permissions: string[]) => permissions.some((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const hasAllPermissions = useCallback(\n (permissions: string[]) => permissions.every((p) => state.context?.permissions?.includes(p)),\n [state.context?.permissions],\n );\n\n const isFeatureEnabled = useCallback(\n (key: string) => state.features?.features?.[key] ?? false,\n [state.features?.features],\n );\n\n const signOutFn = useCallback(\n async (postLogoutRedirectUri?: string) => {\n const uri = postLogoutRedirectUri\n ?? (postLogoutRedirectPath\n ? `${window.location.origin}${postLogoutRedirectPath}`\n : undefined);\n await logtoSignOut(uri);\n },\n [logtoSignOut, postLogoutRedirectPath],\n );\n\n const getToken = useCallback(async (): Promise<string | null> => {\n if (isRecoveringRef.current) return null;\n\n // If Logto already has an error (e.g. from a failed refresh), don't\n // call getAccessToken again — it would silently retry the refresh\n // token request on every invocation, causing an infinite loop.\n if (logtoError) {\n if (!isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n\n try {\n const token = (await getAccessTokenRef.current(tokenResource)) ?? null;\n\n if (token) {\n tokenFailCountRef.current = 0;\n return token;\n }\n\n // Logto's proxy swallows errors and returns undefined. If we get\n // null repeatedly it means the refresh token is broken.\n tokenFailCountRef.current += 1;\n if (tokenFailCountRef.current >= TOKEN_FAIL_THRESHOLD && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n } catch (err) {\n // Fallback: in case a future Logto version does throw\n const message = err instanceof Error ? err.message : String(err);\n const isGrantError =\n message.includes('invalid_grant') ||\n message.includes('grant request is invalid');\n\n if (isGrantError && !isRecoveringRef.current) {\n isRecoveringRef.current = true;\n try { await clearAllTokens(); } catch { /* best-effort */ }\n if (autoSignIn) {\n const redirectUri =\n typeof window !== 'undefined'\n ? `${window.location.origin}${callbackPath}`\n : callbackPath;\n signIn(redirectUri);\n }\n }\n return null;\n }\n }, [tokenResource, autoSignIn, callbackPath, signIn, clearAllTokens, logtoError]);\n\n // Fetch SDK data exactly once when authenticated\n useEffect(() => {\n if (logtoLoading || !isAuthenticated || hasFetched.current) return;\n hasFetched.current = true;\n\n const fetchAll = async () => {\n setState((prev) => ({ ...prev, isLoading: true, isUserSubscriptionLoading: true }));\n try {\n // Step 1: fetch context first — we need app.billingScope to decide which subscription to load\n const [context, features] = await Promise.all([\n fetchApiRef.current<SdkContext>(SDK_ENDPOINTS.CONTEXT).catch(() => null),\n fetchApiRef.current<SdkFeaturesState>(SDK_ENDPOINTS.FEATURES).catch(() => null),\n ]);\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n // Step 2: fetch the correct subscription based on billingScope\n let subscription: SdkSubscription | null = null;\n let userSubscription: SdkSubscription | null = null;\n let userSubscriptionError: Error | null = null;\n\n if (billingScope === 'USER' && userId) {\n // User-scoped app (B2C) — only fetch user subscription\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n } else if (billingScope === 'TENANT') {\n // Tenant-scoped app (B2B) — only fetch tenant subscription\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n // userSubscription not applicable for TENANT scope\n } else {\n // billingScope unknown (app not resolved) — fetch both for backward compatibility\n subscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.SUBSCRIPTION,\n ).catch(() => null);\n if (userId) {\n try {\n userSubscription = await fetchApiRef.current<SdkSubscription>(\n SDK_ENDPOINTS.USER_SUBSCRIPTION,\n );\n } catch (err) {\n userSubscriptionError = err as Error;\n }\n }\n }\n\n setState({\n isLoading: false,\n error: null,\n context,\n features,\n subscription,\n userSubscription,\n isUserSubscriptionLoading: false,\n userSubscriptionError,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isLoading: false,\n isUserSubscriptionLoading: false,\n error: error as Error,\n }));\n }\n };\n\n fetchAll();\n }, [logtoLoading, isAuthenticated]);\n\n const contextValue: HabeetatContextValue = useMemo(\n () => ({\n ...state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getAccessToken: getToken,\n platformUrl: apiUrl,\n appName,\n appId,\n tenantSlug,\n loggerConfig: logging,\n signOut: signOutFn,\n }),\n [\n state,\n refreshContext,\n refreshFeatures,\n refreshSubscription,\n refreshUserSubscription,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n isFeatureEnabled,\n getToken,\n apiUrl,\n appName,\n appId,\n tenantSlug,\n logging,\n signOutFn,\n ],\n );\n\n // Delegate to callback handler when on the callback path\n if (isCallback) {\n return <CallbackHandler loadingFallback={loadingFallback} />;\n }\n\n // Always render context provider — never unmount children\n return (\n <HabeetatContext.Provider value={contextValue}>\n {children}\n </HabeetatContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public provider — wraps LogtoProvider so callers don't need to\n// ---------------------------------------------------------------------------\n\n/**\n * HabeetatProvider — single provider for Habeetat auth + SDK context.\n *\n * Internally wraps `LogtoProvider` from `@logto/react`, so you no longer\n * need to install or import that package in your application.\n *\n * @example\n * ```tsx\n * import { HabeetatProvider } from '@habeetat/sdk-react';\n *\n * <HabeetatProvider\n * logto={{\n * endpoint: 'https://iam.example.com',\n * appId: 'abc123',\n * resources: ['https://api.example.com/api'],\n * }}\n * platformUrl=\"https://api.example.com/sdk/v1\"\n * tenantSlug=\"acme\"\n * autoSignIn\n * callbackPath=\"/callback\"\n * >\n * <App />\n * </HabeetatProvider>\n * ```\n */\nexport function HabeetatProvider({\n logto,\n platformUrl,\n logtoResource,\n appId,\n appName,\n tenantSlug,\n autoSignIn = false,\n callbackPath = '/callback',\n loadingFallback,\n logging,\n postLogoutRedirectPath,\n children,\n}: HabeetatProviderProps) {\n const logtoConfigRef = useRef({\n endpoint: logto.endpoint,\n appId: logto.appId,\n ...(logto.resources && { resources: logto.resources }),\n ...(logto.scopes && { scopes: logto.scopes }),\n });\n const logtoConfig = logtoConfigRef.current;\n\n return (\n <LogtoProvider config={logtoConfig}>\n <HabeetatInner\n platformUrl={platformUrl}\n logtoResource={logtoResource}\n appId={appId}\n appName={appName}\n tenantSlug={tenantSlug}\n autoSignIn={autoSignIn}\n callbackPath={callbackPath}\n loadingFallback={loadingFallback}\n logging={logging}\n postLogoutRedirectPath={postLogoutRedirectPath}\n >\n {children}\n </HabeetatInner>\n </LogtoProvider>\n );\n}\n","import { useContext } from 'react';\nimport { HabeetatContext, type HabeetatContextValue } from '../context/HabeetatContext';\n\n/**\n * Hook to access Habeetat SDK context\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { context, isLoading, error } = useHabeetat();\n * \n * if (isLoading) return <Spinner />;\n * if (error) return <Error message={error.message} />;\n * \n * return <div>Hello, {context?.user.name}</div>;\n * }\n * ```\n */\nexport function useHabeetat(): HabeetatContextValue {\n const context = useContext(HabeetatContext);\n \n if (!context) {\n throw new Error('useHabeetat must be used within a HabeetatProvider');\n }\n \n return context;\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for permission checks\n * \n * @example\n * ```tsx\n * function ContactsPage() {\n * const { hasPermission, hasAnyPermission } = usePermissions();\n * \n * const canRead = hasPermission('contacts:read');\n * const canWrite = hasPermission('contacts:write');\n * const canManage = hasAnyPermission(['contacts:delete', 'contacts:admin']);\n * \n * return (\n * <div>\n * {canRead && <ContactsList />}\n * {canWrite && <AddContactButton />}\n * {canManage && <ManageContactsButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions() {\n const { context, hasPermission, hasAnyPermission, hasAllPermissions } = useHabeetat();\n \n return {\n /** All user permissions */\n permissions: context?.permissions ?? [],\n /** All user roles */\n roles: context?.roles ?? [],\n /** Check if user has a specific permission */\n hasPermission,\n /** Check if user has any of the specified permissions */\n hasAnyPermission,\n /** Check if user has all of the specified permissions */\n hasAllPermissions,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for feature flag checks\n * \n * @example\n * ```tsx\n * function DealsPage() {\n * const { isEnabled, features } = useFeatures();\n * \n * if (!isEnabled('crm.deals.enabled')) {\n * return <UpgradePrompt feature=\"Deals\" />;\n * }\n * \n * return <DealsList />;\n * }\n * ```\n */\nexport function useFeatures() {\n const { features, isFeatureEnabled, refreshFeatures } = useHabeetat();\n \n return {\n /** All feature flags */\n features: features?.features ?? {},\n /** Feature source (plan, tenant, etc.) */\n source: features?.source,\n /** Plan code if source is plan */\n planCode: features?.planCode,\n /** Check if a feature is enabled */\n isEnabled: isFeatureEnabled,\n /** Refresh features from server */\n refresh: refreshFeatures,\n };\n}\n","import { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for subscription and plan info\n */\nexport function useSubscription() {\n const { subscription, refreshSubscription } = useHabeetat();\n \n return {\n /** Current subscription */\n subscription,\n /** Current plan */\n plan: subscription?.plan,\n /** Plan limits */\n limits: subscription?.limits ?? {},\n /** Current usage */\n usage: subscription?.usage ?? {},\n /** Subscription status */\n status: subscription?.status,\n /** Check if subscription is active */\n isActive: subscription?.status === 'active' || subscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: subscription?.status === 'trial',\n /** Check limit */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = subscription?.limits?.[key];\n const current = subscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh subscription */\n refresh: refreshSubscription,\n };\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Hook for USER-scoped subscription (B2C SaaS model).\n * Returns the subscription tied to the individual user, not the tenant.\n *\n * @example\n * ```tsx\n * function SubscriptionBadge() {\n * const { plan, isLoading, error, refresh } = useUserSubscription();\n *\n * if (isLoading) return <Spinner />;\n * if (error) return <RetryButton onRetry={refresh} />;\n * return <PlanBadge plan={plan} />;\n * }\n * ```\n */\nexport function useUserSubscription() {\n const {\n userSubscription,\n context,\n refreshUserSubscription,\n isUserSubscriptionLoading,\n userSubscriptionError,\n } = useHabeetat();\n\n const userId = context?.user?.id;\n\n const refresh = useCallback(\n (appId?: string) => refreshUserSubscription(appId),\n [refreshUserSubscription],\n );\n\n return {\n /** Current user subscription */\n subscription: userSubscription,\n /** Current plan */\n plan: userSubscription?.plan,\n /** Plan limits */\n limits: userSubscription?.limits ?? {},\n /** Current usage */\n usage: userSubscription?.usage ?? {},\n /** Subscription status */\n status: userSubscription?.status,\n /** Check if subscription is active */\n isActive: userSubscription?.status === 'active' || userSubscription?.status === 'trial',\n /** Check if in trial */\n isTrialing: userSubscription?.status === 'trial',\n /** Whether the user has any subscription */\n hasSubscription: userSubscription !== null && userSubscription !== undefined,\n /** Check limit against user subscription */\n checkLimit: (key: string, increment = 0): boolean => {\n const limit = userSubscription?.limits?.[key];\n const current = userSubscription?.usage?.[key] ?? 0;\n if (limit === undefined) return true;\n return current + increment <= limit;\n },\n /** Refresh the user subscription */\n refresh,\n /** Current user ID */\n userId,\n /** Whether the user subscription is currently being fetched (initial load or refresh) */\n isLoading: isUserSubscriptionLoading,\n /** Error from the most recent fetch attempt, or null if successful */\n error: userSubscriptionError,\n };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\nimport type { SdkAvailablePlan } from '@habeetat/sdk-core';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface UsePlansReturn {\n /** Available plans for the current app */\n plans: SdkAvailablePlan[];\n /** Whether plans are being loaded */\n isLoading: boolean;\n /** Error if fetching failed */\n error: Error | null;\n /** Refetch plans from server */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to fetch available subscription plans for the current app.\n * The plans endpoint is public (no auth required).\n */\nexport function usePlans(): UsePlansReturn {\n const { platformUrl, appId } = useHabeetat();\n const [plans, setPlans] = useState<SdkAvailablePlan[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const hasFetched = useRef(false);\n\n const fetchPlans = useCallback(async () => {\n if (!platformUrl || !appId) return;\n setIsLoading(true);\n setError(null);\n try {\n const url = new URL(SDK_ENDPOINTS.PLANS(appId), platformUrl);\n const response = await fetch(url.toString());\n if (!response.ok) throw new Error(`Failed to fetch plans: ${response.status}`);\n const data = (await response.json()) as SdkAvailablePlan[];\n setPlans(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [platformUrl, appId]);\n\n useEffect(() => {\n if (hasFetched.current) return;\n hasFetched.current = true;\n fetchPlans();\n }, [fetchPlans]);\n\n const refresh = useCallback(async () => {\n hasFetched.current = false;\n await fetchPlans();\n }, [fetchPlans]);\n\n return { plans, isLoading, error, refresh };\n}\n","import { useLogto } from '@logto/react';\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n}\n\n/**\n * Returns basic Logto auth state: `{ isAuthenticated, isLoading }`.\n */\nexport function useAuth(): AuthState {\n const { isAuthenticated, isLoading } = useLogto();\n return { isAuthenticated, isLoading };\n}\n","import { useLogto } from '@logto/react';\n\n/**\n * Returns a `signIn(redirectUri)` function that initiates the Logto sign-in flow.\n * The `redirectUri` must match one of the redirect URIs registered in Logto.\n */\nexport function useSignIn(): (redirectUri: string) => Promise<void> {\n const { signIn } = useLogto();\n return signIn;\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\n\n/**\n * Returns a `signOut(postLogoutRedirectUri?)` function.\n */\nexport function useSignOut(): (postLogoutRedirectUri?: string) => Promise<void> {\n const { signOut } = useContext(HabeetatContext);\n return signOut;\n}\n","import type { LogLevel } from '@habeetat/sdk-core';\nimport { SDK_ENDPOINTS } from '@habeetat/sdk-core';\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface FrontendLoggerConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /** Minimum log level to emit (default: 'debug') */\n level?: LogLevel;\n /** Number of log records to buffer before flushing (default: 10) */\n batchSize?: number;\n /** Flush interval in milliseconds (default: 5000) */\n flushInterval?: number;\n}\n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n tenantId?: string;\n context?: Record<string, unknown>;\n timestamp: string;\n source: 'frontend';\n serviceName?: string;\n}\n\n/**\n * Frontend logging client that batches log entries and sends them\n * to the platform backend via POST /sdk/v1/logs/batch.\n *\n * This class is framework-agnostic (no React dependency).\n */\nexport class HabeetatLoggerClient {\n private buffer: LogEntry[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n private readonly minLevel: number;\n private readonly batchSize: number;\n\n constructor(\n private readonly apiUrl: string,\n private readonly getAccessToken: () => Promise<string | null>,\n private readonly defaultAttributes: {\n tenantId?: string;\n appId?: string;\n userId?: string;\n serviceName?: string;\n },\n config?: FrontendLoggerConfig,\n ) {\n this.enabled = config?.enabled ?? true;\n this.minLevel = LOG_LEVEL_PRIORITY[config?.level ?? 'debug'];\n this.batchSize = config?.batchSize ?? 10;\n\n const interval = config?.flushInterval ?? 5000;\n if (this.enabled && interval > 0) {\n this.flushTimer = setInterval(() => this.flush(), interval);\n }\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!this.enabled) return;\n if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;\n\n this.buffer.push({\n level,\n message,\n tenantId: this.defaultAttributes.tenantId,\n context: {\n ...context,\n ...(this.defaultAttributes.appId && { appId: this.defaultAttributes.appId }),\n ...(this.defaultAttributes.userId && { userId: this.defaultAttributes.userId }),\n },\n timestamp: new Date().toISOString(),\n source: 'frontend',\n serviceName: this.defaultAttributes.serviceName,\n });\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context);\n }\n\n /**\n * Flush buffered log entries to the backend.\n * Best-effort: failures are silently ignored.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const entries = this.buffer.splice(0);\n\n try {\n const token = await this.getAccessToken();\n if (!token) return;\n\n const url = `${this.apiUrl}${SDK_ENDPOINTS.LOGS_BATCH}`;\n await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ logs: entries }),\n });\n } catch {\n // Frontend logging is best-effort — silently drop on failure\n }\n }\n\n /**\n * Flush remaining logs and stop the timer.\n * Call this on component unmount.\n */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n}\n","import { useRef, useEffect, useCallback, useMemo, useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport {\n HabeetatLoggerClient,\n type FrontendLoggerConfig,\n} from '../logger/HabeetatLoggerClient';\nimport type { LogLevel } from '@habeetat/sdk-core';\n\nexport interface UseLoggerReturn {\n log: (level: LogLevel, message: string, context?: Record<string, unknown>) => void;\n debug: (message: string, context?: Record<string, unknown>) => void;\n info: (message: string, context?: Record<string, unknown>) => void;\n warn: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n flush: () => Promise<void>;\n}\n\n/**\n * React hook that provides a logger connected to the Habeetat\n * centralized logging system (SigNoz via the backend).\n *\n * Logs are automatically enriched with user, tenant, and app context\n * from the HabeetatProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const logger = useLogger();\n *\n * const handleClick = () => {\n * logger.info('Button clicked', { buttonId: 'submit' });\n * };\n * }\n * ```\n */\nexport function useLogger(config?: FrontendLoggerConfig): UseLoggerReturn {\n const {\n platformUrl,\n getAccessToken,\n context: sdkContext,\n loggerConfig,\n } = useContext(HabeetatContext);\n\n const clientRef = useRef<HabeetatLoggerClient | null>(null);\n\n // Merge provider-level config with hook-level overrides\n const mergedConfig = useMemo<FrontendLoggerConfig>(\n () => ({\n enabled: config?.enabled ?? loggerConfig?.enabled ?? true,\n level: config?.level ?? loggerConfig?.level ?? 'debug',\n batchSize: config?.batchSize,\n flushInterval: config?.flushInterval,\n }),\n [config, loggerConfig],\n );\n\n // Recreate client when dependencies change\n useEffect(() => {\n if (!platformUrl) return;\n\n clientRef.current?.destroy();\n clientRef.current = new HabeetatLoggerClient(\n platformUrl,\n getAccessToken,\n {\n tenantId: sdkContext?.tenant?.id,\n appId: sdkContext?.app?.id,\n userId: sdkContext?.user?.id,\n },\n mergedConfig,\n );\n\n return () => {\n clientRef.current?.destroy();\n clientRef.current = null;\n };\n }, [platformUrl, getAccessToken, sdkContext?.tenant?.id, sdkContext?.app?.id, sdkContext?.user?.id, mergedConfig]);\n\n const log = useCallback(\n (level: LogLevel, message: string, context?: Record<string, unknown>) => {\n clientRef.current?.log(level, message, context);\n },\n [],\n );\n\n const debug = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.debug(message, context);\n },\n [],\n );\n\n const info = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.info(message, context);\n },\n [],\n );\n\n const warn = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.warn(message, context);\n },\n [],\n );\n\n const error = useCallback(\n (message: string, context?: Record<string, unknown>) => {\n clientRef.current?.error(message, context);\n },\n [],\n );\n\n const flush = useCallback(async () => {\n await clientRef.current?.flush();\n }, []);\n\n return useMemo(\n () => ({ log, debug, info, warn, error, flush }),\n [log, debug, info, warn, error, flush],\n );\n}\n","import { useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\ninterface TrackEventInput {\n eventName: string;\n properties?: Record<string, unknown>;\n sessionId?: string;\n timestamp?: string;\n}\n\nexport interface UseAnalyticsReturn {\n track: (events: TrackEventInput | TrackEventInput[]) => Promise<void>;\n}\n\n/**\n * Hook for tracking analytics events.\n * The `appName` is injected automatically from the HabeetatProvider config.\n *\n * @example\n * ```tsx\n * const { track } = useAnalytics();\n * await track({ eventName: 'button_click', properties: { button: 'save' } });\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n const { getAccessToken, platformUrl, appName, tenantSlug } = useHabeetat();\n\n const track = useCallback(async (events: TrackEventInput | TrackEventInput[]) => {\n if (!platformUrl || !tenantSlug) return;\n\n const token = await getAccessToken();\n if (!token) return;\n\n const eventList = Array.isArray(events) ? events : [events];\n\n await fetch(`${platformUrl}/analytics/track`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n tenantId: tenantSlug,\n ...(appName && { appId: appName }),\n events: eventList,\n }),\n });\n }, [getAccessToken, platformUrl, appName, tenantSlug]);\n\n return { track };\n}\n","import { useContext } from 'react';\nimport { HabeetatContext } from '../context/HabeetatContext';\nimport type { SdkUserContext, SdkTenantContext, SdkOrganizationContext, SdkAppContext } from '@habeetat/sdk-core';\n\nexport interface UseUserReturn {\n user: SdkUserContext | null;\n tenant: SdkTenantContext | null;\n organization: SdkOrganizationContext | null;\n app: SdkAppContext | null;\n permissions: string[];\n roles: string[];\n scopes: string[];\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook that exposes the full user profile and tenant context\n * resolved by the Habeetat Platform SDK.\n *\n * All data is sourced from the already-loaded SDK context — no\n * additional network requests are made.\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { user, tenant, isLoading } = useUser();\n *\n * if (isLoading) return <Spinner />;\n *\n * return (\n * <div>\n * <img src={user?.avatarUrl ?? ''} alt=\"avatar\" />\n * <p>{user?.name}</p>\n * <p>{user?.email}</p>\n * <p>Tenant: {tenant?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n const { context, isLoading, error } = useContext(HabeetatContext);\n\n return {\n user: context?.user ?? null,\n tenant: context?.tenant ?? null,\n organization: context?.organization ?? null,\n app: context?.app ?? null,\n permissions: context?.permissions ?? [],\n roles: context?.roles ?? [],\n scopes: context?.scopes ?? [],\n isLoading,\n error,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\n/**\n * Minimal interface for an object with request interceptors.\n * Compatible with Axios, ky, and similar HTTP clients.\n */\ninterface HttpClientWithInterceptors {\n interceptors: {\n request: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use(onFulfilled: (config: any) => any, onRejected?: (error: unknown) => unknown): number;\n eject(id: number): void;\n };\n };\n}\n\n/**\n * Hook that attaches an Authorization header interceptor to an Axios instance.\n * Automatically injects the current access token from HabeetatProvider.\n *\n * Replaces manual patterns like `tokenStore`, `setAuthToken`, or `setInterval`\n * for token refresh.\n *\n * @param httpClient - The HTTP client instance (Axios or compatible) to attach the interceptor to\n *\n * @example\n * ```tsx\n * import apiClient from '@/core/http/axios.config';\n * import { useHttpInterceptor } from '@habeetat/sdk-react';\n *\n * const HttpSetup = () => {\n * useHttpInterceptor(apiClient);\n * return null;\n * };\n * ```\n */\nexport function useHttpInterceptor(httpClient: HttpClientWithInterceptors): void {\n const { getAccessToken } = useHabeetat();\n const getAccessTokenRef = useRef(getAccessToken);\n getAccessTokenRef.current = getAccessToken;\n\n useEffect(() => {\n const interceptorId = httpClient.interceptors.request.use(\n async (config: Record<string, unknown>) => {\n try {\n const token = await getAccessTokenRef.current();\n if (token) {\n const headers = (config.headers ?? {}) as Record<string, unknown>;\n headers['Authorization'] = `Bearer ${token}`;\n config.headers = headers;\n }\n } catch {\n // If token acquisition fails, let the request proceed without auth.\n // The server will return 401 and the app can handle it.\n }\n return config;\n },\n );\n\n return () => {\n httpClient.interceptors.request.eject(interceptorId);\n };\n }, [httpClient]);\n}\n","import { useState, useCallback } from 'react';\nimport { useHabeetat } from './useHabeetat';\n\nexport interface CheckoutParams {\n /** Plan ID to subscribe to */\n planId: string;\n /** Billing option ID (monthly/yearly) */\n billingOptionId: string;\n /** Whether to start a trial */\n trial?: boolean;\n /** URL to redirect to on success */\n successUrl: string;\n /** URL to redirect to on cancellation */\n cancelUrl: string;\n}\n\nexport interface UseCheckoutReturn {\n /** Start a checkout session. Redirects to Stripe on success. */\n startCheckout: (params: CheckoutParams) => Promise<void>;\n /** Whether a checkout is in progress */\n isLoading: boolean;\n /** Error from the last checkout attempt */\n error: Error | null;\n}\n\n/**\n * Hook for starting a Stripe checkout session via the Habeetat platform.\n *\n * Auto-detects billing scope from the SDK context:\n * - USER scope (B2C): calls `/users/:userId/subscriptions/checkout`\n * - TENANT scope (B2B): calls `/tenants/:tenantSlug/subscriptions/checkout`\n *\n * On success, redirects the browser to the Stripe checkout URL.\n *\n * @example\n * ```tsx\n * const { startCheckout, isLoading, error } = useCheckout();\n *\n * const handleUpgrade = () => {\n * startCheckout({\n * planId: 'plan_xxx',\n * billingOptionId: 'opt_xxx',\n * trial: false,\n * successUrl: `${window.location.origin}/billing?success=1`,\n * cancelUrl: `${window.location.origin}/billing?cancelled=1`,\n * });\n * };\n * ```\n */\nexport function useCheckout(): UseCheckoutReturn {\n const { getAccessToken, context, platformUrl, tenantSlug } = useHabeetat();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const startCheckout = useCallback(async (params: CheckoutParams) => {\n if (!platformUrl) {\n setError(new Error('Platform URL not configured'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getAccessToken();\n if (!token) throw new Error('No access token available');\n\n // Strip /sdk/v1 suffix to get base platform URL\n const baseUrl = platformUrl.replace(/\\/sdk\\/v1\\/?$/, '');\n\n const billingScope = context?.app?.billingScope;\n const userId = context?.user?.id;\n\n let url: string;\n let body: Record<string, unknown>;\n\n if (billingScope === 'TENANT' && tenantSlug) {\n url = `${baseUrl}/tenants/${encodeURIComponent(tenantSlug)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n };\n } else {\n // Default to USER scope\n if (!userId) throw new Error('User not authenticated');\n url = `${baseUrl}/users/${encodeURIComponent(userId)}/subscriptions/checkout`;\n body = {\n appId: context?.app?.id,\n planId: params.planId,\n billingOptionId: params.billingOptionId,\n trial: params.trial,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n };\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(\n (errData as Record<string, string>).message ?? `Checkout failed: ${response.status}`,\n );\n }\n\n const data = await response.json() as { checkoutUrl?: string; activated?: boolean };\n\n if (data.checkoutUrl) {\n window.location.href = data.checkoutUrl;\n }\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.0-dev.20260521144805.4f68772",
3
+ "version": "0.2.1-dev.20260606080502.37cebd8",
4
4
  "description": "Habeetat Platform SDK for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",