feat: add recent furni resync client contract

This commit is contained in:
Simo committed 2026-08-02 14:56:12 +02:00
1 parent cf563f3550
commit 88ac5ac1ba
2 files changed
+95

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
import { describe, expect, it, vi } from "vitest";
import {
RECENT_FURNI_RESYNC_URL,
requestRecentFurniResync,
} from "./recent-furni-resync";
describe("requestRecentFurniResync", () => {
it("posts to the fixed seven-day resync endpoint and normalizes the result", async () => {
const fetcher = vi.fn(async () =>
Response.json({
ok: true,
mode: "days",
days: 7,
examined: 4,
resynced: 3,
failed: 1,
rconOk: false,
errors: [{ classname: "chair", message: "invalid entry" }],
}),
);
await expect(requestRecentFurniResync(fetcher)).resolves.toEqual({
examined: 4,
resynced: 3,
failed: 1,
rconOk: false,
errors: [{ classname: "chair", message: "invalid entry" }],
});
expect(RECENT_FURNI_RESYNC_URL).toBe(
"/api/admin/import/furni/resync?days=7",
);
expect(fetcher).toHaveBeenCalledWith(RECENT_FURNI_RESYNC_URL, {
method: "POST",
});
});
it("throws the API error when the request fails", async () => {
const fetcher = vi.fn(async () =>
Response.json({ error: "Forbidden" }, { status: 403 }),
);
await expect(requestRecentFurniResync(fetcher)).rejects.toThrow(
"Forbidden",
);
});
});
+49
View File
@@ -0,0 +1,49 @@
export const RECENT_FURNI_RESYNC_URL = "/api/admin/import/furni/resync?days=7";
export interface RecentFurniResyncError {
classname: string;
message: string;
}
export interface RecentFurniResyncResult {
examined: number;
resynced: number;
failed: number;
rconOk: boolean;
errors: RecentFurniResyncError[];
}
type AdminFetcher = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
export async function requestRecentFurniResync(
fetcher: AdminFetcher,
): Promise<RecentFurniResyncResult> {
const response = await fetcher(RECENT_FURNI_RESYNC_URL, { method: "POST" });
const payload = (await response.json()) as Record<string, unknown>;
if (!response.ok) {
throw new Error(
typeof payload.error === "string" ? payload.error : "Furni resync failed",
);
}
const errors = Array.isArray(payload.errors)
? payload.errors.filter(
(value): value is RecentFurniResyncError =>
typeof value === "object" &&
value !== null &&
typeof (value as RecentFurniResyncError).classname === "string" &&
typeof (value as RecentFurniResyncError).message === "string",
)
: [];
return {
examined: Number(payload.examined) || 0,
resynced: Number(payload.resynced) || 0,
failed: Number(payload.failed) || 0,
rconOk: payload.rconOk === true,
errors,
};
}