From 1dd74500f2ea43de2b2e955cf5cf1762e4b5af07 Mon Sep 17 00:00:00 2001 From: Charlotte Som Date: Sat, 7 Jun 2025 04:20:00 +0100 Subject: [PATCH] use lexicon.ts rpc on the client --- client/viewer.tsx | 50 ++++++++++++++++++++++++++-------------------- common/identity.ts | 2 +- deno.json | 4 +++- vendor/lexicon.ts | 2 +- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/client/viewer.tsx b/client/viewer.tsx index 2c6ecb5..f9bd5ba 100644 --- a/client/viewer.tsx +++ b/client/viewer.tsx @@ -4,42 +4,47 @@ import type { VideoLexiconUniverse } from "../common/lexicons.ts"; import { resolveDid, resolveHandle } from "../common/identity.ts"; import { VIDEO_PATTERN } from "../common/routes.ts"; +import type { ATProtoUniverse } from "@char/lexicon.ts/atproto"; +import { XRPC } from "@char/lexicon.ts/rpc"; + type VideoRecord = Infer; const fetchVideoRecord = async ( did: string, rkey: string ): Promise => { - // TODO: we do lots of casting here that we shouldn't need once we have lexicon.ts validations - const didDoc = await resolveDid(did); const pds = didDoc.service?.find((it) => it.id === "#atproto_pds") ?.serviceEndpoint as string | undefined; if (!pds) throw new Error("could not resolve pds for requested repo"); - const getRecordURL = new URL("/xrpc/com.atproto.repo.getRecord", pds); - getRecordURL.searchParams.set("collection", "blue.cerulea.video.video"); - getRecordURL.searchParams.set("repo", did); - getRecordURL.searchParams.set("rkey", rkey); + const xrpc = new XRPC(pds); + const record = await xrpc.get("com.atproto.repo.getRecord", { + parameters: { + collection: "blue.cerulea.video.video", + repo: did, + rkey, + }, + }); - const recordResponse = await fetch(getRecordURL); - if (recordResponse.status !== 200) - throw new Error("got error fetching record"); - - const record = (await recordResponse.json()).value as VideoRecord; - return record; + // TODO: replace this cast with a lexicon.ts validation check + return record.value as VideoRecord; }; -const resolveVideoURL = async (did: string, blob: string): Promise => { - const res = await fetch("/xrpc/blue.cerulea.video.fetchVideo", { - method: "POST", - headers: { "content-encoding": "application/json" }, - body: JSON.stringify({ repo: did, blob }), - }); - if (res.status !== 200) throw new Error("got error fetching video cdn url"); - const data = await res.json(); - return `/user-content/${data.filename}`; +const resolveVideoURL = async ( + did: `did:${string}`, + blob: string +): Promise => { + const xrpc = new XRPC(globalThis.location.href); + try { + const res = await xrpc.call("blue.cerulea.video.fetchVideo", { + input: { repo: did, blob }, + }); + return `/user-content/${res.filename}`; + } catch { + throw new Error("got error fetching URL of video at CDN"); + } }; const main = async () => { @@ -52,7 +57,8 @@ const main = async () => { rkey: string; }; - const did = repo.startsWith("did:") ? repo : await resolveHandle(repo); + const isDid = (s: string): s is `did:${string}` => s.startsWith("did:"); + const did = isDid(repo) ? repo : await resolveHandle(repo); const record = await fetchVideoRecord(did, rkey); const videoURL = await resolveVideoURL( diff --git a/common/identity.ts b/common/identity.ts index 309a9e8..8c2ba63 100644 --- a/common/identity.ts +++ b/common/identity.ts @@ -17,7 +17,7 @@ const didResolver = new CompositeDidDocumentResolver({ }, }); -export function resolveHandle(handle: string): Promise { +export function resolveHandle(handle: string): Promise<`did:${string}`> { return handleResolver.resolve(handle as `${string}.${string}`); } diff --git a/deno.json b/deno.json index 0e7091f..3116ba9 100644 --- a/deno.json +++ b/deno.json @@ -13,7 +13,9 @@ "@std/http": "jsr:@std/http@^1.0.17", "@std/path": "jsr:@std/path@^1.1.0", "@zod/mini": "npm:@zod/mini@^4.0.0-beta.20250505T195954", - "@char/lexicon.ts": "./vendor/lexicon.ts/lib/mod.ts" + "@char/lexicon.ts": "./vendor/lexicon.ts/lib/mod.ts", + "@char/lexicon.ts/atproto": "./vendor/lexicon.ts/pkg/atproto-lexica/mod.ts", + "@char/lexicon.ts/rpc": "./vendor/lexicon.ts/pkg/rpc/rpc.ts" }, "compilerOptions": { "lib": ["deno.window", "dom"], diff --git a/vendor/lexicon.ts b/vendor/lexicon.ts index f070c8b..1edb68e 160000 --- a/vendor/lexicon.ts +++ b/vendor/lexicon.ts @@ -1 +1 @@ -Subproject commit f070c8b56df7d3335a970118a401dfd7ee2f63f2 +Subproject commit 1edb68e5eac3ddfabdd77674ed8193ef9af05649