import * as tfrpc from '/tfrpc.js'; let g_database; let g_hash; let g_sql_cache = {}; tfrpc.register(async function localStorageGet(key) { return app.localStorageGet(key); }); tfrpc.register(async function localStorageSet(key, value) { return app.localStorageSet(key, value); }); tfrpc.register(async function databaseGet(key) { return g_database ? g_database.get(key) : undefined; }); tfrpc.register(async function databaseSet(key, value) { return g_database ? g_database.set(key, value) : undefined; }); tfrpc.register(async function createIdentity() { return ssb.createIdentity(); }); tfrpc.register(async function getServerIdentity() { return ssb.getServerIdentity(); }); tfrpc.register(async function getIdentities() { return ssb.getIdentities(); }); tfrpc.register(async function getAllIdentities() { return ssb.getAllIdentities(); }); tfrpc.register(async function following(ids, depth) { return ssb.following(ids, depth); }); tfrpc.register(async function getBroadcasts() { return ssb.getBroadcasts(); }); tfrpc.register(async function getConnections() { return ssb.connections(); }); tfrpc.register(async function getStoredConnections() { return ssb.storedConnections(); }); tfrpc.register(async function forgetStoredConnection(connection) { return ssb.forgetStoredConnection(connection); }); tfrpc.register(async function createTunnel(portal, target) { return ssb.createTunnel(portal, target); }); tfrpc.register(async function connect(token) { await ssb.connect(token); }); tfrpc.register(async function closeConnection(id) { await ssb.closeConnection(id); }); tfrpc.register(async function query(sql, args, options) { let start = new Date(); let result = []; let key = options?.cacheable ? JSON.stringify([sql, args]) : undefined; let entry = key ? g_sql_cache[key] : undefined; const k_ideal_count = 64; if (entry) { result = entry.result; } else { await ssb.sqlAsync(sql, args, function callback(row) { result.push(row); }); if (key) { g_sql_cache[key] = { result: result, time: new Date().valueOf(), }; if (Object.keys(g_sql_cache).length > k_ideal_count * 2) { let aged = Object.entries(g_sql_cache).map(([k, v]) => [v.time, k]); aged.sort(); for (let i = 0; i < aged.length / 2; i++) { delete g_sql_cache[aged[i][1]]; } } } } let end = new Date(); print( (end - start) / 1000, entry ? 'from cache' : 'from db', sql.replaceAll(/\s+/g, ' ').trim() ); return result; }); tfrpc.register(async function appendMessage(id, message) { return ssb.appendMessageWithIdentity(id, message); }); core.register('message', async function message_handler(message) { if (message.event == 'hashChange') { g_hash = message.hash; await tfrpc.rpc.hashChanged(message.hash); } }); tfrpc.register(function getHash(id, message) { return g_hash; }); tfrpc.register(function setHash(hash) { return app.setHash(hash); }); core.register('onMessage', async function (id) { await tfrpc.rpc.notifyNewMessage(id); }); core.register('onBlob', async function (id) { await tfrpc.rpc.notifyNewBlob(id); }); tfrpc.register(async function store_blob(blob) { if (Array.isArray(blob)) { blob = Uint8Array.from(blob); } return await ssb.blobStore(blob); }); tfrpc.register(async function get_blob(id) { return utf8Decode(await ssb.blobGet(id)); }); tfrpc.register(async function store_message(message) { return await ssb.storeMessage(message); }); tfrpc.register(function apps() { return core.apps(); }); tfrpc.register(async function try_decrypt(id, content) { return await ssb.privateMessageDecrypt(id, content); }); tfrpc.register(async function encrypt(id, recipients, content) { return await ssb.privateMessageEncrypt(id, recipients, content); }); tfrpc.register(async function getActiveIdentity() { return await ssb.getActiveIdentity(); }); tfrpc.register(async function sync() { return await ssb.sync(); }); tfrpc.register(async function url() { return core.url; }); tfrpc.register(async function globalSettingsGet(key) { return core.globalSettingsGet(key); }); tfrpc.register(async function globalSettingsSet(key, value) { return core.globalSettingsSet(key, value); }); tfrpc.register(function isAdministrator() { return core.user?.credentials?.permissions?.administration; }); core.register('onBroadcastsChanged', async function () { await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts()); }); core.register('onConnectionsChanged', async function () { await tfrpc.rpc.set('connections', await ssb.connections()); }); core.register('setActiveIdentity', async function (id) { await tfrpc.rpc.set('identity', id); }); async function main() { if (typeof database !== 'undefined') { g_database = await database('ssb'); } await app.setDocument(utf8Decode(await getFile('index.html'))); } main();