Phase2
Some checks failed
CI / Node — lint, typecheck, test, build (push) Failing after 10s
CI / Go — node-agent tests (push) Failing after 8s
CI / Go — edge-gateway build (push) Successful in 13s

This commit is contained in:
smueller
2026-06-26 12:01:25 +02:00
parent 58961000eb
commit c4077d4673
93 changed files with 4099 additions and 165 deletions

View File

@@ -0,0 +1,104 @@
import { apiFetch } from "./auth";
export type GameServerStatus =
| "DRAFT"
| "PROVISIONING"
| "INSTALLING"
| "STOPPED"
| "STARTING"
| "RUNNING"
| "STOPPING"
| "ERROR"
| "DELETING"
| "DELETED";
export type SoftwareFamily =
| "VANILLA"
| "PAPER"
| "PURPUR"
| "FABRIC"
| "FORGE"
| "NEOFORGE"
| "QUILT"
| "BEDROCK_DEDICATED";
export interface Server {
id: string;
userId: string;
planId: string | null;
nodeId: string | null;
name: string;
status: GameServerStatus;
version: number;
edition: "JAVA" | "BEDROCK";
softwareFamily: SoftwareFamily;
minecraftVersion: string;
eulaAccepted: boolean;
hostPort: number | null;
containerId: string | null;
dataPath: string | null;
ramMb: number;
createdAt: string;
updatedAt: string;
}
export interface ServerListResponse {
servers: Server[];
}
export interface ServerActionResponse {
server: Server;
jobId?: string;
}
export interface CreateServerPayload {
name: string;
planId?: string;
minecraftVersion: string;
softwareFamily: SoftwareFamily;
eulaAccepted: true;
}
export interface Plan {
id: string;
name: string;
slug: string;
description: string | null;
isFree: boolean;
maxRamMb: number;
}
export interface PlanListResponse {
plans: Plan[];
}
export async function listServers(): Promise<ServerListResponse> {
return apiFetch<ServerListResponse>("/servers");
}
export async function getServer(id: string): Promise<Server> {
return apiFetch<Server>(`/servers/${id}`);
}
export async function createServer(payload: CreateServerPayload): Promise<Server> {
return apiFetch<Server>("/servers", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function startServer(id: string): Promise<ServerActionResponse> {
return apiFetch<ServerActionResponse>(`/servers/${id}/start`, {
method: "POST",
});
}
export async function stopServer(id: string): Promise<ServerActionResponse> {
return apiFetch<ServerActionResponse>(`/servers/${id}/stop`, {
method: "POST",
});
}
export async function listPlans(): Promise<PlanListResponse> {
return apiFetch<PlanListResponse>("/plans");
}

View File

@@ -0,0 +1,46 @@
import { z } from "zod";
const softwareFamilyValues = [
"VANILLA",
"PAPER",
"PURPUR",
"FABRIC",
"FORGE",
"NEOFORGE",
"QUILT",
"BEDROCK_DEDICATED",
] as const;
export function createServerSchema(messages: {
nameRequired: string;
nameMax: string;
planRequired: string;
planInvalid: string;
versionRequired: string;
softwareRequired: string;
eulaRequired: string;
}) {
return z.object({
name: z
.string()
.min(1, messages.nameRequired)
.max(64, messages.nameMax),
planId: z
.string()
.min(1, messages.planRequired)
.uuid(messages.planInvalid),
minecraftVersion: z.string().min(1, messages.versionRequired),
softwareFamily: z.enum(softwareFamilyValues, {
errorMap: () => ({ message: messages.softwareRequired }),
}),
eulaAccepted: z
.boolean()
.refine((value) => value === true, { message: messages.eulaRequired }),
});
}
export type CreateServerFormValues = z.infer<ReturnType<typeof createServerSchema>>;
export const MINECRAFT_VERSIONS = ["1.21.1", "1.21", "1.20.6", "1.20.4"] as const;
export const SOFTWARE_FAMILIES = softwareFamilyValues;