import * as tfrpc from '/tfrpc.js'; let g_db; tfrpc.register(async function todo_get_all() { let names = await todo_get_names(); let result = []; for (let name of names) { result.push({ name: name, items: await todo_get(name), }); } return result; }); async function todo_get_names() { return JSON.parse((await g_db.get('files')) ?? '[]'); } async function todo_add(list) { let exchanged = false; let tries = 10; while (!exchanged && tries-- > 0) { let original = await g_db.get('files'); let names = JSON.parse(original ?? '[]'); let set = new Set(names); set.add(list); names = JSON.stringify([...set].sort()); exchanged = original === names || (await g_db.exchange('files', original, names)); } return exchanged; } tfrpc.register(todo_add); async function todo_remove(list) { let exchanged = false; let tries = 10; while (!exchanged && tries-- > 0) { let original = await g_db.get('files'); let names = JSON.parse(original ?? '[]'); let set = new Set(names); set.delete(list); names = JSON.stringify([...set].sort()); exchanged = original === names || (await g_db.exchange('files', original, names)); } await g_db.remove('list:' + list); return exchanged; } tfrpc.register(todo_remove); tfrpc.register(async function todo_rename(old_name, new_name) { if (await g_db.get('list:' + new_name)) { throw RuntimeError(`${new_name} already exists.`); } let list = await todo_get(old_name); await todo_set(new_name, list); await todo_add(new_name); await todo_remove(old_name); }); async function todo_get(list) { try { let value = await g_db.get('list:' + list); return JSON.parse(value ?? '[]'); } catch (error) { print(error); return []; } } async function todo_set(list, value) { await g_db.set('list:' + list, JSON.stringify(value)); } tfrpc.register(todo_set); async function main() { g_db = await database('todo'); await app.setDocument(utf8Decode(getFile('index.html'))); } main();