New token arch

This commit is contained in:
Urtzi Alfaro
2026-01-10 21:45:37 +01:00
parent cc53037552
commit bf1db7cb9e
26 changed files with 1751 additions and 107 deletions

View File

@@ -10,7 +10,7 @@ import {
SubscriptionTier
} from '../types/subscription';
import { useCurrentTenant } from '../../stores';
import { useAuthUser } from '../../stores/auth.store';
import { useAuthUser, useJWTSubscription } from '../../stores/auth.store';
import { useSubscriptionEvents } from '../../contexts/SubscriptionEventsContext';
export interface SubscriptionFeature {
@@ -53,15 +53,42 @@ export const useSubscription = () => {
retry: 1,
});
// Get JWT subscription data for instant rendering
const jwtSubscription = useJWTSubscription();
// Derive subscription info from query data or tenant fallback
// IMPORTANT: Memoize to prevent infinite re-renders in dependent hooks
const subscriptionInfo: SubscriptionInfo = useMemo(() => ({
plan: usageSummary?.plan || initialPlan,
status: usageSummary?.status || 'active',
features: usageSummary?.usage || {},
loading: isLoading,
error: error ? 'Failed to load subscription data' : undefined,
}), [usageSummary?.plan, usageSummary?.status, usageSummary?.usage, initialPlan, isLoading, error]);
const subscriptionInfo: SubscriptionInfo = useMemo(() => {
// If we have fresh API data (from loadSubscriptionData), use it
// This handles the case where token refresh failed but API call succeeded
const apiPlan = usageSummary?.plan;
const jwtPlan = jwtSubscription?.tier;
// Prefer API data if available and more recent
// Ensure status is compatible with SubscriptionInfo interface
const rawStatus = usageSummary?.status || jwtSubscription?.status || 'active';
const status = (() => {
switch (rawStatus) {
case 'active':
case 'inactive':
case 'past_due':
case 'cancelled':
case 'trialing':
return rawStatus;
default:
return 'active';
}
})();
return {
plan: apiPlan || jwtPlan || initialPlan,
status: status,
features: usageSummary?.usage || {},
loading: isLoading && !apiPlan && !jwtPlan,
error: error ? 'Failed to load subscription data' : undefined,
fromJWT: !apiPlan && !!jwtPlan,
};
}, [jwtSubscription, usageSummary?.plan, usageSummary?.status, usageSummary?.usage, initialPlan, isLoading, error]);
// Check if user has a specific feature
const hasFeature = useCallback(async (featureName: string): Promise<SubscriptionFeature> => {

View File

@@ -69,6 +69,9 @@ export interface DemoSessionResponse {
expires_at: string; // ISO datetime
demo_config: Record<string, any>;
session_token: string;
subscription_tier: string; // NEW: Subscription tier from demo session
is_enterprise: boolean; // NEW: Whether this is an enterprise demo
tenant_name: string; // NEW: Tenant name for display
}
/**