feat(panel): edit memoryMB from the Settings modal

Adds GET/POST /api/daemon/config (safe subset of server-config.json --
just memoryMB for now) and a "Resources" section in the existing Settings
modal. The Save and Save+restart buttons now POST both /api/server/settings
and /api/daemon/config; restartRequired is OR'd across the two endpoints.

Future fields like backupKeep / backupSchedule / bluemapDir can be added
by extending DAEMON_FIELDS in settings.js + the validation block in
RunCommand.cs. Sensitive fields (passwords, manifestUrl, ports) are
intentionally kept off this endpoint.
This commit is contained in:
Matt Sijbers
2026-05-20 21:25:47 +01:00
parent 9bf3cc69b0
commit 683c2c19ff
4 changed files with 116 additions and 5 deletions
+43
View File
@@ -707,6 +707,49 @@ public sealed class RunCommand : AsyncCommand<BaseCommandSettings>
return Results.Json(new { ok = true, restartRequired = serverProc.IsRunning });
});
// ── Daemon config (safe subset of server-config.json) ──
// Lets the panel edit things that live in our own config, not server.properties:
// memoryMB (the JVM -Xmx). Sensitive fields (passwords, manifestUrl, ports) are
// intentionally not exposed here -- those still need direct file edits + restart.
app.MapGet("/api/daemon/config", () => Results.Json(new
{
memoryMB = config.MemoryMB,
}));
app.MapPost("/api/daemon/config", async (HttpContext ctx) =>
{
using var sr = new StreamReader(ctx.Request.Body);
var payload = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
await sr.ReadToEndAsync(), JsonOpts.CaseInsensitive);
if (payload is null || payload.Count == 0)
return Results.BadRequest(new { ok = false, error = "Empty payload." });
var changed = false;
if (payload.TryGetValue("memoryMB", out var memEl))
{
int memMB;
if (memEl.ValueKind == JsonValueKind.Number) memMB = memEl.GetInt32();
else if (!int.TryParse(memEl.GetString(), out memMB))
return Results.BadRequest(new { ok = false, error = "memoryMB must be a number" });
// Sanity bounds. MC needs at least 1 GB; absolute cap of 64 GB protects against
// a fat-fingered entry that would refuse to start (JVM allocates Xmx up front).
if (memMB < 1024) return Results.BadRequest(new { ok = false, error = "memoryMB must be >= 1024" });
if (memMB > 65536) return Results.BadRequest(new { ok = false, error = "memoryMB must be <= 65536" });
if (config.MemoryMB != memMB)
{
config.MemoryMB = memMB;
changed = true;
}
}
if (changed) config.Save(configPath);
// Memory changes always require a restart -- the JVM can't grow -Xmx at runtime.
return Results.Json(new { ok = true, restartRequired = changed && serverProc.IsRunning });
});
// ── BlueMap (manual render) ──
app.MapGet("/api/map/status", () => Results.Json(new
{