Give packs an identity so create can refuse missing deps and load in a stable order.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 00:20:36 +03:00
co-authored by Cursor
parent e5a0ae5b9d
commit 263c94c55d
28 changed files with 851 additions and 56 deletions
+40 -4
View File
@@ -11,8 +11,16 @@ internal static class ModEndpoints
{
public static void MapModEndpoints(this IEndpointRouteBuilder builder)
{
builder.MapGet("/api/mods", (ModContent mods) =>
new ModsResponse(mods.ListPacks().Select(pack => new ModInfoResponse(pack.Id, pack.Required)).ToArray()))
builder.MapGet("/api/mods", (string? lang, ModContent mods) =>
{
var locale = string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase) ? "en" : "ru";
return new ModsResponse(mods.ListPacks(locale).Select(pack => new ModInfoResponse(
pack.Id,
pack.Required,
pack.Label,
pack.Version,
pack.Requires)).ToArray());
})
.WithName("GetMods");
builder.MapGet("/api/catalog", (string? lang, string? mods, ModContent content) =>
@@ -31,7 +39,19 @@ internal static class ModEndpoints
return Problem(StatusCodes.Status400BadRequest, "invalid-catalog", "The core pack is missing.");
}
var packIds = content.NormalizePackIds(extras);
IReadOnlyList<string> packIds;
try
{
packIds = content.ResolveSelectedPacks(extras);
}
catch (PackDependencyException ex)
{
return PackProblem(ex);
}
catch (ContentLoadException ex)
{
return Problem(StatusCodes.Status400BadRequest, "invalid-catalog", ex.Message);
}
DefCatalog catalog;
MapLayout map;
try
@@ -69,6 +89,17 @@ internal static class ModEndpoints
return mods.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
}
private static IResult PackProblem(PackDependencyException ex) =>
Results.Problem(
detail: ex.Message,
statusCode: StatusCodes.Status400BadRequest,
title: ex.Code,
extensions: new Dictionary<string, object?>
{
["code"] = ex.Code,
["missing"] = ex.MissingPackId,
});
private static IResult Problem(int statusCode, string code, string detail) =>
Results.Problem(detail: detail, statusCode: statusCode, title: code, extensions: new Dictionary<string, object?>
{
@@ -78,7 +109,12 @@ internal static class ModEndpoints
internal sealed record ModsResponse(IReadOnlyList<ModInfoResponse> Mods);
internal sealed record ModInfoResponse(string Id, bool Required);
internal sealed record ModInfoResponse(
string Id,
bool Required,
string Label,
string Version,
IReadOnlyList<string> Requires);
internal sealed record CatalogResponse(
IReadOnlyList<DefInfoResponse> Territories,