Files
EpicNext-Cms/src/lib/services/figuredata.ts
T
openhands 944e8ff1d8
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
fix: harden update pipeline and restore a clean production build
- update-Nitrov3.sh: build CMS into .next-staging and swap atomically so a
  failed build never takes the live site down; auto-merge new variables
  from .env.example; validate env for duplicates/broken lines; restart the
  emulator/CMS only when rebuilt or unhealthy; fix step renumbering
- next.config.ts: support NEXT_DIST_DIR for staged production builds
- fix all TS errors (unused imports, missing tryDownloadCandidates helper)
  so tsc and the production build pass clean
- add Dockerfile/.dockerignore and switch docker-compose to a CMS container
- include prevailing UI/refactor changes (SurfaceCard, ticketing, tsconfig)
2026-08-28 12:48:04 +02:00

91 lines
2.3 KiB
TypeScript

import { resolveGamedataFile } from "@/lib/services/import/core/asset-paths";
import {
readGamedataJson,
withGamedataLock,
writeGamedataJsonAtomic,
} from "@/lib/services/import/core/gamedata-json";
import { siteSettings } from "@/lib/services/site-settings";
interface FdSet {
id: number;
[k: string]: unknown;
}
interface FdSetType {
type: string;
paletteId: number;
sets: FdSet[];
[k: string]: unknown;
}
interface FdPalette {
id: number;
colors: unknown[];
}
interface FigureDataFile {
palettes: FdPalette[];
setTypes: FdSetType[];
}
const pathOverride: string | null = null;
export async function getFigureDataPath(): Promise<string> {
if (pathOverride) return pathOverride;
const url = await siteSettings.get(
"figuredata_url",
"/nitro-assets/gamedata/FigureData.json",
);
return await resolveGamedataFile(
url ?? "/nitro-assets/gamedata/FigureData.json",
"FigureData.json",
);
}
export async function readFigureData(): Promise<FigureDataFile> {
const data = await readGamedataJson<Partial<FigureDataFile>>(
await getFigureDataPath(),
);
return { palettes: data.palettes ?? [], setTypes: data.setTypes ?? [] };
}
export async function listLocalSetIds(setType: string): Promise<Set<number>> {
const fd = await readFigureData();
const st = fd.setTypes.find((s) => s.type === setType);
return new Set((st?.sets ?? []).map((s) => s.id));
}
export async function mergeSet(
setType: string,
paletteId: number,
set: FdSet,
): Promise<void> {
const file = await getFigureDataPath();
await withGamedataLock(file, async () => {
const fd = await readGamedataJson<FigureDataFile>(file);
fd.setTypes ??= [];
let st = fd.setTypes.find((s) => s.type === setType);
if (!st) {
st = { type: setType, paletteId, sets: [] };
fd.setTypes.push(st);
}
st.sets ??= [];
const idx = st.sets.findIndex((s) => s.id === set.id);
if (idx >= 0) {
st.sets[idx] = set;
} else {
st.sets.push(set);
}
await writeGamedataJsonAtomic(file, fd);
});
}
export async function mergePalette(palette: FdPalette): Promise<void> {
const file = await getFigureDataPath();
await withGamedataLock(file, async () => {
const fd = await readGamedataJson<FigureDataFile>(file);
fd.palettes ??= [];
if (!fd.palettes.some((p) => p.id === palette.id)) {
fd.palettes.push(palette);
await writeGamedataJsonAtomic(file, fd);
}
});
}