Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697import { error } from "@sveltejs/kit";import { ok } from "@atcute/client";import { isBlob } from "@atcute/lexicons/interfaces";import { mainSchema as uploadBlobSchema } from "@atcute/atproto/types/repo/uploadBlob";import type { Did, ResourceUri } from "@atcute/lexicons/syntax";import type { OAuthUserAgent } from "@atcute/oauth-browser-client";import { createClient } from "$lib/auth/agent";import { awaitDeletedRecord, awaitIndexedOrSaved } from "$lib/api/awaitRecord";import type { BobbinContext } from "$lib/api/client";import { resolveMiniDoc } from "$lib/api/identity";import { orNull } from "$lib/api/load";import { getString, type RecordView, type StringRecord } from "$lib/api/records";import { cidOf, nsidOf, recordKeyOf } from "$lib/api/syntax";import { rkeyFromUri } from "$lib/api/uri";import { deleteRecord, putRecord, type WrittenRecord } from "$lib/api/write";
const STRING_COLLECTION = nsidOf("org.tangled.snippet.string");
export interface StringSubject { did: Did; handle: string; pds: string; uri: ResourceUri; record: RecordView<StringRecord>;}
export const loadStringSubject = async ( ctx: BobbinContext, handle: string, rkey: string): Promise<StringSubject> => { const doc = await orNull(resolveMiniDoc(ctx, handle)); if (!doc) error(404, "String not found");
const uri = `at://${doc.did}/${STRING_COLLECTION}/${rkey}` as ResourceUri; const record = await orNull(getString(ctx, uri)); if (!record) error(404, "String not found");
return { did: doc.did as Did, handle: doc.handle, pds: doc.pds, uri, record };};
// bobbin indexes the record only; the content blob lives on the owner's pdsexport const fetchStringContents = async ( fetch: typeof globalThis.fetch, { did, pds, record }: StringSubject): Promise<string> => { const url = new URL("/xrpc/com.atproto.sync.getBlob", pds); url.searchParams.set("did", did); const { content } = record.value.snippet; url.searchParams.set("cid", isBlob(content) ? content.ref.$link : content.cid); const res = await fetch(url); if (!res.ok) error(502, "String contents unavailable"); return res.text();};
export const uploadStringContents = async ( agent: OAuthUserAgent, contents: string): Promise<StringRecord["snippet"]["content"]> => { const input = new Blob([contents], { type: "text/plain" }); const { blob } = await ok(createClient(agent).call(uploadBlobSchema, { input })); return blob;};
export const putString = async ( agent: OAuthUserAgent, bobbin: BobbinContext, rkey: string, record: StringRecord, swapRecord?: string): Promise<WrittenRecord> => { const written = await putRecord( agent, STRING_COLLECTION, recordKeyOf(rkey), record, swapRecord ? cidOf(swapRecord) : undefined ); await awaitIndexedOrSaved(bobbin, written); return written;};
export const deleteString = async ( agent: OAuthUserAgent, bobbin: BobbinContext, uri: ResourceUri, swapRecord?: string): Promise<boolean> => { await deleteRecord( agent, STRING_COLLECTION, rkeyFromUri(uri), swapRecord ? cidOf(swapRecord) : undefined ); return awaitDeletedRecord(bobbin, uri);};