( userId: string, prefetchedSub?: HighestPrioritySubscription | null )
| 89 | * (leave `undefined`) to fetch it here. |
| 90 | */ |
| 91 | export async function getUserStorageLimit( |
| 92 | userId: string, |
| 93 | prefetchedSub?: HighestPrioritySubscription | null |
| 94 | ): Promise<number> { |
| 95 | try { |
| 96 | const sub = prefetchedSub === undefined ? await resolveSub(userId) : prefetchedSub |
| 97 | |
| 98 | const limits = getStorageLimits() |
| 99 | |
| 100 | if (!sub || isFree(sub.plan)) { |
| 101 | return limits.free |
| 102 | } |
| 103 | |
| 104 | if (isOrgScopedSubscription(sub, userId)) { |
| 105 | const metadata = sub.metadata as { customStorageLimitGB?: number } | null |
| 106 | if (metadata?.customStorageLimitGB) { |
| 107 | return metadata.customStorageLimitGB * 1024 * 1024 * 1024 |
| 108 | } |
| 109 | return isEnterprise(sub.plan) ? limits.enterpriseDefault : limits.team |
| 110 | } |
| 111 | |
| 112 | // Personally-scoped plans use the per-plan default storage cap. |
| 113 | const effectivePlan = getPlanTypeForLimits(sub.plan) |
| 114 | const limitByPlan: Record<'free' | 'pro' | 'team', number> = { |
| 115 | free: limits.free, |
| 116 | pro: limits.pro, |
| 117 | team: limits.team, |
| 118 | } |
| 119 | return limitByPlan[effectivePlan as 'free' | 'pro' | 'team'] ?? limits.free |
| 120 | } catch (error) { |
| 121 | logger.error('Error getting user storage limit:', error) |
| 122 | return getStorageLimits().free |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Get current storage usage for a user. Returns usage in bytes. |
no test coverage detected