···
import { page } from '#/lib/view'
import * as Status from '#/lexicon/types/com/example/status'
12
+
// Helper function for defining routes
···
export const createRouter = (ctx: AppContext) => {
const router = express.Router()
router.use('/public', express.static(path.join(__dirname, 'pages', 'public')))
···
41
+
// OAuth callback to complete session creation
handler(async (req, res) => {
···
handler(async (_req, res) => {
···
handler(async (req, res) => {
const handle = req.body?.handle
if (typeof handle !== 'string' || !isValidHandle(handle)) {
return res.type('html').send(page(login({ error: 'invalid handle' })))
75
+
// Initiate the OAuth flow
const url = await ctx.oauthClient.authorize(handle)
return res.redirect(url.toString())
···
handler(async (req, res) => {
···
handler(async (req, res) => {
108
+
// If the user is signed in, get an agent which communicates with their server
const agent = await getSessionAgent(req, res, ctx)
111
+
// Fetch data stored in our SQLite
const statuses = await ctx.db
···
.where('authorDid', '=', agent.accountDid)
126
+
// Map user DIDs to their domain-name handles
const didHandleMap = await ctx.resolver.resolveDidsToHandles(
statuses.map((s) => s.authorDid)
132
+
// Serve the logged-out view
return res.type('html').send(page(home({ statuses, didHandleMap })))
136
+
// Fetch additional information about the logged-in user
const { data: profile } = await agent.getProfile({
140
+
didHandleMap[profile.handle] = agent.accountDid
142
+
// Serve the logged-in view
.send(page(home({ statuses, didHandleMap, profile, myStatus })))
149
+
// "Set status" handler
handler(async (req, res) => {
153
+
// If the user is signed in, get an agent which communicates with their server
const agent = await getSessionAgent(req, res, ctx)
return res.status(401).json({ error: 'Session required' })
159
+
// Construct & validate their status record
$type: 'com.example.status',
status: req.body?.status,
···
170
+
// Write the status record to the user's repository
await agent.com.atproto.repo.putRecord({
collection: 'com.example.status',
···
184
+
// Optimistically update our SQLite
185
+
// This isn't strictly necessary because the write event will be
186
+
// handled in #/firehose/ingestor.ts, but it ensures that future reads
187
+
// will be up-to-date after this method finishes.