mirror of
https://github.com/supabase/supabase.git
synced 2026-09-06 09:59:03 +08:00
## Problem Workers with an omitted runtime are displayed as Unknown, even though an omitted runtime represents a custom worker image. ## Fix Display Custom when the runtime is omitted. Preserve friendly labels for known runtimes and raw values for explicit unrecognized runtimes. ## How to test - Run `node_modules/.bin/vitest --run components/interfaces/Workers/Workers.utils.test.ts` from `apps/studio`. - Open a worker whose API response omits `spec.runtime`. - Expected result: the runtime badge displays Custom. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Worker runtimes without available metadata are now labeled **“Custom”** instead of **“Unknown.”** - Updated the related behavior validation to reflect the corrected runtime label. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
71 lines
2.8 KiB
TypeScript
71 lines
2.8 KiB
TypeScript
import { RUNTIMES, WORKER_NAME_WORDS, type RuntimeMeta } from './Workers.constants'
|
|
import type { Worker, WorkerAccess, WorkerBuildState } from './Workers.types'
|
|
import { ResponseError } from '@/types'
|
|
|
|
export interface WorkerFilters {
|
|
search: string
|
|
state: WorkerBuildState | 'all'
|
|
access: WorkerAccess | 'all'
|
|
}
|
|
|
|
export const filterWorkers = (workers: Worker[], filters: WorkerFilters): Worker[] => {
|
|
const search = filters.search.trim().toLowerCase()
|
|
return workers.filter((worker) => {
|
|
const matchesSearch = worker.name.toLowerCase().includes(search)
|
|
const matchesState = filters.state === 'all' || worker.buildState === filters.state
|
|
const matchesAccess = filters.access === 'all' || worker.access === filters.access
|
|
return matchesSearch && matchesState && matchesAccess
|
|
})
|
|
}
|
|
|
|
export interface Page<T> {
|
|
items: T[]
|
|
currentPage: number
|
|
totalPages: number
|
|
startIndex: number
|
|
}
|
|
|
|
// Clamps the requested page so filtering down to fewer results never strands an empty page.
|
|
export const getPage = <T>(items: T[], requestedPage: number, pageSize: number): Page<T> => {
|
|
const totalPages = Math.max(1, Math.ceil(items.length / pageSize))
|
|
const currentPage = Math.min(Math.max(1, requestedPage), totalPages)
|
|
const startIndex = (currentPage - 1) * pageSize
|
|
return {
|
|
items: items.slice(startIndex, startIndex + pageSize),
|
|
currentPage,
|
|
totalPages,
|
|
startIndex,
|
|
}
|
|
}
|
|
|
|
export const getRuntimeMeta = (runtime: string | undefined): RuntimeMeta | undefined =>
|
|
runtime === undefined ? undefined : RUNTIMES[runtime]
|
|
|
|
export const formatRuntime = (runtime: string | undefined): string =>
|
|
getRuntimeMeta(runtime)?.label ?? runtime ?? 'Custom'
|
|
|
|
// The API reports size as e.g. "2gb-1vcpu"; render the parts when they parse, the raw value if not.
|
|
export const formatSize = (size: string): string => {
|
|
const match = size.match(/^(\d+)gb-(\d+)vcpu$/)
|
|
if (!match) return size
|
|
return `${match[1]} GB · ${match[2]} vCPU`
|
|
}
|
|
|
|
export const formatResources = (worker: Worker): string =>
|
|
`${formatSize(worker.size)} · ${worker.declaredInstances} inst`
|
|
|
|
// Suggests a friendly, already-valid starting name so the deploy dialog isn't blank.
|
|
export const generateWorkerName = (): string => {
|
|
const word = WORKER_NAME_WORDS[Math.floor(Math.random() * WORKER_NAME_WORDS.length)]
|
|
const number = Math.floor(Math.random() * 900000) + 100000
|
|
return `worker-${word}-${number}`
|
|
}
|
|
|
|
// A project outside the alpha allow-list gets a 404, not a 403.
|
|
export const isWorkersUnavailable = (error: Error | null): boolean =>
|
|
error instanceof ResponseError && error.code === 404
|
|
|
|
// An enrolled project still answers 403 when the caller lacks the workers permission.
|
|
export const isWorkersForbidden = (error: Error | null): boolean =>
|
|
error instanceof ResponseError && error.code === 403
|