Files
wild-pc/app/src/lib/labels.ts
Paul Payne 05b28cb584 Rename Castle -> Wild PC across the repo
Repo-side rename only (Phases 1-3 of the migration plan); the live box
(~/.castle, systemd units, /data/castle, domains) is a separate cutover.

- Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api),
  dist names, entry point `wildpc = wildpc_cli.main:main`.
- Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*.
- Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml ->
  wildpc.yaml, /data/castle -> /data/wildpc.
- Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc.
- Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend.
- Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated;
  redundant nested uv.lock files dropped (workspace root lock is authoritative).

Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds.
Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
2026-07-18 22:55:08 -07:00

110 lines
3.7 KiB
TypeScript

import type { LucideIcon } from "lucide-react"
import { Box, Clock, LayoutTemplate, Server, SquareCode, Waypoints, Wrench } from "lucide-react"
// Canonical kind → icon — the single source of truth so the nav, Overview tiles,
// cards, the System map, and the command palette all speak one visual language.
// (Colors live in KindBadge; labels/descriptions are below.) `program` is the
// catalog pseudo-kind, not a deployment kind — the SquareCode glyph the Programs
// nav entry and Overview tile use.
export const KIND_ICONS: Record<string, LucideIcon> = {
service: Server,
job: Clock,
tool: Wrench,
static: LayoutTemplate,
reference: Waypoints,
program: SquareCode,
}
export function kindIcon(kind: string): LucideIcon {
return KIND_ICONS[kind] ?? Box
}
export const LAUNCHER_LABELS: Record<string, string> = {
python: "Python",
command: "Command",
container: "Container",
compose: "Compose",
node: "Node.js",
}
// Derived deployment kinds (service | job | tool | static | reference).
export const KIND_LABELS: Record<string, string> = {
service: "Service",
job: "Job",
tool: "Tool",
static: "Static",
reference: "Reference",
}
export const KIND_DESCRIPTIONS: Record<string, string> = {
service: "Long-running process (systemd)",
job: "Scheduled task (timer)",
tool: "CLI installed on PATH",
static: "Static site served by the gateway",
reference: "External service on another node",
}
export const STACK_LABELS: Record<string, string> = {
"python-fastapi": "Python / FastAPI",
"python-cli": "Python / CLI",
"react-vite": "React / Vite",
supabase: "Supabase",
rust: "Rust",
go: "Go",
bash: "Bash",
container: "Container",
command: "Command",
remote: "Remote",
}
export function launcherLabel(launcher: string): string {
return LAUNCHER_LABELS[launcher] ?? launcher
}
export function kindLabel(kind: string): string {
return KIND_LABELS[kind] ?? kind
}
export function stackLabel(stack: string): string {
return STACK_LABELS[stack] ?? stack
}
/**
* The kind-scoped detail route for a deployment. A name can be shared across
* kinds (a `backup` service + job + tool), so links must carry the kind to
* reach the right twin. Statics share the service detail page.
*/
export function detailPath(name: string, kind: string): string {
if (kind === "tool") return `/tools/${name}`
if (kind === "job") return `/jobs/${name}`
return `/services/${name}`
}
/**
* Full URL for a service exposed at <subdomain>.<gateway.domain>. The domain is
* derived from the dashboard's own host (it is served at wildpc.<domain>), so
* this returns null when the dashboard is on a bare host (off mode, no subdomains).
*/
export function subdomainUrl(subdomain: string): string | null {
if (typeof window === "undefined") return null
const { protocol, hostname } = window.location
const labels = hostname.split(".")
if (labels.length <= 2) return null
return `${protocol}//${subdomain}.${labels.slice(1).join(".")}`
}
/**
* The concrete host a subdomain is exposed at — `<subdomain>.<domain>` — using
* this node's configured gateway domain. Falls back to the literal
* `<subdomain>.<gateway.domain>` placeholder only when no domain is configured
* (off mode), so hints and previews show real values wherever one exists.
*/
export function gatewayHost(subdomain: string, domain?: string | null): string {
return domain ? `${subdomain}.${domain}` : `${subdomain}.<gateway.domain>`
}
/** Same as {@link gatewayHost}, for the public (Cloudflare tunnel) zone. */
export function publicGatewayHost(subdomain: string, publicDomain?: string | null): string {
return publicDomain ? `${subdomain}.${publicDomain}` : `${subdomain}.<gateway.public_domain>`
}