export interface DocumentUsage { rowCount?: RowCounts; dataSizeBytes?: number; attachmentsSizeBytes?: number; } export interface RowCounts { total: number; [tableRef: number]: number; } export type DataLimitStatus = 'approachingLimit' | 'gracePeriod' | 'deleteOnly' | null; type DocUsageOrPending = { [Metric in keyof Required]: Required[Metric] | 'pending' } export interface DocUsageSummary extends DocUsageOrPending { dataLimitStatus: DataLimitStatus; } // Count of non-removed documents in an org, grouped by data limit status. export type OrgUsageSummary = Record, number>; type FilteredDocUsage = { [Metric in keyof DocUsageOrPending]: DocUsageOrPending[Metric] | 'hidden' } export interface FilteredDocUsageSummary extends FilteredDocUsage { dataLimitStatus: DataLimitStatus; } // Ratio of usage at which we start telling users that they're approaching limits. export const APPROACHING_LIMIT_RATIO = 0.9; /** * Computes a ratio of `usage` to `limit`, if possible. Returns 0 if `usage` or `limit` * is invalid or undefined. */ export function getUsageRatio(usage: number | undefined, limit: number | undefined): number { if (!isEnforceableLimit(limit) || usage === undefined || usage < 0) { // Treat undefined or invalid values as having 0 usage. return 0; } return usage / limit; } /** * Returns an empty org usage summary with values initialized to 0. */ export function createEmptyOrgUsageSummary(): OrgUsageSummary { return { approachingLimit: 0, gracePeriod: 0, deleteOnly: 0, }; } /** * Returns true if `limit` is defined and is a valid, positive number. */ function isEnforceableLimit(limit: number | undefined): limit is number { return limit !== undefined && limit > 0; }