StorageSettings.utils.ts97 lines · main
| 1 | import { StorageSizeUnits } from './StorageSettings.constants' |
| 2 | |
| 3 | const k = 1024 |
| 4 | |
| 5 | export const BUCKET_LIMIT_ERROR_PREFIX = 'bucketLimit:' |
| 6 | |
| 7 | type BucketLimitErrorBucket = { name: string; limit: number } |
| 8 | |
| 9 | export const convertFromBytes = (bytes: number, unit?: StorageSizeUnits) => { |
| 10 | // Up to GB since that's our storage upload limit |
| 11 | if (bytes <= 0) return { value: 0, unit: StorageSizeUnits.BYTES } |
| 12 | |
| 13 | const i = |
| 14 | unit !== undefined |
| 15 | ? Object.values(StorageSizeUnits).indexOf(unit) |
| 16 | : Math.floor(Math.log(bytes) / Math.log(k)) |
| 17 | |
| 18 | const formattedIdx = unit !== undefined ? (i < 0 ? 0 : i) : i > 3 ? 3 : i |
| 19 | |
| 20 | const formattedUnit = Object.values(StorageSizeUnits)[formattedIdx] |
| 21 | const value = bytes / Math.pow(k, formattedIdx) |
| 22 | return { value, unit: formattedUnit } |
| 23 | } |
| 24 | |
| 25 | export const convertToBytes = (size: number, unit: StorageSizeUnits = StorageSizeUnits.BYTES) => { |
| 26 | const i = Object.values(StorageSizeUnits).indexOf(unit) |
| 27 | if (size < 0 || i < 0) return 0 |
| 28 | |
| 29 | return size * Math.pow(k, i) |
| 30 | } |
| 31 | |
| 32 | function getStorageURL(projectRef: string, protocol: string, endpoint?: string) { |
| 33 | const projUrl = endpoint |
| 34 | ? `${protocol}://${endpoint}` |
| 35 | : `https://${projectRef}.storage.supabase.co` |
| 36 | const url = new URL(projUrl) |
| 37 | return url |
| 38 | } |
| 39 | |
| 40 | export function getConnectionURL(projectRef: string, protocol: string, endpoint?: string) { |
| 41 | const url = getStorageURL(projectRef, protocol, endpoint) |
| 42 | url.pathname = '/storage/v1/s3' |
| 43 | return url.toString() |
| 44 | } |
| 45 | |
| 46 | export function getCatalogURI(projectRef: string, protocol: string, endpoint?: string) { |
| 47 | const url = getStorageURL(projectRef, protocol, endpoint) |
| 48 | url.pathname = '/storage/v1/iceberg' |
| 49 | return url.toString() |
| 50 | } |
| 51 | |
| 52 | export function getVectorURI(projectRef: string, protocol: string, endpoint?: string) { |
| 53 | const url = getStorageURL(projectRef, protocol, endpoint) |
| 54 | url.pathname = '/storage/v1/vector' |
| 55 | return url.toString() |
| 56 | } |
| 57 | |
| 58 | export const formatBytesForDisplay = (bytes: number) => { |
| 59 | const { value, unit } = convertFromBytes(bytes) |
| 60 | return `${value.toLocaleString(undefined, { maximumFractionDigits: 2 })} ${unit}` |
| 61 | } |
| 62 | |
| 63 | export const encodeBucketLimitErrorMessage = (buckets: BucketLimitErrorBucket[]) => { |
| 64 | const encodedBuckets = buckets |
| 65 | .map(({ name, limit }) => `${encodeURIComponent(name)}|${limit}`) |
| 66 | .join(',') |
| 67 | return `${BUCKET_LIMIT_ERROR_PREFIX}${encodedBuckets}` |
| 68 | } |
| 69 | |
| 70 | export const isBucketLimitErrorMessage = (message?: string) => { |
| 71 | return message?.startsWith(BUCKET_LIMIT_ERROR_PREFIX) |
| 72 | } |
| 73 | |
| 74 | export const decodeBucketLimitErrorMessage = (message?: string): BucketLimitErrorBucket[] => { |
| 75 | if (!isBucketLimitErrorMessage(message)) return [] |
| 76 | |
| 77 | const payload = message?.slice(BUCKET_LIMIT_ERROR_PREFIX.length) ?? '' |
| 78 | if (payload.length === 0) return [] |
| 79 | |
| 80 | return payload |
| 81 | .split(',') |
| 82 | .filter(Boolean) |
| 83 | .map((entry) => { |
| 84 | const parts = entry.split('|') |
| 85 | if (parts.length !== 2) return undefined |
| 86 | |
| 87 | const name = decodeURIComponent(parts[0]) |
| 88 | if (!name) return undefined |
| 89 | |
| 90 | const limitString = parts[1] |
| 91 | const limit = Number(limitString ?? 0) |
| 92 | if (Number.isNaN(limit)) return undefined |
| 93 | |
| 94 | return { name, limit } |
| 95 | }) |
| 96 | .filter((entry) => entry !== undefined) |
| 97 | } |