import { ok } from "@atcute/client"; import { mainSchema as createRecordSchema } from "@atcute/atproto/types/repo/createRecord"; import { mainSchema as getRecordSchema } from "@atcute/atproto/types/repo/getRecord"; import { mainSchema as deleteRecordSchema } from "@atcute/atproto/types/repo/deleteRecord"; import { mainSchema as putRecordSchema } from "@atcute/atproto/types/repo/putRecord"; import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; import { createClient } from "#lib/auth/agent.ts"; import { clear } from "#lib/api/cache.ts"; import { atUriOf, cidOf, type AtUri, type Cid, type Nsid, type Rkey } from "#lib/api/syntax.ts"; export interface WrittenRecord { uri: AtUri; cid: Cid; } interface ReadRecord { value: T; /** getRecord returns cid only when present, null can't be used as swapRecord */ written: WrittenRecord | null; } export const readRecord = async ( agent: OAuthUserAgent, collection: Nsid, rkey: Rkey ): Promise | null> => { const response = await createClient(agent).call(getRecordSchema, { params: { repo: agent.sub, collection, rkey } }); if (response.ok) return { value: response.data.value as T, written: response.data.cid ? { uri: atUriOf(response.data.uri), cid: cidOf(response.data.cid) } : null }; const error = (response.data as { error?: string } | undefined)?.error; if (error === "RecordNotFound" || error === "CouldNotFindRecord") return null; await ok(response); return null; }; // every record write in the app goes through here, so the read cache is dropped // on any mutation instead of each write site remembering which keys it dirties export const createRecord = async ( agent: OAuthUserAgent, collection: Nsid, record: T, rkey?: Rkey ): Promise => { const { uri, cid } = await ok( createClient(agent).call(createRecordSchema, { input: { repo: agent.sub, collection, ...(rkey ? { rkey } : {}), record } }) ); clear(); return { uri: atUriOf(uri), cid: cidOf(cid) }; }; export const putRecord = async ( agent: OAuthUserAgent, collection: Nsid, rkey: Rkey, record: T, // the write fails if the record moved since it was read swapRecord?: Cid ): Promise => { const { uri, cid } = await ok( createClient(agent).call(putRecordSchema, { input: { repo: agent.sub, collection, rkey, ...(swapRecord ? { swapRecord } : {}), record } }) ); clear(); return { uri: atUriOf(uri), cid: cidOf(cid) }; }; export const deleteRecord = async ( agent: OAuthUserAgent, collection: Nsid, rkey: Rkey, swapRecord?: Cid ): Promise => { await ok( createClient(agent).call(deleteRecordSchema, { input: { repo: agent.sub, collection, rkey, ...(swapRecord ? { swapRecord } : {}) } }) ); clear(); };