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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user