import { createMemo, createSignal, For, Show, onMount, type Component } from "solid-js" import { Globe, Loader2, Plus, Trash2 } from "lucide-solid" import { useI18n } from "../../lib/i18n" import { serverApi } from "../../lib/api-client" import { ensureSidecarsLoaded, sidecars, sidecarsLoading } from "../../stores/sidecars" function deriveSidecarId(value: string): string { return value .trim() .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/-{2,}/g, "-") .replace(/^-|-$/g, "") } export const SideCarsSettingsSection: Component = () => { const { t } = useI18n() const [name, setName] = createSignal("") const [port, setPort] = createSignal("3000") const [insecure, setInsecure] = createSignal(false) const [prefixMode, setPrefixMode] = createSignal<"strip" | "preserve">("strip") const [busyId, setBusyId] = createSignal(null) const [creating, setCreating] = createSignal(false) const [formError, setFormError] = createSignal(null) const [actionError, setActionError] = createSignal(null) onMount(() => { void ensureSidecarsLoaded() }) const orderedSidecars = createMemo(() => Array.from(sidecars().values()).sort((a, b) => a.name.localeCompare(b.name))) const derivedId = createMemo(() => deriveSidecarId(name()) || "your-sidecar") async function handleCreate() { const trimmedName = name().trim() const nextPort = Number(port()) if (!trimmedName || !Number.isInteger(nextPort) || nextPort <= 0 || nextPort > 65535) { setFormError(t("sidecars.form.validation")) return } setCreating(true) setFormError(null) try { await serverApi.createSidecar({ kind: "port", name: trimmedName, port: nextPort, insecure: insecure(), prefixMode: prefixMode(), }) setName("") setPort("3000") setInsecure(false) setPrefixMode("strip") } catch (error) { setFormError(error instanceof Error ? error.message : String(error)) } finally { setCreating(false) } } async function handleDelete(id: string) { setBusyId(id) setActionError(null) try { await serverApi.deleteSidecar(id) } catch (error) { setActionError(error instanceof Error ? error.message : String(error)) } finally { setBusyId(null) } } return (

{t("settings.section.sidecars.title")}

{t("settings.section.sidecars.subtitle")}

{t("settings.scope.server")}
{t("sidecars.form.name")}
{t("sidecars.basePath")}: /sidecars/{derivedId()}
{ setFormError(null) setName(event.currentTarget.value) }} />
{t("sidecars.form.port")}
127.0.0.1
{ setFormError(null) setPort(event.currentTarget.value) }} inputMode="numeric" />
{t("sidecars.form.protocol")}
{t("sidecars.form.protocol.help")}
{t("sidecars.form.prefixMode")}
{t("sidecars.form.prefixMode.help")}
{formError()}

{t("sidecars.settings.listTitle")}

{t("sidecars.settings.listSubtitle")}

{actionError()}
{t("sidecars.picker.loading")}
}> 0} fallback={
{t("sidecars.settings.empty")}
}> {(sidecar) => (
{sidecar.name}
{t("sidecars.kind.port")} · {sidecar.insecure ? "http" : "https"}://127.0.0.1:{sidecar.port}
{t("sidecars.basePath")}: /sidecars/{sidecar.id} · {t(`sidecars.form.prefixMode.${sidecar.prefixMode}`)}
{t(`sidecars.status.${sidecar.status}`)}
)}
) }