mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## Context Adds a "Best available region" option in the region selector for the project creation form - Should only show up for free plan organizations (will be selected as the default option instead of the recommended option from GET `/available-regions`) - "Recommended" badges will also be hidden in this scenario - Behaviour should be status quo for non free plan organizations <img width="500" alt="image" src="https://github.com/user-attachments/assets/de0a183d-37c0-445d-98ca-c5aaf6353e73" /> ## To test Important to ensure that project creation still behaves as per usual - [ ] Free plan: Creating a project with "best available region" select creates the project if the recommended region from GET `/available-regions` - A quick way to check this is to swap to a paid org and see the "recommended" general region - [ ] Free plan: Can also create a project with other regions selected as per usual - [ ] Non free plan: Can create project as per usual - [ ] Verify that everything is status quo if configcat feature flag is off
126 lines
4.3 KiB
TypeScript
126 lines
4.3 KiB
TypeScript
import type { CloudProvider, Region } from 'shared-data'
|
|
import { AWS_REGIONS } from 'shared-data'
|
|
import { SMART_REGION_TO_EXACT_REGION_MAP } from 'shared-data/regions'
|
|
|
|
import { DesiredInstanceSize, instanceSizeSpecs } from '@/data/projects/new-project.constants'
|
|
|
|
export function smartRegionToExactRegion(smartOrExactRegion: string) {
|
|
return SMART_REGION_TO_EXACT_REGION_MAP.get(smartOrExactRegion) ?? smartOrExactRegion
|
|
}
|
|
|
|
export function getAvailableRegions(
|
|
cloudProvider: CloudProvider,
|
|
environment = process.env.NEXT_PUBLIC_ENVIRONMENT
|
|
): Region {
|
|
switch (cloudProvider) {
|
|
case 'AWS':
|
|
case 'AWS_K8S':
|
|
return AWS_REGIONS
|
|
case 'AWS_NIMBUS':
|
|
if (environment !== 'prod') {
|
|
// Only allow Southeast Asia for Nimbus (local/staging)
|
|
return {
|
|
SOUTHEAST_ASIA: AWS_REGIONS.SOUTHEAST_ASIA,
|
|
}
|
|
}
|
|
|
|
// Only allow US East for Nimbus (prod)
|
|
return {
|
|
EAST_US: AWS_REGIONS.EAST_US,
|
|
}
|
|
default:
|
|
throw new Error('Invalid cloud provider')
|
|
}
|
|
}
|
|
|
|
type ResolveDefaultDbRegionArgs = {
|
|
cloudProvider: CloudProvider
|
|
isHighAvailabilityRestricted: boolean
|
|
highAvailabilityRegionName: string | undefined
|
|
isSmartRegionEnabled: boolean
|
|
recommendedSmartRegion: string | undefined
|
|
autoDefaultRegion: string | undefined
|
|
fixedDefaultRegion: string
|
|
environment?: string
|
|
}
|
|
|
|
export function resolveDefaultDbRegion({
|
|
cloudProvider,
|
|
isHighAvailabilityRestricted,
|
|
highAvailabilityRegionName,
|
|
isSmartRegionEnabled,
|
|
recommendedSmartRegion,
|
|
autoDefaultRegion,
|
|
fixedDefaultRegion,
|
|
environment = process.env.NEXT_PUBLIC_ENVIRONMENT,
|
|
}: ResolveDefaultDbRegionArgs): string | undefined {
|
|
if (isHighAvailabilityRestricted) return highAvailabilityRegionName
|
|
if (isSmartRegionEnabled) return recommendedSmartRegion
|
|
|
|
// The geolocated default is only usable if the provider actually offers that region
|
|
// (e.g. AWS_NIMBUS is restricted to a single region)
|
|
const isAutoDefaultRegionAvailable = Object.entries(
|
|
getAvailableRegions(cloudProvider, environment)
|
|
).some(([, region]) => region.displayName === autoDefaultRegion)
|
|
|
|
return isAutoDefaultRegionAvailable && autoDefaultRegion !== undefined
|
|
? autoDefaultRegion
|
|
: fixedDefaultRegion
|
|
}
|
|
|
|
type ResolveSelectedRegionOptionTypeArgs = {
|
|
isBestAvailableSelected: boolean
|
|
dbRegion: string | undefined
|
|
smartGroupRegions: Array<{ name: string }>
|
|
specificRegions: Array<{ name: string }>
|
|
}
|
|
|
|
export function resolveSelectedRegionOptionType({
|
|
isBestAvailableSelected,
|
|
dbRegion,
|
|
smartGroupRegions,
|
|
specificRegions,
|
|
}: ResolveSelectedRegionOptionTypeArgs): 'general' | 'specific' | undefined {
|
|
// The "Best available region" shortcut always resolves to a smart-group recommendation
|
|
if (isBestAvailableSelected) return 'general'
|
|
if (smartGroupRegions.some((region) => region.name === dbRegion)) return 'general'
|
|
if (specificRegions.some((region) => region.name === dbRegion)) return 'specific'
|
|
return undefined
|
|
}
|
|
|
|
/**
|
|
* When launching new projects, they only get assigned a compute size once successfully launched,
|
|
* this might assume wrong compute size, but only for projects being rapidly launched after one another on non-default compute sizes.
|
|
*
|
|
* Needs to be in the API in the future [kevin]
|
|
*/
|
|
export const monthlyInstancePrice = (instance: string | undefined): number => {
|
|
return instanceSizeSpecs[instance as DesiredInstanceSize]?.priceMonthly || 10
|
|
}
|
|
|
|
export const instanceLabel = (instance: string | undefined): string => {
|
|
return instanceSizeSpecs[instance as DesiredInstanceSize]?.label || 'Micro'
|
|
}
|
|
|
|
export const getHighAvailabilityRegionCode = (
|
|
environment = process.env.NEXT_PUBLIC_ENVIRONMENT
|
|
) => {
|
|
// Local dev stacks can run in any of the supported regions, so they're left unrestricted
|
|
if (environment === 'prod') return 'us-east-1'
|
|
if (environment === 'staging') return 'us-east-1'
|
|
if (environment === 'local') return 'eu-central-1'
|
|
return undefined
|
|
}
|
|
|
|
export const filterHighAvailabilityRegions = <T extends { code: string }>(
|
|
regions: T[],
|
|
highAvailability: boolean,
|
|
environment = process.env.NEXT_PUBLIC_ENVIRONMENT
|
|
) => {
|
|
const isLocal = environment === 'local'
|
|
const regionCode = getHighAvailabilityRegionCode(environment)
|
|
return highAvailability && !isLocal && regionCode !== undefined
|
|
? regions.filter((region) => region.code === regionCode)
|
|
: regions
|
|
}
|