60 lines
2.8 KiB
JavaScript
60 lines
2.8 KiB
JavaScript
// ── Rehearser library persistence ────────────────────────────────────────────
|
|
// SQLite-backed rehearsal records and the one-time IndexedDB migration are
|
|
// isolated from parsing, casting, and stage playback. Functions stay global
|
|
// during the compatibility migration because audiobook.js/library.js call them.
|
|
|
|
async function rehDbGetAll() {
|
|
const r = await fetch('/api/rehearsals');
|
|
if (!r.ok) throw new Error('rehDbGetAll failed: ' + r.status);
|
|
const d = await r.json();
|
|
return d.rehearsals || [];
|
|
}
|
|
async function rehDbGetById(id) {
|
|
const r = await fetch('/api/rehearsals/' + id);
|
|
if (r.status === 404) return undefined;
|
|
if (!r.ok) throw new Error('rehDbGetById failed: ' + r.status);
|
|
return r.json();
|
|
}
|
|
async function rehDbAdd(record) {
|
|
const r = await fetch('/api/rehearsals', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(_rehSanitize(record)) });
|
|
if (!r.ok) throw new Error('rehDbAdd failed: ' + r.status);
|
|
return (await r.json()).id;
|
|
}
|
|
async function rehDbPut(record) {
|
|
if (!record.id) return rehDbAdd(record);
|
|
const r = await fetch('/api/rehearsals/' + record.id, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(_rehSanitize(record)) });
|
|
if (!r.ok) throw new Error('rehDbPut failed: ' + r.status);
|
|
}
|
|
async function rehDbDelete(id) {
|
|
const r = await fetch('/api/rehearsals/' + id, { method: 'DELETE' });
|
|
if (!r.ok) throw new Error('rehDbDelete failed: ' + r.status);
|
|
}
|
|
function _rehSanitize(rec) {
|
|
const out = { ...rec };
|
|
if (out.clips) out.clips = (out.clips || []).map(c => ({ lineIndex: c.lineIndex, speaker: c.speaker, type: c.type }));
|
|
return out;
|
|
}
|
|
function _rehIdbGetAll() {
|
|
return new Promise(resolve => {
|
|
const req = indexedDB.open('reh-library', 1);
|
|
req.onerror = () => resolve([]);
|
|
req.onsuccess = e => {
|
|
const db = e.target.result;
|
|
if (!db.objectStoreNames.contains('rehearsals')) { db.close(); resolve([]); return; }
|
|
const all = db.transaction('rehearsals', 'readonly').objectStore('rehearsals').getAll();
|
|
all.onsuccess = ev => { db.close(); resolve(ev.target.result || []); };
|
|
all.onerror = () => { db.close(); resolve([]); };
|
|
};
|
|
});
|
|
}
|
|
(async function _rehMigrateIfNeeded() {
|
|
try {
|
|
if ((await rehDbGetAll()).length) return;
|
|
const old = await _rehIdbGetAll();
|
|
if (!old.length) return;
|
|
const r = await fetch('/api/rehearsals/migrate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(old.map(_rehSanitize)) });
|
|
if (r.ok) console.log(`[rehearser] migrated ${(await r.json()).imported} records from IndexedDB → SQLite`);
|
|
} catch (e) { console.warn('[rehearser] migration skipped:', e); }
|
|
})();
|
|
window.rehDbGetById = rehDbGetById;
|