let g_hash; async function query(sql, params) { let results = []; await ssb.sqlAsync(sql, params, function (row) { results.push(row); }); return results; } async function resolve(id) { try { let blob = await ssb.blobGet(id); if (blob) { let json; try { json = JSON.parse(utf8Decode(blob)); } catch { return {id: utf8Decode(blob)}; } if (json?.links) { for (let [key, value] of Object.entries(json.links)) { json.links[key] = await resolve(value); } return json; } else { return 'huh?' + json; } } else { return `missing<${id}>`; } } catch (e) { return id + ': ' + e.message; } } async function get_names(identities) { return Object.fromEntries( ( await query( ` SELECT author, name FROM ( SELECT messages.author, RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank, messages.content ->> 'name' AS name FROM messages JOIN json_each(?) AS identities ON identities.value = messages.author WHERE json_extract(messages.content, '$.type') = 'about' AND content ->> 'about' = messages.author AND name IS NOT NULL) WHERE author_rank = 1 `, [JSON.stringify(identities)] ) ).map((x) => [x.author, x.name]) ); } async function render(hash) { g_hash = hash; if (!hash) { let sites = await query( ` SELECT site.author, site.id FROM messages site WHERE site.content ->> 'type' = 'web-init' `, [] ); let names = await get_names(sites.map((x) => x.author)); if (hash === g_hash) { await app.setDocument( `` ); } } else { let site_id = hash.charAt(0) == '#' ? decodeURIComponent(hash.substring(1)) : decodeURIComponent(hash); await app.setDocument(` `); } } core.register('message', async function message_handler(message) { if (message.event == 'hashChange') { await render(message.hash); } }); async function main() { render(null); } main();