migrate runtime call sites to lex clients and sdk actions

Phase 3 tasks 3-7 (parallel wave): composer/post pipeline on
pdsClient/appviewClient with structural+instance blob guards and a golden
CID fixture test; chat Convo/EventBus/queries on the dedicated chat client;
preferences sugar to SDK actions on the PDS client; remaining state/queries
producers (usePostThread unspecced flip, video scoped-token clients,
notifications, starter packs, lists) to client.call; UI runtime sweep
(AtUri from @atproto/syntax, moderation fns from @bsky.app/sdk/moderation,
SDK RichText, ozone reason tokens, guard rewrites via #/types/bsky).

Intermediate checkpoint (hooks skipped): ~114 typecheck errors remain in
cross-boundary consumer files, resolved by the type-only codemod next.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-07-16 21:04:44 +03:00
parent b1a4e1cd16
commit 300a50b69a
296 changed files with 4507 additions and 3903 deletions
+32 -8
View File
@@ -1,38 +1,62 @@
import {copyAsync} from 'expo-file-system/legacy'
import {type Agent, type ComAtprotoRepoUploadBlob} from '@atproto/api'
import {type BlobRef} from '@atproto/lex'
import {type Client, type EncodingString} from '@atproto/lex-client'
import {safeDeleteAsync} from '#/lib/media/manip'
/**
* @param encoding Allows overriding the blob's type
* The blob-upload response body: `{blob}`. lex `Client.uploadBlob` returns the
* full XRPC response, so callers read `res.body.blob` (the parsed blob ref).
*/
type UploadBlobResult = {blob: BlobRef}
/**
* @param encoding Allows overriding the blob's type. Passed as the lex upload
* option (NEVER a content-type header - lex-client throws if the encoding is
* set via headers).
*/
export async function uploadBlob(
agent: Agent,
client: Client,
input: string | Blob,
encoding?: string,
): Promise<ComAtprotoRepoUploadBlob.Response> {
): Promise<UploadBlobResult> {
if (typeof input === 'string' && input.startsWith('file:')) {
const blob = await asBlob(input)
return agent.uploadBlob(blob, {encoding})
return uploadBlobResult(client, blob, encoding)
}
if (typeof input === 'string' && input.startsWith('/')) {
const blob = await asBlob(`file://${input}`)
return agent.uploadBlob(blob, {encoding})
return uploadBlobResult(client, blob, encoding)
}
if (typeof input === 'string' && input.startsWith('data:')) {
const blob = await fetch(input).then(r => r.blob())
return agent.uploadBlob(blob, {encoding})
return uploadBlobResult(client, blob, encoding)
}
if (input instanceof Blob) {
return agent.uploadBlob(input, {encoding})
return uploadBlobResult(client, input, encoding)
}
throw new TypeError(`Invalid uploadBlob input: ${typeof input}`)
}
async function uploadBlobResult(
client: Client,
blob: Blob,
encoding?: string,
): Promise<UploadBlobResult> {
/*
* The lex encoding option is a branded mime string (`${string}/${string}`);
* callers pass a plain mime string, so assert the brand here.
*/
const res = await client.uploadBlob(blob, {
encoding: encoding as EncodingString | undefined,
})
return {blob: res.body.blob}
}
async function asBlob(uri: string): Promise<Blob> {
return withSafeFile(uri, async safeUri => {
// Note