Use new endpoints for suggested users (#10185)

This commit is contained in:
DS Boyce
2026-04-07 13:10:23 -07:00
committed by GitHub
parent 3c21fee6c2
commit a049a6538c
12 changed files with 219 additions and 238 deletions
+1 -1
View File
@@ -81,7 +81,7 @@
"icons:optimize": "svgo -f ./assets/icons"
},
"dependencies": {
"@atproto/api": "^0.19.5",
"@atproto/api": "^0.19.6",
"@bitdrift/react-native": "^0.6.8",
"@braintree/sanitize-url": "^6.0.2",
"@bsky.app/alf": "^0.1.7",
+11 -104
View File
@@ -7,7 +7,7 @@ import Animated, {
LayoutAnimationConfig,
LinearTransition,
} from 'react-native-reanimated'
import {type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {type AppBskyFeedDefs} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro'
import {useNavigation} from '@react-navigation/native'
@@ -15,11 +15,9 @@ import {type NavigationProp} from '#/lib/routes/types'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useGetPopularFeedsQuery} from '#/state/queries/feed'
import {type FeedDescriptor} from '#/state/queries/post-feed'
import {useProfilesQuery} from '#/state/queries/profile'
import {useSuggestedFollowsByActorWithDismiss} from '#/state/queries/suggested-follows'
import {useGetSuggestedUsersForDiscoverQuery} from '#/state/queries/trending/useGetSuggestedUsersForDiscoverQuery'
import {useSession} from '#/state/session'
import * as userActionHistory from '#/state/userActionHistory'
import {type SeenPost} from '#/state/userActionHistory'
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
import {
atoms as a,
@@ -37,12 +35,12 @@ import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Has
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
import {InlineLinkText} from '#/components/Link'
import * as ProfileCard from '#/components/ProfileCard'
import {ProgressGuideList} from '#/components/ProgressGuide/List'
import {Text} from '#/components/Typography'
import {type Metrics, useAnalytics} from '#/analytics'
import {IS_IOS} from '#/env'
import type * as bsky from '#/types/bsky'
import {FollowDialogWithoutGuide} from './ProgressGuide/FollowDialog'
import {ProgressGuideList} from './ProgressGuide/List'
const DISMISS_ANIMATION_DURATION = 200
@@ -109,95 +107,6 @@ export function SuggestedFeedsCardPlaceholder() {
)
}
function getRank(seenPost: SeenPost): string {
let tier: string
if (seenPost.feedContext === 'popfriends') {
tier = 'a'
} else if (seenPost.feedContext?.startsWith('cluster')) {
tier = 'b'
} else if (seenPost.feedContext === 'popcluster') {
tier = 'c'
} else if (seenPost.feedContext?.startsWith('ntpc')) {
tier = 'd'
} else if (seenPost.feedContext?.startsWith('t-')) {
tier = 'e'
} else if (seenPost.feedContext === 'nettop') {
tier = 'f'
} else {
tier = 'g'
}
let score = Math.round(
Math.log(
1 + seenPost.likeCount + seenPost.repostCount + seenPost.replyCount,
),
)
if (seenPost.isFollowedBy || Math.random() > 0.9) {
score *= 2
}
const rank = 100 - score
return `${tier}-${rank}`
}
function sortSeenPosts(postA: SeenPost, postB: SeenPost): 0 | 1 | -1 {
const rankA = getRank(postA)
const rankB = getRank(postB)
// Yes, we're comparing strings here.
// The "larger" string means a worse rank.
if (rankA > rankB) {
return 1
} else if (rankA < rankB) {
return -1
} else {
return 0
}
}
function useExperimentalSuggestedUsersQuery() {
const {currentAccount} = useSession()
const userActionSnapshot = userActionHistory.useActionHistorySnapshot()
const dids = useMemo(() => {
const {likes, follows, followSuggestions, seen} = userActionSnapshot
const likeDids = likes
.map(l => new AtUri(l))
.map(uri => uri.host)
.filter(did => !follows.includes(did))
let suggestedDids: string[] = []
if (followSuggestions.length > 0) {
suggestedDids = [
// It's ok if these will pick the same item (weighed by its frequency)
/* eslint-disable react-hooks/purity */
followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
/* eslint-enable react-hooks/purity */
]
}
const seenDids = seen
.sort(sortSeenPosts)
.map(l => new AtUri(l.uri))
.map(uri => uri.host)
return [...new Set([...suggestedDids, ...likeDids, ...seenDids])].filter(
did => did !== currentAccount?.did,
)
}, [userActionSnapshot, currentAccount])
const {data, isLoading, error} = useProfilesQuery({
handles: dids.slice(0, 16),
})
const profiles = data
? data.profiles.filter(profile => {
return !profile.viewer?.following
})
: []
return {
isLoading,
error,
profiles: profiles.slice(0, 6),
}
}
export function SuggestedFollows({feed}: {feed: FeedDescriptor}) {
const {currentAccount} = useSession()
const [feedType, feedUriOrDid] = feed.split('|')
@@ -229,11 +138,9 @@ export function SuggestedFollowsProfile({did}: {did: string}) {
}
export function SuggestedFollowsHome() {
const {
isLoading: isSuggestionsLoading,
profiles: experimentalProfiles,
error: experimentalError,
} = useExperimentalSuggestedUsersQuery()
const {isLoading, data, error} = useGetSuggestedUsersForDiscoverQuery()
const profiles = data?.actors
const [dismissedDids, setDismissedDids] = useState<Set<string>>(new Set())
@@ -247,12 +154,12 @@ export function SuggestedFollowsHome() {
recId?: string
}> = []
for (const profile of experimentalProfiles) {
result.push({actor: profile, recId: undefined})
for (const profile of profiles ?? []) {
result.push({actor: profile, recId: data?.recId})
}
return result
}, [experimentalProfiles])
}, [data?.recId, profiles])
const filteredProfiles = useMemo(() => {
return allProfiles.filter(p => !dismissedDids.has(p.actor.did))
@@ -260,10 +167,10 @@ export function SuggestedFollowsHome() {
return (
<ProfileGrid
isSuggestionsLoading={isSuggestionsLoading}
isSuggestionsLoading={isLoading}
profiles={filteredProfiles}
totalProfileCount={allProfiles.length}
error={experimentalError}
error={error}
viewContext="feed"
onDismiss={onDismiss}
/>
@@ -8,7 +8,7 @@ import {popularInterests, useInterestsDisplayNames} from '#/lib/interests'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useActorSearch} from '#/state/queries/actor-search'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {useGetSuggestedUsersQuery} from '#/state/queries/trending/useGetSuggestedUsersQuery'
import {useGetSuggestedUsersForSeeMoreQuery} from '#/state/queries/trending/useGetSuggestedUsersForSeeMoreQuery'
import {useSession} from '#/state/session'
import {type Follow10ProgressGuide} from '#/state/shell/progress-guide'
import {type ListMethods} from '#/view/com/util/List'
@@ -141,7 +141,7 @@ function DialogInner({guide}: {guide?: Follow10ProgressGuide}) {
data: suggestions,
isFetching: isFetchingSuggestions,
error: suggestionsError,
} = useGetSuggestedUsersQuery({
} = useGetSuggestedUsersForSeeMoreQuery({
category: selectedInterest,
limit: 50,
})
+6 -5
View File
@@ -28,7 +28,10 @@ import {
createGetSuggestedFeedsQueryKey,
useGetSuggestedFeedsQuery,
} from '#/state/queries/trending/useGetSuggestedFeedsQuery'
import {getSuggestedUsersQueryKeyRoot} from '#/state/queries/trending/useGetSuggestedUsersQuery'
import {
getSuggestedUsersForExploreQueryKeyRoot,
useGetSuggestedUsersForExploreQuery,
} from '#/state/queries/trending/useGetSuggestedUsersForExploreQuery'
import {createGetTrendsQueryKey} from '#/state/queries/trending/useGetTrendsQuery'
import {
createSuggestedStarterPacksQueryKey,
@@ -48,7 +51,6 @@ import {ExploreInterestsCard} from '#/screens/Search/modules/ExploreInterestsCar
import {ExploreRecommendations} from '#/screens/Search/modules/ExploreRecommendations'
import {ExploreTrendingTopics} from '#/screens/Search/modules/ExploreTrendingTopics'
import {ExploreTrendingVideos} from '#/screens/Search/modules/ExploreTrendingVideos'
import {useSuggestedUsers} from '#/screens/Search/util/useSuggestedUsers'
import {atoms as a, native, platform, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {Button} from '#/components/Button'
@@ -242,9 +244,8 @@ export function Explore({
isLoading: suggestedUsersIsLoading,
error: suggestedUsersError,
isRefetching: suggestedUsersIsRefetching,
} = useSuggestedUsers({
} = useGetSuggestedUsersForExploreQuery({
category: selectedInterest || (useFullExperience ? null : interests[0]),
search: !useFullExperience,
})
/* End special language handling */
@@ -316,7 +317,7 @@ export function Explore({
queryKey: createSuggestedStarterPacksQueryKey(),
}),
qc.resetQueries({
queryKey: [getSuggestedUsersQueryKeyRoot],
queryKey: [getSuggestedUsersForExploreQueryKeyRoot],
}),
qc.resetQueries({
queryKey: [useActorSearchQueryKeyRoot],
@@ -1,59 +0,0 @@
import {useMemo} from 'react'
import {useInterestsDisplayNames} from '#/lib/interests'
import {useActorSearch} from '#/state/queries/actor-search'
import {useGetSuggestedUsersQuery} from '#/state/queries/trending/useGetSuggestedUsersQuery'
/**
* Conditional hook, used in case a user is a non-english speaker, in which
* case we fall back to searching for users instead of our more curated set.
*/
export function useSuggestedUsers({
category = null,
search = false,
}: {
category?: string | null
/**
* If true, we'll search for users using the translated value of `category`,
* based on the user's app language setting
*/
search?: boolean
}) {
const interestsDisplayNames = useInterestsDisplayNames()
const curated = useGetSuggestedUsersQuery({
enabled: !search,
category,
})
const searched = useActorSearch({
enabled: !!search,
// use user's app language translation for this value
query: category ? interestsDisplayNames[category] : '',
limit: 10,
})
return useMemo(() => {
if (search) {
return {
// we're not paginating right now
data: searched?.data
? {
actors: searched.data.pages.flatMap(p => p.actors) ?? [],
recId: undefined,
}
: undefined,
isLoading: searched.isLoading,
error: searched.error,
isRefetching: searched.isRefetching,
refetch: searched.refetch,
}
} else {
return {
data: curated.data,
isLoading: curated.isLoading,
error: curated.error,
isRefetching: curated.isRefetching,
refetch: curated.refetch,
}
}
}, [curated, searched, search])
}
+12 -2
View File
@@ -19,7 +19,9 @@ import {
} from '#/state/queries/preferences'
import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
import {createGetSuggestedFeedsQueryKey} from '#/state/queries/trending/useGetSuggestedFeedsQuery'
import {createGetSuggestedUsersQueryKey} from '#/state/queries/trending/useGetSuggestedUsersQuery'
import {createGetSuggestedUsersForDiscoverQueryKey} from '#/state/queries/trending/useGetSuggestedUsersForDiscoverQuery'
import {createGetSuggestedUsersForExploreQueryKey} from '#/state/queries/trending/useGetSuggestedUsersForExploreQuery'
import {createGetSuggestedUsersForSeeMoreQueryKey} from '#/state/queries/trending/useGetSuggestedUsersForSeeMoreQuery'
import {createSuggestedStarterPacksQueryKey} from '#/state/queries/useSuggestedStarterPacksQuery'
import {useAgent} from '#/state/session'
import {atoms as a, useGutters, useTheme} from '#/alf'
@@ -120,7 +122,15 @@ function Inner({
await Promise.all([
qc.resetQueries({queryKey: createSuggestedStarterPacksQueryKey()}),
qc.resetQueries({queryKey: createGetSuggestedFeedsQueryKey()}),
qc.resetQueries({queryKey: createGetSuggestedUsersQueryKey({})}),
qc.resetQueries({
queryKey: createGetSuggestedUsersForDiscoverQueryKey({}),
}),
qc.resetQueries({
queryKey: createGetSuggestedUsersForExploreQueryKey({}),
}),
qc.resetQueries({
queryKey: createGetSuggestedUsersForSeeMoreQueryKey({}),
}),
])
Toast.show(
+6 -2
View File
@@ -26,7 +26,9 @@ import {findAllProfilesInQueryData as findAllProfilesInProfileFollowersQueryData
import {findAllProfilesInQueryData as findAllProfilesInProfileFollowsQueryData} from '#/state/queries/profile-follows'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedFollowsQueryData} from '#/state/queries/suggested-follows'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedOnboardingUsersQueryData} from '#/state/queries/trending/useGetSuggestedOnboardingUsersQuery'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersQueryData} from '#/state/queries/trending/useGetSuggestedUsersQuery'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersForDiscoverQueryData} from '#/state/queries/trending/useGetSuggestedUsersForDiscoverQuery'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersForExploreQueryData} from '#/state/queries/trending/useGetSuggestedUsersForExploreQuery'
import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersForSeeMoreQueryData} from '#/state/queries/trending/useGetSuggestedUsersForSeeMoreQuery'
import {findAllProfilesInQueryData as findAllProfilesInPostThreadV2QueryData} from '#/state/queries/usePostThread/queryCache'
import type * as bsky from '#/types/bsky'
import {castAsShadow, type Shadow} from './types'
@@ -249,7 +251,9 @@ function* findProfilesInCache(
yield* findAllProfilesInProfileFollowersQueryData(queryClient, did)
yield* findAllProfilesInProfileFollowsQueryData(queryClient, did)
yield* findAllProfilesInSuggestedOnboardingUsersQueryData(queryClient, did)
yield* findAllProfilesInSuggestedUsersQueryData(queryClient, did)
yield* findAllProfilesInSuggestedUsersForDiscoverQueryData(queryClient, did)
yield* findAllProfilesInSuggestedUsersForExploreQueryData(queryClient, did)
yield* findAllProfilesInSuggestedUsersForSeeMoreQueryData(queryClient, did)
yield* findAllProfilesInSuggestedFollowsQueryData(queryClient, did)
yield* findAllProfilesInActorSearchQueryData(queryClient, did)
yield* findAllProfilesInListConvosQueryData(queryClient, did)
@@ -5,7 +5,6 @@ import {
import {type QueryClient, useQuery} from '@tanstack/react-query'
import {createBskyTopicsHeader} from '#/lib/api/feed/utils'
import {logger} from '#/logger'
import {getContentLanguages} from '#/state/preferences/languages'
import {STALE} from '#/state/queries'
import {usePreferencesQuery} from '#/state/queries/preferences'
@@ -54,27 +53,8 @@ export function useGetSuggestedOnboardingUsersQuery(props: QueryProps) {
},
},
)
// FALLBACK: if no results for 'all', try again with no interests specified
if (!props.category && data.actors.length === 0) {
logger.error(
`Did not get any suggested onboarding users, falling back - interests: ${overrideInterests}`,
)
const {data: fallbackData} =
await agent.app.bsky.unspecced.getSuggestedOnboardingUsers(
{
category: props.category ?? undefined,
limit: props.limit || 10,
},
{
headers: {
'Accept-Language': contentLangs,
},
},
)
return fallbackData
}
return data
return {...data, recId: data.recIdStr}
},
})
}
@@ -0,0 +1,75 @@
import {
type AppBskyActorDefs,
type AppBskyUnspeccedGetSuggestedUsersForDiscover,
} from '@atproto/api'
import {type QueryClient, useQuery} from '@tanstack/react-query'
import {
aggregateUserInterests,
createBskyTopicsHeader,
} from '#/lib/api/feed/utils'
import {getContentLanguages} from '#/state/preferences/languages'
import {STALE} from '#/state/queries'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {useAgent} from '#/state/session'
export type QueryProps = {
limit?: number
}
export const getSuggestedUsersForDiscoverQueryKeyRoot =
'unspecced-suggested-users-for-explore'
export const createGetSuggestedUsersForDiscoverQueryKey = (
props: QueryProps,
) => [getSuggestedUsersForDiscoverQueryKeyRoot, props.limit]
export function useGetSuggestedUsersForDiscoverQuery(props: QueryProps = {}) {
const agent = useAgent()
const {data: preferences} = usePreferencesQuery()
return useQuery({
staleTime: STALE.MINUTES.THREE,
queryKey: createGetSuggestedUsersForDiscoverQueryKey(props),
queryFn: async () => {
const contentLangs = getContentLanguages().join(',')
const userInterests = aggregateUserInterests(preferences)
const {data} =
await agent.app.bsky.unspecced.getSuggestedUsersForDiscover(
{
limit: props.limit || 10,
},
{
headers: {
...createBskyTopicsHeader(userInterests),
'Accept-Language': contentLangs,
},
},
)
return {...data, recId: data.recIdStr}
},
})
}
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
const responses =
queryClient.getQueriesData<AppBskyUnspeccedGetSuggestedUsersForDiscover.OutputSchema>(
{
queryKey: [getSuggestedUsersForDiscoverQueryKeyRoot],
},
)
for (const [_key, response] of responses) {
if (!response) {
continue
}
for (const actor of response.actors) {
if (actor.did === did) {
yield actor
}
}
}
}
@@ -1,6 +1,6 @@
import {
type AppBskyActorDefs,
type AppBskyUnspeccedGetSuggestedUsers,
type AppBskyUnspeccedGetSuggestedUsersForExplore,
} from '@atproto/api'
import {type QueryClient, useQuery} from '@tanstack/react-query'
@@ -8,7 +8,6 @@ import {
aggregateUserInterests,
createBskyTopicsHeader,
} from '#/lib/api/feed/utils'
import {logger} from '#/logger'
import {getContentLanguages} from '#/state/preferences/languages'
import {STALE} from '#/state/queries'
import {usePreferencesQuery} from '#/state/queries/preferences'
@@ -17,29 +16,26 @@ import {useAgent} from '#/state/session'
export type QueryProps = {
category?: string | null
limit?: number
enabled?: boolean
}
export const getSuggestedUsersQueryKeyRoot = 'unspecced-suggested-users'
export const createGetSuggestedUsersQueryKey = (props: QueryProps) => [
getSuggestedUsersQueryKeyRoot,
props.category,
props.limit,
]
export const getSuggestedUsersForExploreQueryKeyRoot =
'unspecced-suggested-users-for-explore'
export const createGetSuggestedUsersForExploreQueryKey = (
props: QueryProps,
) => [getSuggestedUsersForExploreQueryKeyRoot, props.category, props.limit]
export function useGetSuggestedUsersQuery(props: QueryProps) {
export function useGetSuggestedUsersForExploreQuery(props: QueryProps = {}) {
const agent = useAgent()
const {data: preferences} = usePreferencesQuery()
return useQuery({
enabled: !!preferences && props.enabled !== false,
staleTime: STALE.MINUTES.THREE,
queryKey: createGetSuggestedUsersQueryKey(props),
queryKey: createGetSuggestedUsersForExploreQueryKey(props),
queryFn: async () => {
const contentLangs = getContentLanguages().join(',')
const userInterests = aggregateUserInterests(preferences)
const {data} = await agent.app.bsky.unspecced.getSuggestedUsers(
const {data} = await agent.app.bsky.unspecced.getSuggestedUsersForExplore(
{
category: props.category ?? undefined,
limit: props.limit || 10,
@@ -51,27 +47,8 @@ export function useGetSuggestedUsersQuery(props: QueryProps) {
},
},
)
// FALLBACK: if no results for 'all', try again with no interests specified
if (!props.category && data.actors.length === 0) {
logger.error(
`Did not get any suggested users, falling back - interests: ${userInterests}`,
)
const {data: fallbackData} =
await agent.app.bsky.unspecced.getSuggestedUsers(
{
category: props.category ?? undefined,
limit: props.limit || 10,
},
{
headers: {
'Accept-Language': contentLangs,
},
},
)
return fallbackData
}
return data
return {...data, recId: data.recIdStr}
},
})
}
@@ -81,9 +58,11 @@ export function* findAllProfilesInQueryData(
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
const responses =
queryClient.getQueriesData<AppBskyUnspeccedGetSuggestedUsers.OutputSchema>({
queryKey: [getSuggestedUsersQueryKeyRoot],
})
queryClient.getQueriesData<AppBskyUnspeccedGetSuggestedUsersForExplore.OutputSchema>(
{
queryKey: [getSuggestedUsersForExploreQueryKeyRoot],
},
)
for (const [_key, response] of responses) {
if (!response) {
continue
@@ -0,0 +1,77 @@
import {
type AppBskyActorDefs,
type AppBskyUnspeccedGetSuggestedUsersForSeeMore,
} from '@atproto/api'
import {type QueryClient, useQuery} from '@tanstack/react-query'
import {
aggregateUserInterests,
createBskyTopicsHeader,
} from '#/lib/api/feed/utils'
import {getContentLanguages} from '#/state/preferences/languages'
import {STALE} from '#/state/queries'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {useAgent} from '#/state/session'
export type QueryProps = {
category?: string | null
limit?: number
}
export const getSuggestedUsersForSeeMoreQueryKeyRoot =
'unspecced-suggested-users-for-explore'
export const createGetSuggestedUsersForSeeMoreQueryKey = (
props: QueryProps,
) => [getSuggestedUsersForSeeMoreQueryKeyRoot, props.category, props.limit]
export function useGetSuggestedUsersForSeeMoreQuery(props: QueryProps = {}) {
const agent = useAgent()
const {data: preferences} = usePreferencesQuery()
return useQuery({
staleTime: STALE.MINUTES.THREE,
queryKey: createGetSuggestedUsersForSeeMoreQueryKey(props),
queryFn: async () => {
const contentLangs = getContentLanguages().join(',')
const userInterests = aggregateUserInterests(preferences)
const {data} = await agent.app.bsky.unspecced.getSuggestedUsersForSeeMore(
{
category: props.category ?? undefined,
limit: props.limit || 50,
},
{
headers: {
...createBskyTopicsHeader(userInterests),
'Accept-Language': contentLangs,
},
},
)
return {...data, recId: data.recIdStr}
},
})
}
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
const responses =
queryClient.getQueriesData<AppBskyUnspeccedGetSuggestedUsersForSeeMore.OutputSchema>(
{
queryKey: [getSuggestedUsersForSeeMoreQueryKeyRoot],
},
)
for (const [_key, response] of responses) {
if (!response) {
continue
}
for (const actor of response.actors) {
if (actor.did === did) {
yield actor
}
}
}
}
+13 -6
View File
@@ -20,14 +20,14 @@
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
"@atproto/api@^0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.19.5.tgz#6388e5d6d3a1693fe04b5f37c705682bac8601d3"
integrity sha512-u6R5TecYJDO8l8QFN09AMuJASYnUkJ4HhYE5hg4/dha/z14a+OAil2/dli/208uM5AHPFLtlnB8kIK9XU5GgQQ==
"@atproto/api@^0.19.6":
version "0.19.6"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.19.6.tgz#c8fae3d792fe429c900ac0ba2609d60b9a89e28b"
integrity sha512-8L5dZvGaclB52b8msjtgDNx3uLWUY4PELA7KbFyAWBFVasCceE1txdrscCqDCLN+Fff9+Sm07OIjnjHYJXdETA==
dependencies:
"@atproto/common-web" "^0.4.19"
"@atproto/lexicon" "^0.6.2"
"@atproto/syntax" "^0.5.2"
"@atproto/syntax" "^0.5.3"
"@atproto/xrpc" "^0.7.7"
await-lock "^2.2.2"
multiformats "^9.9.0"
@@ -73,13 +73,20 @@
multiformats "^9.9.0"
zod "^3.23.8"
"@atproto/syntax@^0.5.0", "@atproto/syntax@^0.5.1", "@atproto/syntax@^0.5.2":
"@atproto/syntax@^0.5.0", "@atproto/syntax@^0.5.1":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.5.2.tgz#d4b32c9feb421ceeb5ade1fa80bc42764d51e52e"
integrity sha512-W41szOnkppoHr0iCUrzL8gy3OD6qmDyp1UvUgmTx2oFQfgbudpz51T/gznesiCcqiUT5obfHdx4PJ+WdlEOE7Q==
dependencies:
tslib "^2.8.1"
"@atproto/syntax@^0.5.3":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.5.3.tgz#4331d01f63fe56c374dcf95d4432a22b62271a17"
integrity sha512-gzhlHOJHm5KXdCc17fXi1fXM81ccs5jJfNgCui84ay9JGvczxegpYHNqdMlv+iBuhtBzFIjgx6ChjRxN/kO8kQ==
dependencies:
tslib "^2.8.1"
"@atproto/xrpc@^0.7.7":
version "0.7.7"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.7.7.tgz#c0e3106c854cb9bc7d3129de2f31b8256eb0ed11"