mirror of
https://github.com/supabase/supabase.git
synced 2026-09-06 09:59:03 +08:00
## What
The Workers list page at `/project/[ref]/workers`, behind
`useFlag('workers')`. Reads `GET /v2/projects/{ref}/workers`.
- Sidebar and command-menu entries, both hidden when the flag is off
- Name search, state and access filters, pagination
- Read-only
Gating, in order: flag off redirects to the project home; a 404 from the
API means the project is outside the alpha allow-list ("not enabled for
this project"); a 403 means the caller lacks the permission
(`NoPermission`); anything else is an `AlertError`.
`parseWorker` in `data/workers/workers.utils.ts` is the only place the
API shape becomes the view model. It validates with zod, so a drifted
response fails the query instead of half-rendering a row.
## How to test
Only on the **Mockamaster** project in staging — it is the one project
in the alpha allow-list, and standing a worker up anywhere else is
involved right now.
1. Staging dashboard → Mockamaster → **Compute** in the sidebar
2. Expect the `dashboard-test` worker: state `Active`, runtime Deno,
private, US West, 2 GB · 1 vCPU · 1 inst
3. Open any other project's `/workers` URL → "Compute is not enabled for
this project"
4. Turn the `workers` flag off → the sidebar entry disappears and the
URL redirects to the project home
Closes FE-4188
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
import type { Worker, WorkerBuildState } from '@/components/interfaces/Workers/Workers.types'
|
|
|
|
const BUILD_STATES = ['building', 'active', 'failed'] as const satisfies readonly WorkerBuildState[]
|
|
|
|
const WorkerResponseSchema = z.object({
|
|
id: z.string(),
|
|
attributes: z.object({
|
|
build_state: z.enum(BUILD_STATES).catch('failed'),
|
|
deleting: z.boolean().optional(),
|
|
image_version: z.string().optional(),
|
|
instances: z
|
|
.object({
|
|
declared: z.number(),
|
|
live: z.number(),
|
|
ready: z.number(),
|
|
stale: z.number(),
|
|
})
|
|
.optional(),
|
|
instances_error: z.string().optional(),
|
|
spec: z.object({
|
|
exposure: z.string(),
|
|
instances: z.number(),
|
|
runtime: z.string().optional(),
|
|
size: z.string(),
|
|
}),
|
|
state_reason: z.string().optional(),
|
|
}),
|
|
})
|
|
|
|
export const parseWorker = (datum: unknown): Worker => {
|
|
const { id, attributes } = WorkerResponseSchema.parse(datum)
|
|
return {
|
|
name: id,
|
|
buildState: attributes.build_state,
|
|
isDeleting: attributes.deleting ?? false,
|
|
runtime: attributes.spec.runtime,
|
|
size: attributes.spec.size,
|
|
access: attributes.spec.exposure === 'public' ? 'public' : 'private',
|
|
declaredInstances: attributes.spec.instances,
|
|
instances: attributes.instances,
|
|
imageVersion: attributes.image_version,
|
|
stateReason: attributes.state_reason,
|
|
instancesError: attributes.instances_error,
|
|
}
|
|
}
|