export async function readJsonFile(file) { try { return JSON.parse(await file.text()); } catch (error) { const reason = error instanceof Error ? error.message : String(error); throw new Error(`${file.name} 파일은 올바른 JSON이 아닙니다: ${reason}`); } } export function downloadJson(value, fileName) { const body = `${JSON.stringify(value, null, 2)}\n`; const url = URL.createObjectURL(new Blob([body], { type: "application/json" })); const anchor = document.createElement("a"); anchor.href = url; anchor.download = fileName; anchor.click(); setTimeout(() => URL.revokeObjectURL(url), 0); } export function downloadBlob(blob, fileName) { const url = URL.createObjectURL(blob); const anchor = document.createElement("a"); anchor.href = url; anchor.download = fileName; anchor.click(); setTimeout(() => URL.revokeObjectURL(url), 0); } export async function sha256File(file) { const digest = await crypto.subtle.digest("SHA-256", await file.arrayBuffer()); return [...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join(""); } export function deepClone(value) { return structuredClone(value); }