import type { MateriaLoopConfig, MateriaPipelineConfig, PiMateriaConfig } from "../types.js"; /** WebUI loadout DTOs are socket-first at the API boundary. */ export type WebUiLoadoutDto = Omit & { sockets?: MateriaPipelineConfig["sockets"]; loops?: Record; }; export type WebUiLoopDto = MateriaLoopConfig & { sockets?: string[]; }; export type WebUiConfigDto = Partial> = Omit & { loadouts?: Record; }; export function toWebUiLoadoutDto(loadout: MateriaPipelineConfig): WebUiLoadoutDto { const cloned = clone(loadout) as WebUiLoadoutDto; if (cloned.loops) { cloned.loops = Object.fromEntries(Object.entries(cloned.loops).map(([id, loop]) => [id, toWebUiLoopDto(loop)])); } return cloned; } export function fromWebUiLoadoutDto(loadout: WebUiLoadoutDto): MateriaPipelineConfig { const cloned = clone(loadout) as MateriaPipelineConfig; if (cloned.loops) { cloned.loops = Object.fromEntries(Object.entries(cloned.loops).map(([id, loop]) => [id, fromWebUiLoopDto(loop)])); } return cloned; } export function toWebUiConfigDto>(config: TConfig): WebUiConfigDto { const cloned = clone(config) as WebUiConfigDto; if (cloned.loadouts) { cloned.loadouts = Object.fromEntries(Object.entries(cloned.loadouts).map(([name, loadout]) => [name, loadout === null ? null : toWebUiLoadoutDto(loadout as MateriaPipelineConfig)])); } return cloned; } export function fromWebUiConfigDto(config: TConfig): Omit & { loadouts?: Record } { const cloned = clone(config) as Omit & { loadouts?: Record }; if (cloned.loadouts) { cloned.loadouts = Object.fromEntries(Object.entries(cloned.loadouts).map(([name, loadout]) => [name, loadout === null ? null : fromWebUiLoadoutDto(loadout as WebUiLoadoutDto)])); } return cloned; } function toWebUiLoopDto(loop: MateriaLoopConfig): WebUiLoopDto { return clone(loop) as WebUiLoopDto; } function fromWebUiLoopDto(loop: WebUiLoopDto): MateriaLoopConfig { return clone(loop) as MateriaLoopConfig; } function clone(value: T): T { return value === undefined ? value : JSON.parse(JSON.stringify(value)) as T; }