import {z} from 'zod' export type GetApiV0RegionsOptions = {baseUrl: string, fetch?: typeof fetch | undefined}; export const cloudProvider = z.enum(["aws", "gcp", "azure", "ovh"]); export const awsRegion = z.enum(["af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-south-2", "ap-southeast-2", "ap-southeast-3", "ap-southeast-4", "ap-southeast-5", "ap-southeast-7", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2", "eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", "il-central-1", "me-central-1", "mx-central-1", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2"]); export const gcpRegion = z.enum(["asia-east1", "asia-northeast1", "asia-southeast1", "europe-north1", "europe-west1", "europe-west3", "europe-west4", "northamerica-northeast2", "southamerica-west1", "us-central1", "us-east1", "us-east4", "us-west1", "us-west2"]); export const azureRegion = z.enum(["australiacentral", "australiaeast", "australiasoutheast", "brazilsouth", "canadacentral", "canadaeast", "centralindia", "centralus", "chinaeast2", "chinanorth", "chinanorth2", "chinanorth3", "eastasia", "eastus", "eastus2", "francecentral", "germanywestcentral", "indonesiacentral", "israelcentral", "italynorth", "japaneast", "japanwest", "koreacentral", "mexicocentral", "newzealandnorth", "northcentralus", "northeurope", "norwayeast", "polandcentral", "southafricanorth", "southcentralus", "southindia", "spaincentral", "swedencentral", "switzerlandnorth", "uaenorth", "uksouth", "ukwest", "westcentralus", "westeurope", "westus", "westus2", "westus3"]); export const ovhRegion = z.enum(["fr-strasbourg", "pl-warsaw"]); export const cloudZone = z.object({provider: cloudProvider, region: z.union([awsRegion, gcpRegion, azureRegion, ovhRegion])}); export const regionResponse = z.object({regions: z.array(cloudZone)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Regions * * GET /v0/regions/ */ export const getApiV0Regions = async (options: GetApiV0RegionsOptions) => { const {baseUrl, fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v0/regions/${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(regionResponse, await res.json()) };