import { setupAuth, getAuthenticatedDid, authVerifier } from "./utils/auth.ts"; import { setupSystemDb } from "./utils/dbsystem.ts"; import { didDocument } from "./utils/diddoc.ts"; import { cachedFetch, searchParamsToJson, withCors } from "./utils/server.ts"; import { ViewServer, ViewServerConfig } from "./viewserver.ts"; import { extractDid } from "./utils/identity.ts"; import { config } from "./config.ts"; import { compile, devWatch } from "./shared-landing/build.ts"; // ------------------------------------------ // AppView Setup // ------------------------------------------ setupAuth({ serviceDid: config.viewServer.did, //keyCacheSize: 500, //keyCacheTTL: 10 * 60 * 1000, }); const viewServerConfig: ViewServerConfig = { baseDbPath: "./dbs/view/registered-users", // The directory for user databases systemDbPath: "./dbs/view/registered-users/system.db", // The path for the main system database }; export const genericViewServer = new ViewServer(viewServerConfig); setupSystemDb(genericViewServer.systemDB); let { js, html, css } = await compile({ target: "view", initialData: { config: config.viewServer, users: (await genericViewServer.unspeccedGetRegisteredUsers()) ?? [], }, }); // add me lol genericViewServer.systemDB.exec(` INSERT OR IGNORE INTO users (did, role, registrationdate, onboardingstatus) VALUES ( 'did:plc:mn45tewwnse5btfftvd3powc', 'admin', datetime('now'), 'ready' ); INSERT OR IGNORE INTO users (did, role, registrationdate, onboardingstatus) VALUES ( 'did:web:did12.whey.party', 'admin', datetime('now'), 'ready' ); `); genericViewServer.start(); // ------------------------------------------ // XRPC Method Implementations // ------------------------------------------ const placeholderselfcheckstatus = { "#bsky_appview:/xrpc/app.bsky.actor.getPreferences": "black", "#bsky_appview:/xrpc/app.bsky.actor.getProfile": "green", "#bsky_appview:/xrpc/app.bsky.actor.getProfiles": "green", "#bsky_appview:/xrpc/app.bsky.actor.getSuggestions": "black", "#bsky_appview:/xrpc/app.bsky.actor.putPreferences": "black", "#bsky_appview:/xrpc/app.bsky.actor.searchActorsTypeahead": "black", "#bsky_appview:/xrpc/app.bsky.actor.searchActors": "black", "#bsky_appview:/xrpc/app.bsky.feed.describeFeedGenerator": "black", "#bsky_appview:/xrpc/app.bsky.feed.getActorFeeds": "black", "#bsky_appview:/xrpc/app.bsky.feed.getActorLikes": "black", "#bsky_appview:/xrpc/app.bsky.feed.getAuthorFeed": "red", "#bsky_appview:/xrpc/app.bsky.feed.getFeedGenerator": "black", "#bsky_appview:/xrpc/app.bsky.feed.getFeedGenerators": "green", // arguably "#bsky_appview:/xrpc/app.bsky.feed.getFeedSkeleton": "black", "#bsky_appview:/xrpc/app.bsky.feed.getFeed": "red", "#bsky_appview:/xrpc/app.bsky.feed.getLikes": "black", "#bsky_appview:/xrpc/app.bsky.feed.getListFeed": "black", "#bsky_appview:/xrpc/app.bsky.feed.getPostThread": "red", "#bsky_appview:/xrpc/app.bsky.unspecced.getPostThreadV2": "red", "#bsky_appview:/xrpc/app.bsky.feed.getPosts": "green", "#bsky_appview:/xrpc/app.bsky.feed.getQuotes": "black", "#bsky_appview:/xrpc/app.bsky.feed.getRepostedBy": "black", "#bsky_appview:/xrpc/app.bsky.feed.getSuggestedFeeds": "black", "#bsky_appview:/xrpc/app.bsky.feed.getTimeline": "black", "#bsky_appview:/xrpc/app.bsky.feed.searchPosts": "black", "#bsky_appview:/xrpc/app.bsky.feed.sendInteractions": "black", "#bsky_appview:/xrpc/app.bsky.graph.getActorStarterPacks": "black", "#bsky_appview:/xrpc/app.bsky.graph.getBlocks": "black", "#bsky_appview:/xrpc/app.bsky.graph.getFollowers": "black", "#bsky_appview:/xrpc/app.bsky.graph.getFollows": "black", "#bsky_appview:/xrpc/app.bsky.graph.getKnownFollowers": "black", "#bsky_appview:/xrpc/app.bsky.graph.getListBlocks": "black", "#bsky_appview:/xrpc/app.bsky.graph.getListMutes": "black", "#bsky_appview:/xrpc/app.bsky.graph.getList": "black", "#bsky_appview:/xrpc/app.bsky.graph.getLists": "black", "#bsky_appview:/xrpc/app.bsky.graph.getMutes": "black", "#bsky_appview:/xrpc/app.bsky.graph.getRelationships": "black", "#bsky_appview:/xrpc/app.bsky.graph.getStarterPack": "black", "#bsky_appview:/xrpc/app.bsky.graph.getStarterPacks": "black", "#bsky_appview:/xrpc/app.bsky.graph.getSuggestedFollowsByActor": "black", "#bsky_appview:/xrpc/app.bsky.graph.muteActorList": "black", "#bsky_appview:/xrpc/app.bsky.graph.muteActor": "black", "#bsky_appview:/xrpc/app.bsky.graph.muteThread": "black", "#bsky_appview:/xrpc/app.bsky.graph.searchStarterPacks": "black", "#bsky_appview:/xrpc/app.bsky.graph.unmuteActorList": "black", "#bsky_appview:/xrpc/app.bsky.graph.unmuteActor": "black", "#bsky_appview:/xrpc/app.bsky.graph.unmuteThread": "black", "#bsky_appview:/xrpc/app.bsky.labeler.getServices": "black", "#bsky_appview:/xrpc/app.bsky.notification.getUnreadCount": "black", "#bsky_appview:/xrpc/app.bsky.notification.listNotifications": "green", "#bsky_appview:/xrpc/app.bsky.notification.putPreferences": "black", "#bsky_appview:/xrpc/app.bsky.notification.registerPush": "black", "#bsky_appview:/xrpc/app.bsky.notification.updateSeen": "black", "#bsky_appview:/xrpc/app.bsky.video.getJobStatus": "black", "#bsky_appview:/xrpc/app.bsky.video.getUploadLimits": "black", "#bsky_appview:/xrpc/app.bsky.video.uploadVideo": "black", "#bsky_appview:/xrpc/app.bsky.unspecced.getTrendingTopics": "red", "#bsky_appview:/xrpc/app.bsky.unspecced.getConfig": "red", }; Deno.serve( { port: config.viewServer.port }, async (req: Request): Promise => { const url = new URL(req.url); const pathname = url.pathname; const searchParams = searchParamsToJson(url.searchParams); const publicdir = "/public"; if (pathname.startsWith(publicdir)) { const filepath = decodeURIComponent(pathname.slice(publicdir.length)); try { const file = await Deno.open("." + filepath, { read: true }); return new Response(file.readable); } catch { return new Response("404 Not Found", { status: 404 }); } } const todopleasespecthis = "/_unspecced"; if (pathname.startsWith(todopleasespecthis)) { const unspeccedroute = decodeURIComponent( pathname.slice(todopleasespecthis.length) ); if (unspeccedroute === "/config") { const safeconfig = { inviteOnly: config.viewServer.inviteOnly, //port: number, did: config.viewServer.did, host: config.viewServer.host, indexPriority: config.viewServer.indexPriority, }; return new Response(JSON.stringify(safeconfig), { headers: withCors({ "content-type": "application/json; charset=utf-8", }), }); } if (unspeccedroute === "/users") { const res = await genericViewServer.unspeccedGetRegisteredUsers(); return new Response(JSON.stringify(res), { headers: withCors({ "content-type": "application/json; charset=utf-8", }), }); } if (unspeccedroute === "/apitest") { return new Response(JSON.stringify(placeholderselfcheckstatus), { headers: withCors({ "content-type": "application/json; charset=utf-8", }), }); } } if (html && js) { if (pathname === "/" || pathname === "") { return new Response(html, { headers: withCors({ "content-type": "text/html; charset=utf-8" }), }); } if (pathname === "/landing-view.js") { return new Response(js, { headers: withCors({ "content-type": "application/javascript; charset=utf-8", }), }); } } else { if (pathname === "/" || pathname === "") { return new Response(`server is compiling your webpage. loading...`, { headers: withCors({ "content-type": "text/html; charset=utf-8" }), }); } } if (pathname === "/app.css") { return new Response(css, { headers: withCors({ "content-type": "text/css; charset=utf-8", }), }); } if (pathname === "/.well-known/did.json") { return new Response( JSON.stringify( didDocument( "view", config.viewServer.did, config.viewServer.host, "whatever" ) ), { headers: withCors({ "Content-Type": "application/json" }), } ); } if (pathname === "/health") { return new Response("OK", { status: 200, headers: withCors({ "Content-Type": "text/plain", }), }); } if (req.method === "OPTIONS") { return new Response(null, { status: 204, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "*", }, }); } console.log(`request for "${pathname}"`); return await genericViewServer.viewServerHandler(req); } ); devWatch({ target: "view", initialData: { config: config.viewServer, users: await genericViewServer.unspeccedGetRegisteredUsers() ?? [], }, onBuild: ({ js: newjs, html: newhtml, css: newcss }) => { js = newjs; html = newhtml; css = newcss; }, });