import {PROFILE} from '../config/profile.ts'; // Transaction/recovery pattern adapted from Photoshot workspace-store.ts. // Domain validation is injected: no raster document imports or shared database. export function createWorkspaceStore(validate:(value:unknown)=>T){ let queue:Promise=Promise.resolve(); function database(){return new Promise((resolve,reject)=>{ const r=indexedDB.open(PROFILE.workspaceDatabase,1); r.onupgradeneeded=()=>r.result.createObjectStore('documents'); r.onsuccess=()=>{r.result.onversionchange=()=>r.result.close();resolve(r.result);}; r.onerror=()=>reject(r.error); r.onblocked=()=>reject(Error('다른 창에서 저장소를 사용하고 있습니다.')); });} function envelope(value:unknown):T { if(!value||typeof value!=='object')throw Error('잘못된 작업공간'); const v=value as {format?:unknown;version?:unknown;savedAt?:unknown;data?:unknown}; if(v.format!==PROFILE.workspaceFormat||v.version!==1||typeof v.savedAt!=='number'||!Number.isFinite(v.savedAt))throw Error('지원하지 않는 작업공간 형식'); return validate(v.data); } return { save(value:T):Promise{ let snapshot:{format:string;version:number;savedAt:number;data:T}; try{snapshot={format:PROFILE.workspaceFormat,version:1,savedAt:Date.now(),data:structuredClone(validate(value))};}catch(e){return Promise.reject(e);} const job=queue.catch(()=>{}).then(async()=>{ const db=await database();try{await new Promise((resolve,reject)=>{ const t=db.transaction('documents','readwrite'),s=t.objectStore('documents'),r=s.get('workspace'); r.onsuccess=()=>{if(r.result!==undefined){try{envelope(r.result);s.put(r.result,'workspace-recovery');}catch{/* Preserve the last known good recovery. */}}s.put(snapshot,'workspace');}; t.oncomplete=()=>resolve();t.onabort=()=>reject(t.error??Error('저장 취소'));t.onerror=()=>reject(t.error); });}finally{db.close();} });queue=job;return job; }, async load(recovery=false):Promise{ await queue.catch(()=>{});const db=await database(); try{const value=await new Promise((resolve,reject)=>{const t=db.transaction('documents'),r=t.objectStore('documents').get(recovery?'workspace-recovery':'workspace');r.onsuccess=()=>resolve(r.result);r.onerror=()=>reject(r.error);t.onabort=()=>reject(t.error);});return value===undefined?null:envelope(value);}finally{db.close();} } }; }