( userId: string, prefetchedSub?: HighestPrioritySubscription | null )
| 130 | * to skip the `getHighestPrioritySubscription` lookup on hot paths. |
| 131 | */ |
| 132 | export async function getUserStorageUsage( |
| 133 | userId: string, |
| 134 | prefetchedSub?: HighestPrioritySubscription | null |
| 135 | ): Promise<number> { |
| 136 | try { |
| 137 | const sub = prefetchedSub === undefined ? await resolveSub(userId) : prefetchedSub |
| 138 | |
| 139 | // Org-scoped subs share pooled `organization.storageUsedBytes`; |
| 140 | // personal plans use `userStats`. |
| 141 | if (isOrgScopedSubscription(sub, userId) && sub) { |
| 142 | const orgRecord = await db |
| 143 | .select({ storageUsedBytes: organization.storageUsedBytes }) |
| 144 | .from(organization) |
| 145 | .where(eq(organization.id, sub.referenceId)) |
| 146 | .limit(1) |
| 147 | |
| 148 | return orgRecord.length > 0 ? orgRecord[0].storageUsedBytes || 0 : 0 |
| 149 | } |
| 150 | |
| 151 | const stats = await db |
| 152 | .select({ storageUsedBytes: userStats.storageUsedBytes }) |
| 153 | .from(userStats) |
| 154 | .where(eq(userStats.userId, userId)) |
| 155 | .limit(1) |
| 156 | |
| 157 | return stats.length > 0 ? stats[0].storageUsedBytes || 0 : 0 |
| 158 | } catch (error) { |
| 159 | logger.error('Error getting user storage usage:', error) |
| 160 | return 0 |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | /** |
| 165 | * Check if user has storage quota available |
no test coverage detected