Scratch space for learning atproto app development
1'use server'
2
3import assert from 'node:assert'
4import type { IncomingMessage, ServerResponse } from 'node:http'
5import { getIronSession } from 'iron-session'
6import { env } from '#/env'
7import { AppContext } from '#/config'
8
9export type Session = { did: string }
10
11export async function createSession(
12 req: IncomingMessage,
13 res: ServerResponse<IncomingMessage>,
14 did: string
15) {
16 const session = await getSessionRaw(req, res)
17 assert(!session.did, 'session already exists')
18 session.did = did
19 await session.save()
20 return { did: session.did }
21}
22
23export async function destroySession(
24 req: IncomingMessage,
25 res: ServerResponse<IncomingMessage>
26) {
27 const session = await getSessionRaw(req, res)
28 await session.destroy()
29 return null
30}
31
32export async function getSession(
33 req: IncomingMessage,
34 res: ServerResponse<IncomingMessage>
35) {
36 const session = await getSessionRaw(req, res)
37 if (!session.did) return null
38 return { did: session.did }
39}
40
41export async function getSessionAgent(
42 req: IncomingMessage,
43 res: ServerResponse<IncomingMessage>,
44 ctx: AppContext
45) {
46 const session = await getSessionRaw(req, res)
47 if (!session.did) return null
48 return await ctx.oauthClient.restore(session.did).catch(async (err) => {
49 ctx.logger.warn({ err }, 'oauth restore failed')
50 await destroySession(req, res)
51 return null
52 })
53}
54
55async function getSessionRaw(
56 req: IncomingMessage,
57 res: ServerResponse<IncomingMessage>
58) {
59 return await getIronSession<Session>(req, res, {
60 cookieName: 'sid',
61 password: env.COOKIE_SECRET,
62 })
63}