Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
wisp.place
1import { Elysia } from 'elysia'
2import { requireAuth } from '../lib/wisp-auth'
3import { NodeOAuthClient } from '@atproto/oauth-client-node'
4import { Agent } from '@atproto/api'
5import { deleteSite } from '../lib/db'
6import { logger } from '../lib/logger'
7
8export const siteRoutes = (client: NodeOAuthClient, cookieSecret: string) =>
9 new Elysia({
10 prefix: '/api/site',
11 cookie: {
12 secrets: cookieSecret,
13 sign: ['did']
14 }
15 })
16 .derive(async ({ cookie }) => {
17 const auth = await requireAuth(client, cookie)
18 return { auth }
19 })
20 .delete('/:rkey', async ({ params, auth }) => {
21 const { rkey } = params
22
23 if (!rkey) {
24 return {
25 success: false,
26 error: 'Site rkey is required'
27 }
28 }
29
30 try {
31 // Create agent with OAuth session
32 const agent = new Agent((url, init) => auth.session.fetchHandler(url, init))
33
34 // Delete the record from AT Protocol
35 try {
36 await agent.com.atproto.repo.deleteRecord({
37 repo: auth.did,
38 collection: 'place.wisp.fs',
39 rkey: rkey
40 })
41 logger.info(`[Site] Deleted site ${rkey} from PDS for ${auth.did}`)
42 } catch (err) {
43 logger.error(`[Site] Failed to delete site ${rkey} from PDS`, err)
44 throw new Error('Failed to delete site from AT Protocol')
45 }
46
47 // Delete from database
48 const result = await deleteSite(auth.did, rkey)
49 if (!result.success) {
50 throw new Error('Failed to delete site from database')
51 }
52
53 logger.info(`[Site] Successfully deleted site ${rkey} for ${auth.did}`)
54
55 return {
56 success: true,
57 message: 'Site deleted successfully'
58 }
59 } catch (err) {
60 logger.error('[Site] Delete error', err)
61 return {
62 success: false,
63 error: err instanceof Error ? err.message : 'Failed to delete site'
64 }
65 }
66 })