Files
supabase/apps/studio/components/interfaces/ProjectCreation/ProjectCreation.utils.ts
Saxon Fletcher d2a3162bf1 Add high availability project creation controls (#48375)
## Summary

- Move High Availability into the standard project creation settings
above Compute, gated by the `instances.high_availability` entitlement.
- Mark the option as Alpha and explain that it is free during Alpha for
up to two projects.
- Enforce the supported HA configuration: `AWS_K8S`, Postgres 17 on the
`ga` release channel (no custom version is sent — the API resolves the
image), and the environment-specific local/staging region restrictions.
- Show eligible locations in a dedicated **High Availability Regions**
group.
- Preserve the existing Advanced Configuration availability rules and
additionally hide the section while HA is enabled.
- Restore the previous provider and Postgres settings when HA is
switched off.

## How to test
1. Go to create a new project
2. Ensure you have access to high availability (e.g. on local)
3. Toggle high availability on and note how the project form restricts
settings listed above

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added High Availability to project creation with Alpha warning
labeling and improved switch accessibility.
* Constrains region selection to compatible High Availability regions
and enforces HA-specific engine/release settings.
* Disables/hides custom PostgreSQL version selection when High
Availability is enabled (and omits HA custom request payloads).

* **Bug Fixes**
* Improved persistence of selected PostgreSQL version and region across
data reloads and configuration panel reopen/toggle.
* Restores region when form state temporarily drops values during
remounts.

* **Tests**
* Expanded end-to-end coverage for HA UI, region grouping, and
submit/payload restoration behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-30 16:36:54 +08:00

67 lines
2.2 KiB
TypeScript

import type { CloudProvider, Region } from 'shared-data'
import { AWS_REGIONS, FLY_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): Region {
switch (cloudProvider) {
case 'AWS':
case 'AWS_K8S':
return AWS_REGIONS
case 'AWS_NIMBUS':
if (process.env.NEXT_PUBLIC_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,
}
case 'FLY':
return FLY_REGIONS
default:
throw new Error('Invalid cloud provider')
}
}
/**
* 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
) => {
if (environment === 'local') return 'eu-central-1'
if (environment === 'staging') return 'us-east-1'
return undefined
}
export const filterHighAvailabilityRegions = <T extends { code: string }>(
regions: T[],
highAvailability: boolean,
environment = process.env.NEXT_PUBLIC_ENVIRONMENT
) => {
const regionCode = getHighAvailabilityRegionCode(environment)
return highAvailability && regionCode !== undefined
? regions.filter((region) => region.code === regionCode)
: regions
}