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
+38 -40
View File
@@ -1,4 +1,5 @@
import {type AppBskyFeedDefs, AppBskyFeedThreadgate, AtUri} from '@atproto/api'
import {type Client} from '@atproto/lex-client'
import {AtUri} from '@atproto/syntax'
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
import {networkRetry, retry} from '#/lib/async/retry'
@@ -12,8 +13,9 @@ import {
threadgateViewToAllowUISetting,
} from '#/state/queries/threadgate/util'
import {useUpdatePostThreadThreadgateQueryCache} from '#/state/queries/usePostThread'
import {type SessionAgent, useAgent} from '#/state/session'
import {usePdsClient} from '#/state/session'
import {useThreadgateHiddenReplyUrisAPI} from '#/state/threadgate-hidden-replies'
import {app, com} from '#/lexicons'
import * as bsky from '#/types/bsky'
export * from '#/state/queries/threadgate/types'
@@ -35,9 +37,9 @@ export function useThreadgateRecordQuery({
initialData,
}: {
postUri?: string
initialData?: AppBskyFeedThreadgate.Record
initialData?: app.bsky.feed.threadgate.Main
} = {}) {
const agent = useAgent()
const pdsClient = usePdsClient()
return useQuery({
enabled: !!postUri,
@@ -46,7 +48,7 @@ export function useThreadgateRecordQuery({
staleTime: STALE.MINUTES.ONE,
async queryFn() {
return getThreadgateRecord({
agent,
pdsClient,
postUri: postUri!,
})
},
@@ -63,7 +65,7 @@ export function useThreadgateViewQuery({
initialData,
}: {
postUri?: string
initialData?: AppBskyFeedDefs.ThreadgateView
initialData?: app.bsky.feed.defs.ThreadgateView
} = {}) {
const getPost = useGetPost()
@@ -80,24 +82,23 @@ export function useThreadgateViewQuery({
}
export async function getThreadgateRecord({
agent,
pdsClient,
postUri,
}: {
agent: SessionAgent
pdsClient: Client
postUri: string
}): Promise<AppBskyFeedThreadgate.Record | null> {
}): Promise<app.bsky.feed.threadgate.Main | null> {
const urip = new AtUri(postUri)
if (!urip.host.startsWith('did:')) {
const res = await agent.resolveHandle({
handle: urip.host,
const {did} = await pdsClient.call(com.atproto.identity.resolveHandle, {
handle: urip.host as `${string}.${string}`,
})
// @ts-expect-error TODO new-sdk-migration
urip.host = res.data.did
urip.host = did
}
try {
const {data} = await retry(
const data = await retry(
2,
e => {
/*
@@ -111,17 +112,14 @@ export async function getThreadgateRecord({
return true
},
() =>
agent.api.com.atproto.repo.getRecord({
pdsClient.call(com.atproto.repo.getRecord, {
repo: urip.host,
collection: 'app.bsky.feed.threadgate',
rkey: urip.rkey,
}),
)
if (
data.value &&
bsky.validate(data.value, AppBskyFeedThreadgate.validateRecord)
) {
if (data.value && bsky.matches(app.bsky.feed.threadgate, data.value)) {
return data.value
} else {
return null
@@ -141,13 +139,13 @@ export async function getThreadgateRecord({
}
export async function writeThreadgateRecord({
agent,
pdsClient,
postUri,
threadgate,
}: {
agent: SessionAgent
pdsClient: Client
postUri: string
threadgate: AppBskyFeedThreadgate.Record
threadgate: app.bsky.feed.threadgate.Main
}) {
const postUrip = new AtUri(postUri)
const record = createThreadgateRecord({
@@ -157,8 +155,8 @@ export async function writeThreadgateRecord({
})
await networkRetry(2, () =>
agent.api.com.atproto.repo.putRecord({
repo: agent.session!.did,
pdsClient.call(com.atproto.repo.putRecord, {
repo: pdsClient.assertDid,
collection: 'app.bsky.feed.threadgate',
rkey: postUrip.rkey,
record,
@@ -168,25 +166,25 @@ export async function writeThreadgateRecord({
export async function upsertThreadgate(
{
agent,
pdsClient,
postUri,
}: {
agent: SessionAgent
pdsClient: Client
postUri: string
},
callback: (
threadgate: AppBskyFeedThreadgate.Record | null,
) => Promise<AppBskyFeedThreadgate.Record | undefined>,
threadgate: app.bsky.feed.threadgate.Main | null,
) => Promise<app.bsky.feed.threadgate.Main | undefined>,
) {
const prev = await getThreadgateRecord({
agent,
pdsClient,
postUri,
})
const next = await callback(prev)
if (!next) return
validateThreadgateRecordOrThrow(next)
await writeThreadgateRecord({
agent,
pdsClient,
postUri,
threadgate: next,
})
@@ -196,15 +194,15 @@ export async function upsertThreadgate(
* Update the allow list for a threadgate record.
*/
export async function updateThreadgateAllow({
agent,
pdsClient,
postUri,
allow,
}: {
agent: SessionAgent
pdsClient: Client
postUri: string
allow: ThreadgateAllowUISetting[]
}) {
return upsertThreadgate({agent, postUri}, async prev => {
return upsertThreadgate({pdsClient, postUri}, async prev => {
if (prev) {
return {
...prev,
@@ -220,7 +218,7 @@ export async function updateThreadgateAllow({
}
export function useSetThreadgateAllowMutation() {
const agent = useAgent()
const pdsClient = usePdsClient()
const queryClient = useQueryClient()
const getPost = useGetPost()
const updatePostThreadThreadgate = useUpdatePostThreadThreadgateQueryCache()
@@ -233,7 +231,7 @@ export function useSetThreadgateAllowMutation() {
postUri: string
allow: ThreadgateAllowUISetting[]
}) => {
return upsertThreadgate({agent, postUri}, async prev => {
return upsertThreadgate({pdsClient, postUri}, async prev => {
if (prev) {
return {
...prev,
@@ -248,7 +246,7 @@ export function useSetThreadgateAllowMutation() {
})
},
async onSuccess(_, {postUri, allow}) {
const data = await retry<AppBskyFeedDefs.ThreadgateView | undefined>(
const data = await retry<app.bsky.feed.defs.ThreadgateView | undefined>(
5, // 5 tries
_e => true,
async () => {
@@ -285,7 +283,7 @@ export function useSetThreadgateAllowMutation() {
}
export function useToggleReplyVisibilityMutation() {
const agent = useAgent()
const pdsClient = usePdsClient()
const queryClient = useQueryClient()
const hiddenReplies = useThreadgateHiddenReplyUrisAPI()
@@ -305,7 +303,7 @@ export function useToggleReplyVisibilityMutation() {
hiddenReplies.removeHiddenReplyUri(replyUri)
}
await upsertThreadgate({agent, postUri}, async prev => {
await upsertThreadgate({pdsClient, postUri}, async prev => {
if (prev) {
if (action === 'hide') {
return mergeThreadgateRecords(prev, {
@@ -358,9 +356,9 @@ export class InvalidInteractionSettingsError extends Error {
}
export function validateThreadgateRecordOrThrow(
record: AppBskyFeedThreadgate.Record,
record: app.bsky.feed.threadgate.Main,
) {
const result = AppBskyFeedThreadgate.validateRecord(record)
const result = bsky.safeParse(app.bsky.feed.threadgate, record)
if (result.success) {
if ((result.value.hiddenReplies?.length ?? 0) > MAX_HIDDEN_REPLIES) {