Phase3
This commit is contained in:
86
apps/web/src/lib/api/console.ts
Normal file
86
apps/web/src/lib/api/console.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { getApiUrl } from "../env";
|
||||
import { apiFetch } from "./auth";
|
||||
|
||||
export interface ConsoleTokenResponse {
|
||||
token: string;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
export interface ConsoleWebSocketHandlers {
|
||||
onOpen?: () => void;
|
||||
onClose?: (event: CloseEvent) => void;
|
||||
onError?: (event: Event) => void;
|
||||
onLine?: (line: string, stream?: string) => void;
|
||||
}
|
||||
|
||||
interface ConsoleLogMessage {
|
||||
type?: string;
|
||||
line?: string;
|
||||
stream?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
function getConsoleWebSocketUrl(serverId: string, token: string): string {
|
||||
const apiUrl = new URL(getApiUrl());
|
||||
apiUrl.protocol = apiUrl.protocol === "https:" ? "wss:" : "ws:";
|
||||
const basePath = apiUrl.pathname.replace(/\/$/, "");
|
||||
apiUrl.pathname = `${basePath}/servers/${serverId}/console/ws`;
|
||||
apiUrl.search = new URLSearchParams({ token }).toString();
|
||||
return apiUrl.toString();
|
||||
}
|
||||
|
||||
export async function getConsoleToken(serverId: string): Promise<ConsoleTokenResponse> {
|
||||
return apiFetch<ConsoleTokenResponse>(`/servers/${serverId}/console/token`);
|
||||
}
|
||||
|
||||
export function createConsoleWebSocket(
|
||||
serverId: string,
|
||||
token: string,
|
||||
handlers: ConsoleWebSocketHandlers,
|
||||
): WebSocket {
|
||||
const socket = new WebSocket(getConsoleWebSocketUrl(serverId, token));
|
||||
|
||||
socket.addEventListener("open", () => {
|
||||
handlers.onOpen?.();
|
||||
});
|
||||
|
||||
socket.addEventListener("close", (event) => {
|
||||
handlers.onClose?.(event);
|
||||
});
|
||||
|
||||
socket.addEventListener("error", (event) => {
|
||||
handlers.onError?.(event);
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
const raw = typeof event.data === "string" ? event.data : "";
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(raw) as ConsoleLogMessage;
|
||||
if (parsed.type === "log" && parsed.line) {
|
||||
handlers.onLine?.(parsed.line, parsed.stream);
|
||||
return;
|
||||
}
|
||||
if (parsed.line) {
|
||||
handlers.onLine?.(parsed.line, parsed.stream);
|
||||
return;
|
||||
}
|
||||
if (parsed.message) {
|
||||
handlers.onLine?.(parsed.message, parsed.stream);
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// Plain text log line
|
||||
}
|
||||
|
||||
if (raw) {
|
||||
handlers.onLine?.(raw);
|
||||
}
|
||||
});
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
export function sendConsoleCommand(socket: WebSocket, command: string): void {
|
||||
socket.send(JSON.stringify({ command }));
|
||||
}
|
||||
61
apps/web/src/lib/api/files.ts
Normal file
61
apps/web/src/lib/api/files.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { apiFetch } from "./auth";
|
||||
|
||||
export interface FileEntry {
|
||||
name: string;
|
||||
path: string;
|
||||
isDir: boolean;
|
||||
size: number;
|
||||
modifiedAt?: string;
|
||||
}
|
||||
|
||||
export interface ListFilesResponse {
|
||||
path: string;
|
||||
entries: FileEntry[];
|
||||
}
|
||||
|
||||
export interface FileContentResponse {
|
||||
path: string;
|
||||
content: string;
|
||||
truncated?: boolean;
|
||||
version?: number;
|
||||
}
|
||||
|
||||
export interface WriteFilePayload {
|
||||
path: string;
|
||||
content: string;
|
||||
version?: number;
|
||||
}
|
||||
|
||||
export async function listFiles(
|
||||
serverId: string,
|
||||
path = "",
|
||||
): Promise<ListFilesResponse> {
|
||||
const params = new URLSearchParams();
|
||||
if (path) {
|
||||
params.set("path", path);
|
||||
}
|
||||
const query = params.toString();
|
||||
return apiFetch<ListFilesResponse>(
|
||||
`/servers/${serverId}/files${query ? `?${query}` : ""}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function readFile(
|
||||
serverId: string,
|
||||
path: string,
|
||||
): Promise<FileContentResponse> {
|
||||
const params = new URLSearchParams({ path });
|
||||
return apiFetch<FileContentResponse>(
|
||||
`/servers/${serverId}/files/content?${params.toString()}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function writeFile(
|
||||
serverId: string,
|
||||
payload: WriteFilePayload,
|
||||
): Promise<FileContentResponse> {
|
||||
return apiFetch<FileContentResponse>(`/servers/${serverId}/files/content`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
17
apps/web/src/lib/api/players.ts
Normal file
17
apps/web/src/lib/api/players.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { apiFetch } from "./auth";
|
||||
|
||||
export interface OnlinePlayer {
|
||||
name: string;
|
||||
uuid?: string;
|
||||
ping?: number;
|
||||
}
|
||||
|
||||
export interface PlayerListResponse {
|
||||
online: OnlinePlayer[];
|
||||
maxPlayers: number;
|
||||
whitelistCount: number;
|
||||
}
|
||||
|
||||
export async function getPlayers(serverId: string): Promise<PlayerListResponse> {
|
||||
return apiFetch<PlayerListResponse>(`/servers/${serverId}/players`);
|
||||
}
|
||||
36
apps/web/src/lib/api/properties.ts
Normal file
36
apps/web/src/lib/api/properties.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { apiFetch } from "./auth";
|
||||
|
||||
export type GameMode = "survival" | "creative" | "adventure" | "spectator";
|
||||
export type Difficulty = "peaceful" | "easy" | "normal" | "hard";
|
||||
|
||||
export interface ServerProperties {
|
||||
motd: string;
|
||||
gamemode: GameMode;
|
||||
difficulty: Difficulty;
|
||||
maxPlayers: number;
|
||||
pvp: boolean;
|
||||
whitelist: boolean;
|
||||
hardcore?: boolean;
|
||||
onlineMode?: boolean;
|
||||
enableCommandBlock?: boolean;
|
||||
viewDistance?: number;
|
||||
simulationDistance?: number;
|
||||
spawnProtection?: number;
|
||||
allowFlight?: boolean;
|
||||
}
|
||||
|
||||
export type UpdateServerPropertiesPayload = Partial<ServerProperties>;
|
||||
|
||||
export async function getProperties(serverId: string): Promise<ServerProperties> {
|
||||
return apiFetch<ServerProperties>(`/servers/${serverId}/properties`);
|
||||
}
|
||||
|
||||
export async function updateProperties(
|
||||
serverId: string,
|
||||
payload: UpdateServerPropertiesPayload,
|
||||
): Promise<ServerProperties> {
|
||||
return apiFetch<ServerProperties>(`/servers/${serverId}/properties`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user