[READ-ONLY] Mirror of https://github.com/flo-bit/svelte-cloudflare-statusphere. statusphere.atmo.tools
atproto cloudflare-workers oauth svelte
0

Configure Feed

Select the types of activity you want to include in your feed.

2.3 kB 85 lines
1import { error } from '@sveltejs/kit'; 2import { command, getRequestEvent } from '$app/server'; 3import * as v from 'valibot'; 4import { permissions } from '../settings'; 5 6// Validate collection format and check against allowed list from settings 7const collectionSchema = v.pipe( 8 v.string(), 9 v.regex(/^[a-zA-Z][a-zA-Z0-9-]*\.[a-zA-Z][a-zA-Z0-9-]*\.[a-zA-Z][a-zA-Z0-9-]*$/), 10 v.check( 11 (c) => permissions.collections.some((allowed) => c === allowed || allowed.startsWith(c + '?')), 12 'Collection not in allowed list' 13 ) 14); 15 16// AT Protocol rkey: TID, 'self', or other valid record keys (alphanumeric, dash, underscore, dot) 17const rkeySchema = v.optional(v.pipe(v.string(), v.regex(/^[a-zA-Z0-9._:~-]{1,512}$/))); 18 19export const putRecord = command( 20 v.object({ 21 collection: collectionSchema, 22 rkey: rkeySchema, 23 record: v.record(v.string(), v.unknown()) 24 }), 25 async (input) => { 26 const { locals } = getRequestEvent(); 27 if (!locals.client || !locals.did) error(401, 'Not authenticated'); 28 29 const response = await locals.client.post('com.atproto.repo.putRecord', { 30 input: { 31 collection: input.collection as `${string}.${string}.${string}`, 32 repo: locals.did, 33 rkey: input.rkey || 'self', 34 record: input.record 35 } 36 }); 37 38 return response.data; 39 } 40); 41 42export const deleteRecord = command( 43 v.object({ 44 collection: collectionSchema, 45 rkey: rkeySchema 46 }), 47 async (input) => { 48 const { locals } = getRequestEvent(); 49 if (!locals.client || !locals.did) error(401, 'Not authenticated'); 50 51 const response = await locals.client.post('com.atproto.repo.deleteRecord', { 52 input: { 53 collection: input.collection as `${string}.${string}.${string}`, 54 repo: locals.did, 55 rkey: input.rkey || 'self' 56 } 57 }); 58 59 return { ok: response.ok }; 60 } 61); 62 63export const uploadBlob = command( 64 v.object({ 65 blob: v.instance(Blob) 66 }), 67 async (input) => { 68 const { locals } = getRequestEvent(); 69 if (!locals.client || !locals.did) error(401, 'Not authenticated'); 70 71 const response = await locals.client.post('com.atproto.repo.uploadBlob', { 72 params: { repo: locals.did }, 73 input: input.blob 74 }); 75 76 if (!response.ok) error(500, 'Upload failed'); 77 78 return response.data.blob as { 79 $type: 'blob'; 80 ref: { $link: string }; 81 mimeType: string; 82 size: number; 83 }; 84 } 85);