rework imports

This commit is contained in:
Oleksii Bulenok
2026-08-20 15:49:04 +02:00
parent 39e487cbb7
commit cb3245e8e8
245 changed files with 2453 additions and 2256 deletions
+4 -3
View File
@@ -7,11 +7,12 @@ import {
} from '@atproto/lex'
import {describe, expect, it} from '@jest/globals'
import {app, com} from '#/lexicons'
import * as AppBskyUnspeccedGetTrends from '#/lexicons/app/bsky/unspecced/getTrends'
import * as ComAtprotoServerCreateAccount from '#/lexicons/com/atproto/server/createAccount'
import {matchXrpcError} from '../xrpc-error'
const createAccount = com.atproto.server.createAccount
const getTrends = app.bsky.unspecced.getTrends
const createAccount = ComAtprotoServerCreateAccount
const getTrends = AppBskyUnspeccedGetTrends
/**
* An `XrpcResponseError` as a lex `Client` would construct it: the method
+42 -41
View File
@@ -1,10 +1,14 @@
import {app} from '#/lexicons'
import type * as AppBskyActorDefs from '#/lexicons/app/bsky/actor/defs'
import * as AppBskyEmbedRecord from '#/lexicons/app/bsky/embed/record'
import * as AppBskyEmbedRecordWithMedia from '#/lexicons/app/bsky/embed/recordWithMedia'
import * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedPost from '#/lexicons/app/bsky/feed/post'
import * as bsky from '#/types/bsky'
import {isPostInLanguage} from '../../locale/helpers'
import {FALLBACK_MARKER_POST} from './feed/home'
import {type ReasonFeedSource} from './feed/types'
type FeedViewPost = app.bsky.feed.defs.FeedViewPost
type FeedViewPost = AppBskyFeedDefs.FeedViewPost
export type FeedTunerFn = (
tuner: FeedTuner,
@@ -13,18 +17,18 @@ export type FeedTunerFn = (
) => FeedViewPostsSlice[]
type FeedSliceItem = {
post: app.bsky.feed.defs.PostView
record: app.bsky.feed.post.Main
parentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
post: AppBskyFeedDefs.PostView
record: AppBskyFeedPost.Main
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
isParentBlocked: boolean
isParentNotFound: boolean
}
type AuthorContext = {
author: app.bsky.actor.defs.ProfileViewBasic
parentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
grandparentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
rootAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
author: AppBskyActorDefs.ProfileViewBasic
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
grandparentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
rootAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
}
export class FeedViewPostsSlice {
@@ -46,7 +50,7 @@ export class FeedViewPostsSlice {
this.isOrphan = false
this.isThreadMuted = post.viewer?.threadMuted ?? false
this.feedPostUri = post.uri
if (bsky.isType(app.bsky.feed.defs.postView, reply?.root)) {
if (bsky.isType(AppBskyFeedDefs.postView, reply?.root)) {
this.rootUri = reply.root.uri
} else {
this.rootUri = post.uri
@@ -62,19 +66,16 @@ export class FeedViewPostsSlice {
return
}
if (
!bsky.isType(app.bsky.feed.post, post.record) ||
!bsky.matches(app.bsky.feed.post, post.record)
!bsky.isType(AppBskyFeedPost, post.record) ||
!bsky.matches(AppBskyFeedPost, post.record)
) {
return
}
const parent = reply?.parent
const isParentBlocked = bsky.isType(app.bsky.feed.defs.blockedPost, parent)
const isParentNotFound = bsky.isType(
app.bsky.feed.defs.notFoundPost,
parent,
)
let parentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
if (bsky.isType(app.bsky.feed.defs.postView, parent)) {
const isParentBlocked = bsky.isType(AppBskyFeedDefs.blockedPost, parent)
const isParentNotFound = bsky.isType(AppBskyFeedDefs.notFoundPost, parent)
let parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
if (bsky.isType(AppBskyFeedDefs.postView, parent)) {
parentAuthor = parent.author
}
this.items.push({
@@ -96,18 +97,18 @@ export class FeedViewPostsSlice {
return
}
if (
!bsky.isType(app.bsky.feed.defs.postView, parent) ||
!bsky.isType(app.bsky.feed.post, parent.record) ||
!bsky.matches(app.bsky.feed.post, parent.record)
!bsky.isType(AppBskyFeedDefs.postView, parent) ||
!bsky.isType(AppBskyFeedPost, parent.record) ||
!bsky.matches(AppBskyFeedPost, parent.record)
) {
this.isOrphan = true
return
}
const root = reply.root
const rootIsView =
bsky.isType(app.bsky.feed.defs.postView, root) ||
bsky.isType(app.bsky.feed.defs.blockedPost, root) ||
bsky.isType(app.bsky.feed.defs.notFoundPost, root)
bsky.isType(AppBskyFeedDefs.postView, root) ||
bsky.isType(AppBskyFeedDefs.blockedPost, root) ||
bsky.isType(AppBskyFeedDefs.notFoundPost, root)
/*
* If the parent is also the root, we just so happen to have the data we
* need to compute if the parent's parent (grandparent) is blocked. This
@@ -120,10 +121,10 @@ export class FeedViewPostsSlice {
: undefined
const grandparentAuthor = reply.grandparentAuthor
const isGrandparentBlocked = Boolean(
grandparent && bsky.isType(app.bsky.feed.defs.blockedPost, grandparent),
grandparent && bsky.isType(AppBskyFeedDefs.blockedPost, grandparent),
)
const isGrandparentNotFound = Boolean(
grandparent && bsky.isType(app.bsky.feed.defs.notFoundPost, grandparent),
grandparent && bsky.isType(AppBskyFeedDefs.notFoundPost, grandparent),
)
this.items.unshift({
post: parent,
@@ -138,9 +139,9 @@ export class FeedViewPostsSlice {
// de-deduping
}
if (
!bsky.isType(app.bsky.feed.defs.postView, root) ||
!bsky.isType(app.bsky.feed.post, root.record) ||
!bsky.matches(app.bsky.feed.post, root.record)
!bsky.isType(AppBskyFeedDefs.postView, root) ||
!bsky.isType(AppBskyFeedPost, root.record) ||
!bsky.matches(AppBskyFeedPost, root.record)
) {
this.isOrphan = true
return
@@ -163,14 +164,14 @@ export class FeedViewPostsSlice {
get isQuotePost() {
const embed = this._feedPost.post.embed
return (
bsky.isType(app.bsky.embed.record.view, embed) ||
bsky.isType(app.bsky.embed.recordWithMedia.view, embed)
bsky.isType(AppBskyEmbedRecord.view, embed) ||
bsky.isType(AppBskyEmbedRecordWithMedia.view, embed)
)
}
get isReply() {
return (
bsky.isType(app.bsky.feed.post, this._feedPost.post.record) &&
bsky.isType(AppBskyFeedPost, this._feedPost.post.record) &&
!!this._feedPost.post.record.reply
)
}
@@ -191,7 +192,7 @@ export class FeedViewPostsSlice {
get isRepost() {
const reason = this._feedPost.reason
return bsky.isType(app.bsky.feed.defs.reasonRepost, reason)
return bsky.isType(AppBskyFeedDefs.reasonRepost, reason)
}
get likeCount() {
@@ -204,18 +205,18 @@ export class FeedViewPostsSlice {
getAuthors(): AuthorContext {
const feedPost = this._feedPost
let author: app.bsky.actor.defs.ProfileViewBasic = feedPost.post.author
let parentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
let grandparentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
let rootAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
let author: AppBskyActorDefs.ProfileViewBasic = feedPost.post.author
let parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
let grandparentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
let rootAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
if (feedPost.reply) {
if (bsky.isType(app.bsky.feed.defs.postView, feedPost.reply.parent)) {
if (bsky.isType(AppBskyFeedDefs.postView, feedPost.reply.parent)) {
parentAuthor = feedPost.reply.parent.author
}
if (feedPost.reply.grandparentAuthor) {
grandparentAuthor = feedPost.reply.grandparentAuthor
}
if (bsky.isType(app.bsky.feed.defs.postView, feedPost.reply.root)) {
if (bsky.isType(AppBskyFeedDefs.postView, feedPost.reply.root)) {
rootAuthor = feedPost.reply.root.author
}
}
@@ -510,7 +511,7 @@ function shouldDisplayReplyInFollowing(
}
function isSelfOrFollowing(
profile: app.bsky.actor.defs.ProfileViewBasic,
profile: AppBskyActorDefs.ProfileViewBasic,
userDid: string,
) {
return Boolean(profile.did === userDid || profile.viewer?.following)
+12 -14
View File
@@ -1,11 +1,12 @@
import {type Client, type XrpcRequestParams} from '@atproto/lex'
import {app} from '#/lexicons'
import * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetAuthorFeed from '#/lexicons/app/bsky/feed/getAuthorFeed'
import * as bsky from '#/types/bsky'
import {type FeedAPI, type FeedAPIResponse} from './types'
type GetAuthorFeedParams = XrpcRequestParams<
typeof app.bsky.feed.getAuthorFeed.main
typeof AppBskyFeedGetAuthorFeed.main
>
export class AuthorFeedAPI implements FeedAPI {
@@ -29,8 +30,8 @@ export class AuthorFeedAPI implements FeedAPI {
return params
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
const data = await this.client.call(app.bsky.feed.getAuthorFeed, {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const data = await this.client.call(AppBskyFeedGetAuthorFeed, {
...this.params,
limit: 1,
})
@@ -50,7 +51,7 @@ export class AuthorFeedAPI implements FeedAPI {
* The agent behaved the same way - its `success` flag was only ever true -
* so the empty-page branch this replaces was unreachable.
*/
const data = await this.client.call(app.bsky.feed.getAuthorFeed, {
const data = await this.client.call(AppBskyFeedGetAuthorFeed, {
...this.params,
cursor,
limit,
@@ -61,15 +62,12 @@ export class AuthorFeedAPI implements FeedAPI {
}
}
_filter(feed: app.bsky.feed.defs.FeedViewPost[]) {
_filter(feed: AppBskyFeedDefs.FeedViewPost[]) {
if (this.params.filter === 'posts_and_author_threads') {
return feed.filter(post => {
const isReply = post.reply
const isRepost = bsky.isType(
app.bsky.feed.defs.reasonRepost,
post.reason,
)
const isPin = bsky.isType(app.bsky.feed.defs.reasonPin, post.reason)
const isRepost = bsky.isType(AppBskyFeedDefs.reasonRepost, post.reason)
const isPin = bsky.isType(AppBskyFeedDefs.reasonPin, post.reason)
if (!isReply) return true
if (isRepost || isPin) return true
return isReply && isAuthorReplyChain(this.params.actor, post, feed)
@@ -82,15 +80,15 @@ export class AuthorFeedAPI implements FeedAPI {
function isAuthorReplyChain(
actor: string,
post: app.bsky.feed.defs.FeedViewPost,
posts: app.bsky.feed.defs.FeedViewPost[],
post: AppBskyFeedDefs.FeedViewPost,
posts: AppBskyFeedDefs.FeedViewPost[],
): boolean {
// current post is by a different user (shouldn't happen)
if (post.post.author.did !== actor) return false
const replyParent = post.reply?.parent
if (bsky.isType(app.bsky.feed.defs.postView, replyParent)) {
if (bsky.isType(AppBskyFeedDefs.postView, replyParent)) {
// reply parent is by a different user
if (replyParent.author.did !== actor) return false
+11 -12
View File
@@ -10,11 +10,12 @@ import {
getAppLanguageAsContentLanguage,
getContentLanguages,
} from '#/state/preferences/languages'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetFeed from '#/lexicons/app/bsky/feed/getFeed'
import {type FeedAPI, type FeedAPIResponse} from './types'
import {createBskyTopicsHeader, isBlueskyOwnedFeed} from './utils'
type GetCustomFeedParams = XrpcRequestParams<typeof app.bsky.feed.getFeed.main>
type GetCustomFeedParams = XrpcRequestParams<typeof AppBskyFeedGetFeed.main>
export class CustomFeedAPI implements FeedAPI {
client: Client
@@ -35,10 +36,10 @@ export class CustomFeedAPI implements FeedAPI {
this.userInterests = userInterests
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const contentLangs = getContentLanguages().join(',')
const data = await this.client.call(
app.bsky.feed.getFeed,
AppBskyFeedGetFeed,
{
...this.params,
limit: 1,
@@ -66,7 +67,7 @@ export class CustomFeedAPI implements FeedAPI {
*/
const data = this.client.did
? await this.client.call(
app.bsky.feed.getFeed,
AppBskyFeedGetFeed,
{
...this.params,
cursor,
@@ -144,7 +145,7 @@ function getLoggedOutAppviewClient(): Client {
*/
async function loggedOutFetch(
params: GetCustomFeedParams,
): Promise<app.bsky.feed.getFeed.$OutputBody | null> {
): Promise<AppBskyFeedGetFeed.$OutputBody | null> {
const contentLangs = getAppLanguageAsContentLanguage()
let data = await getFeedOrNull(params, contentLangs)
@@ -172,13 +173,11 @@ async function loggedOutFetch(
async function getFeedOrNull(
params: GetCustomFeedParams,
contentLangs: string,
): Promise<app.bsky.feed.getFeed.$OutputBody | null> {
): Promise<AppBskyFeedGetFeed.$OutputBody | null> {
try {
return await getLoggedOutAppviewClient().call(
app.bsky.feed.getFeed,
params,
{headers: {'Accept-Language': contentLangs}},
)
return await getLoggedOutAppviewClient().call(AppBskyFeedGetFeed, params, {
headers: {'Accept-Language': contentLangs},
})
} catch (e) {
if (e instanceof XrpcResponseError) {
return null
+5 -4
View File
@@ -1,6 +1,7 @@
import {type Client} from '@atproto/lex'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetTimeline from '#/lexicons/app/bsky/feed/getTimeline'
import {type FeedAPI, type FeedAPIResponse} from './types'
export class FollowingFeedAPI implements FeedAPI {
@@ -10,8 +11,8 @@ export class FollowingFeedAPI implements FeedAPI {
this.client = client
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
const data = await this.client.call(app.bsky.feed.getTimeline, {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const data = await this.client.call(AppBskyFeedGetTimeline, {
limit: 1,
})
return data.feed[0]
@@ -30,7 +31,7 @@ export class FollowingFeedAPI implements FeedAPI {
* way - its `success` flag was only ever true - so the empty-page branch
* this replaces was unreachable.
*/
const data = await this.client.call(app.bsky.feed.getTimeline, {
const data = await this.client.call(AppBskyFeedGetTimeline, {
cursor,
limit,
})
+6 -5
View File
@@ -1,10 +1,11 @@
import {type Client, type XrpcRequestParams} from '@atproto/lex'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetActorLikes from '#/lexicons/app/bsky/feed/getActorLikes'
import {type FeedAPI, type FeedAPIResponse} from './types'
type GetActorLikesParams = XrpcRequestParams<
typeof app.bsky.feed.getActorLikes.main
typeof AppBskyFeedGetActorLikes.main
>
export class LikesFeedAPI implements FeedAPI {
@@ -22,8 +23,8 @@ export class LikesFeedAPI implements FeedAPI {
this.params = feedParams
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
const data = await this.client.call(app.bsky.feed.getActorLikes, {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const data = await this.client.call(AppBskyFeedGetActorLikes, {
...this.params,
limit: 1,
})
@@ -43,7 +44,7 @@ export class LikesFeedAPI implements FeedAPI {
* way - its `success` flag was only ever true - so the empty-page branch
* this replaces was unreachable.
*/
const data = await this.client.call(app.bsky.feed.getActorLikes, {
const data = await this.client.call(AppBskyFeedGetActorLikes, {
...this.params,
cursor,
limit,
+6 -7
View File
@@ -1,11 +1,10 @@
import {type Client, type XrpcRequestParams} from '@atproto/lex'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetListFeed from '#/lexicons/app/bsky/feed/getListFeed'
import {type FeedAPI, type FeedAPIResponse} from './types'
type GetListFeedParams = XrpcRequestParams<
typeof app.bsky.feed.getListFeed.main
>
type GetListFeedParams = XrpcRequestParams<typeof AppBskyFeedGetListFeed.main>
export class ListFeedAPI implements FeedAPI {
client: Client
@@ -22,8 +21,8 @@ export class ListFeedAPI implements FeedAPI {
this.params = feedParams
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
const data = await this.client.call(app.bsky.feed.getListFeed, {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const data = await this.client.call(AppBskyFeedGetListFeed, {
...this.params,
limit: 1,
})
@@ -43,7 +42,7 @@ export class ListFeedAPI implements FeedAPI {
* way - its `success` flag was only ever true - so the empty-page branch
* this replaces was unreachable.
*/
const data = await this.client.call(app.bsky.feed.getListFeed, {
const data = await this.client.call(AppBskyFeedGetListFeed, {
...this.params,
cursor,
limit,
+12 -10
View File
@@ -7,7 +7,9 @@ import {timeout} from '#/lib/async/timeout'
import {feedUriToHref} from '#/lib/strings/url-helpers'
import {getContentLanguages} from '#/state/preferences/languages'
import {type FeedParams} from '#/state/queries/post-feed'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetFeed from '#/lexicons/app/bsky/feed/getFeed'
import * as AppBskyFeedGetTimeline from '#/lexicons/app/bsky/feed/getTimeline'
import {FeedTuner} from '../feed-manip'
import {type FeedTunerFn} from '../feed-manip'
import {
@@ -27,7 +29,7 @@ const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours
*/
type MergeFeedPage = {
cursor?: string
feed: app.bsky.feed.defs.FeedViewPost[]
feed: AppBskyFeedDefs.FeedViewPost[]
} | null
export class MergeFeedAPI implements FeedAPI {
@@ -88,8 +90,8 @@ export class MergeFeedAPI implements FeedAPI {
}
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
const data = await this.client.call(app.bsky.feed.getTimeline, {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
const data = await this.client.call(AppBskyFeedGetTimeline, {
limit: 1,
})
return data.feed[0]
@@ -135,7 +137,7 @@ export class MergeFeedAPI implements FeedAPI {
await Promise.all(promises)
// assemble a response by sampling from feeds with content
const posts: app.bsky.feed.defs.FeedViewPost[] = []
const posts: AppBskyFeedDefs.FeedViewPost[] = []
while (posts.length < limit) {
let slice = this.sampleItem()
if (slice[0]) {
@@ -187,7 +189,7 @@ class MergeFeedSource {
feedTuners: FeedTunerFn[]
sourceInfo: ReasonFeedSource | undefined
cursor: string | undefined = undefined
queue: app.bsky.feed.defs.FeedViewPost[] = []
queue: AppBskyFeedDefs.FeedViewPost[] = []
hasMore = true
constructor({
@@ -209,7 +211,7 @@ class MergeFeedSource {
return this.hasMore && this.queue.length === 0
}
take(n: number): app.bsky.feed.defs.FeedViewPost[] {
take(n: number): AppBskyFeedDefs.FeedViewPost[] {
return this.queue.splice(0, n)
}
@@ -254,7 +256,7 @@ class MergeFeedSource_Following extends MergeFeedSource {
cursor: string | undefined,
limit: number,
): Promise<MergeFeedPage> {
const data = await this.client.call(app.bsky.feed.getTimeline, {
const data = await this.client.call(AppBskyFeedGetTimeline, {
cursor,
limit,
})
@@ -307,7 +309,7 @@ class MergeFeedSource_Custom extends MergeFeedSource {
const contentLangs = getContentLanguages().join(',')
const isBlueskyOwned = isBlueskyOwnedFeed(this.feedUri)
const data = await this.client.call(
app.bsky.feed.getFeed,
AppBskyFeedGetFeed,
{
cursor,
limit,
@@ -326,7 +328,7 @@ class MergeFeedSource_Custom extends MergeFeedSource {
// some custom feeds fail to enforce the pagination limit
// so we manually truncate here
// -prf
let feed: app.bsky.feed.defs.FeedViewPost[] =
let feed: AppBskyFeedDefs.FeedViewPost[] =
limit && data.feed.length > limit
? data.feed.slice(0, limit)
: data.feed
+6 -5
View File
@@ -1,15 +1,16 @@
import {type Client, type XrpcRequestParams} from '@atproto/lex'
import {logger} from '#/logger'
import {app} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetPosts from '#/lexicons/app/bsky/feed/getPosts'
import {type FeedAPI, type FeedAPIResponse} from './types'
type GetPostsParams = XrpcRequestParams<typeof app.bsky.feed.getPosts.main>
type GetPostsParams = XrpcRequestParams<typeof AppBskyFeedGetPosts.main>
export class PostListFeedAPI implements FeedAPI {
client: Client
params: GetPostsParams
peek: app.bsky.feed.defs.FeedViewPost | null = null
peek: AppBskyFeedDefs.FeedViewPost | null = null
constructor({
client,
@@ -29,7 +30,7 @@ export class PostListFeedAPI implements FeedAPI {
}
}
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
if (this.peek) return this.peek
throw new Error('Has not fetched yet')
}
@@ -41,7 +42,7 @@ export class PostListFeedAPI implements FeedAPI {
* way - its `success` flag was only ever true - so the empty-page branch
* this replaces was unreachable.
*/
const data = await this.client.call(app.bsky.feed.getPosts, {
const data = await this.client.call(AppBskyFeedGetPosts, {
...this.params,
})
this.peek = {post: data.posts[0]}
+30 -21
View File
@@ -28,7 +28,16 @@ import {
type PostDraft,
type ThreadDraft,
} from '#/view/com/composer/state/composer'
import {app, chat, com} from '#/lexicons'
import type * as AppBskyEmbedExternal from '#/lexicons/app/bsky/embed/external'
import type * as AppBskyEmbedGallery from '#/lexicons/app/bsky/embed/gallery'
import type * as AppBskyEmbedImages from '#/lexicons/app/bsky/embed/images'
import type * as AppBskyEmbedVideo from '#/lexicons/app/bsky/embed/video'
import * as AppBskyFeedGetPosts from '#/lexicons/app/bsky/feed/getPosts'
import * as AppBskyFeedPost from '#/lexicons/app/bsky/feed/post'
import * as ChatBskyGroupDefs from '#/lexicons/chat/bsky/group/defs'
import type * as ComAtprotoLabelDefs from '#/lexicons/com/atproto/label/defs'
import * as ComAtprotoRepoApplyWrites from '#/lexicons/com/atproto/repo/applyWrites'
import type * as ComAtprotoRepoStrongRef from '#/lexicons/com/atproto/repo/strongRef'
import * as bsky from '#/types/bsky'
import {createGIFDescription} from '../gif-alt-text'
import {computeCid} from './computeCid'
@@ -65,8 +74,8 @@ export async function post(queryClient: QueryClient, opts: PostOpts) {
opts.onStateChange?.(t`Processing...`)
let replyPromise:
| Promise<app.bsky.feed.post.Main['reply']>
| app.bsky.feed.post.Main['reply']
| Promise<AppBskyFeedPost.Main['reply']>
| AppBskyFeedPost.Main['reply']
| undefined
if (opts.replyTo) {
// Not awaited to avoid waterfalls.
@@ -80,7 +89,7 @@ export async function post(queryClient: QueryClient, opts: PostOpts) {
}
const did = opts.pdsClient.assertDid
const writes: com.atproto.repo.applyWrites.$InputBody['writes'] = []
const writes: ComAtprotoRepoApplyWrites.$InputBody['writes'] = []
const uris: string[] = []
let now = new Date()
@@ -99,7 +108,7 @@ export async function post(queryClient: QueryClient, opts: PostOpts) {
draft,
opts.onStateChange,
)
let labels: $Typed<com.atproto.label.defs.SelfLabels> | undefined
let labels: $Typed<ComAtprotoLabelDefs.SelfLabels> | undefined
if (draft.labels.length) {
labels = {
$type: 'com.atproto.label.defs#selfLabels',
@@ -118,7 +127,7 @@ export async function post(queryClient: QueryClient, opts: PostOpts) {
const rt = await rtPromise
const embed = await embedPromise
const reply = await replyPromise
const record: app.bsky.feed.post.Main = {
const record: AppBskyFeedPost.Main = {
// IMPORTANT: $type has to exist, CID is calculated with the `$type` field
// present and will produce the wrong CID if you omit it.
$type: 'app.bsky.feed.post',
@@ -179,7 +188,7 @@ export async function post(queryClient: QueryClient, opts: PostOpts) {
}
try {
await opts.pdsClient.call(com.atproto.repo.applyWrites, {
await opts.pdsClient.call(ComAtprotoRepoApplyWrites, {
repo: did,
writes: writes,
validate: true,
@@ -222,7 +231,7 @@ export class ReplyDeletedError extends Error {
}
async function resolveReply(appviewClient: Client, replyTo: string) {
const data = await appviewClient.call(app.bsky.feed.getPosts, {
const data = await appviewClient.call(AppBskyFeedGetPosts, {
uris: [replyTo as AtUriString],
})
const parentPost = data.posts[0]
@@ -234,9 +243,9 @@ async function resolveReply(appviewClient: Client, replyTo: string) {
uri: parentPost.uri,
cid: parentPost.cid,
}
let rootRef: com.atproto.repo.strongRef.Main = parentRef
let rootRef: ComAtprotoRepoStrongRef.Main = parentRef
if (bsky.isType(app.bsky.feed.post, parentPost.record)) {
if (bsky.isType(AppBskyFeedPost, parentPost.record)) {
if (parentPost.record.reply) {
rootRef = parentPost.record.reply.root
}
@@ -255,7 +264,7 @@ async function resolveEmbed(
queryClient: QueryClient,
draft: PostDraft,
onStateChange: ((state: string) => void) | undefined,
): Promise<app.bsky.feed.post.Main['embed']> {
): Promise<AppBskyFeedPost.Main['embed']> {
if (draft.embed.quote) {
const [resolvedMedia, resolvedQuote] = await Promise.all([
resolveMedia(
@@ -322,10 +331,10 @@ async function resolveMedia(
embedDraft: EmbedDraft,
onStateChange: ((state: string) => void) | undefined,
): Promise<
| $Typed<app.bsky.embed.external.Main>
| $Typed<app.bsky.embed.images.Main>
| $Typed<app.bsky.embed.gallery.Main>
| $Typed<app.bsky.embed.video.Main>
| $Typed<AppBskyEmbedExternal.Main>
| $Typed<AppBskyEmbedImages.Main>
| $Typed<AppBskyEmbedGallery.Main>
| $Typed<AppBskyEmbedVideo.Main>
| undefined
> {
if (embedDraft.media?.type === 'images') {
@@ -334,7 +343,7 @@ async function resolveMedia(
count: imagesDraft.length,
})
onStateChange?.(t`Uploading images...`)
const images: app.bsky.embed.images.Image[] = await Promise.all(
const images: AppBskyEmbedImages.Image[] = await Promise.all(
imagesDraft.map(async (image, i) => {
logger.debug(`Compressing image #${i}`)
const {path, width, height, mime} = await compressImage(
@@ -361,7 +370,7 @@ async function resolveMedia(
count: imagesDraft.length,
})
onStateChange?.(t`Uploading images...`)
const items: $Typed<app.bsky.embed.gallery.Image>[] = await Promise.all(
const items: $Typed<AppBskyEmbedGallery.Image>[] = await Promise.all(
imagesDraft.map(async (image, i) => {
logger.debug(`Compressing image #${i}`)
const {path, width, height, mime} = await compressImage(
@@ -431,7 +440,7 @@ async function resolveMedia(
if (embedDraft.media?.type === 'gif') {
const gifDraft = embedDraft.media
const resolvedGif = await fetchResolveGifQuery(queryClient, gifDraft.gif)
let blob: app.bsky.embed.external.External['thumb']
let blob: AppBskyEmbedExternal.External['thumb']
if (resolvedGif.thumb) {
onStateChange?.(t`Uploading link thumbnail...`)
const {path, mime} = resolvedGif.thumb.source
@@ -455,7 +464,7 @@ async function resolveMedia(
embedDraft.link.uri,
)
if (resolvedLink.type === 'external') {
let blob: app.bsky.embed.external.External['thumb']
let blob: AppBskyEmbedExternal.External['thumb']
if (resolvedLink.thumb) {
onStateChange?.(t`Uploading link thumbnail...`)
const {path, mime} = resolvedLink.thumb.source
@@ -475,7 +484,7 @@ async function resolveMedia(
}
if (
resolvedLink.type === 'chat-invite' &&
bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, resolvedLink.view)
bsky.isType(ChatBskyGroupDefs.joinLinkPreviewView, resolvedLink.view)
) {
return {
$type: 'app.bsky.embed.external',
@@ -494,7 +503,7 @@ async function resolveRecord(
clients: LinkResolvers,
queryClient: QueryClient,
uri: string,
): Promise<com.atproto.repo.strongRef.Main> {
): Promise<ComAtprotoRepoStrongRef.Main> {
const resolvedLink = await fetchResolveLinkQuery(queryClient, clients, uri)
if (resolvedLink.type !== 'record') {
throw Error(t`Expected uri to resolve to a record`)
+28 -22
View File
@@ -24,7 +24,15 @@ import {type ComposerImage} from '#/state/gallery'
import {createComposerImage} from '#/state/gallery'
import {type ChatInvitePreview} from '#/state/queries/join-links'
import {type Gif} from '#/features/gifPicker/types'
import {app, chat, com} from '#/lexicons'
import type * as AppBskyFeedDefs from '#/lexicons/app/bsky/feed/defs'
import * as AppBskyFeedGetFeedGenerator from '#/lexicons/app/bsky/feed/getFeedGenerator'
import * as AppBskyFeedGetPosts from '#/lexicons/app/bsky/feed/getPosts'
import type * as AppBskyGraphDefs from '#/lexicons/app/bsky/graph/defs'
import * as AppBskyGraphGetList from '#/lexicons/app/bsky/graph/getList'
import * as AppBskyGraphGetStarterPack from '#/lexicons/app/bsky/graph/getStarterPack'
import * as ChatBskyGroupGetJoinLinkPreviews from '#/lexicons/chat/bsky/group/getJoinLinkPreviews'
import * as ComAtprotoIdentityResolveHandle from '#/lexicons/com/atproto/identity/resolveHandle'
import type * as ComAtprotoRepoStrongRef from '#/lexicons/com/atproto/repo/strongRef'
import {createGIFDescription} from '../gif-alt-text'
type ResolvedExternalLink = {
@@ -43,30 +51,30 @@ type ResolvedExternalLink = {
type ResolvedPostRecord = {
type: 'record'
record: com.atproto.repo.strongRef.Main
record: ComAtprotoRepoStrongRef.Main
kind: 'post'
view: app.bsky.feed.defs.PostView
view: AppBskyFeedDefs.PostView
}
type ResolvedFeedRecord = {
type: 'record'
record: com.atproto.repo.strongRef.Main
record: ComAtprotoRepoStrongRef.Main
kind: 'feed'
view: app.bsky.feed.defs.GeneratorView
view: AppBskyFeedDefs.GeneratorView
}
type ResolvedListRecord = {
type: 'record'
record: com.atproto.repo.strongRef.Main
record: ComAtprotoRepoStrongRef.Main
kind: 'list'
view: app.bsky.graph.defs.ListView
view: AppBskyGraphDefs.ListView
}
type ResolvedStarterPackRecord = {
type: 'record'
record: com.atproto.repo.strongRef.Main
record: ComAtprotoRepoStrongRef.Main
kind: 'starter-pack'
view: app.bsky.graph.defs.StarterPackView
view: AppBskyGraphDefs.StarterPackView
}
type ResolvedChatInvite = {
@@ -133,7 +141,7 @@ export async function resolveLink(
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
const did = await fetchDid(handleOrDid)
const feed = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
const data = await appviewClient.call(app.bsky.feed.getFeedGenerator, {
const data = await appviewClient.call(AppBskyFeedGetFeedGenerator, {
feed: feed,
})
return {
@@ -151,7 +159,7 @@ export async function resolveLink(
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
const did = await fetchDid(handleOrDid)
const list = makeRecordUri(did, 'app.bsky.graph.list', rkey)
const data = await appviewClient.call(app.bsky.graph.getList, {
const data = await appviewClient.call(AppBskyGraphGetList, {
list: list,
})
return {
@@ -166,7 +174,7 @@ export async function resolveLink(
}
const chatInviteCode = getChatInviteCodeFromUrl(uri)
if (chatInviteCode) {
const data = await chatClient.call(chat.bsky.group.getJoinLinkPreviews, {
const data = await chatClient.call(ChatBskyGroupGetJoinLinkPreviews, {
codes: [chatInviteCode],
})
return {
@@ -185,7 +193,7 @@ export async function resolveLink(
}
const did = await fetchDid(parsed.name)
const starterPack = createStarterPackUri({did, rkey: parsed.rkey})
const data = await appviewClient.call(app.bsky.graph.getStarterPack, {
const data = await appviewClient.call(AppBskyGraphGetStarterPack, {
starterPack: starterPack as AtUriString,
})
return {
@@ -204,13 +212,12 @@ export async function resolveLink(
async function getPost({uri}: {uri: string}) {
const urip = new AtUri(uri)
if (!urip.host.startsWith('did:')) {
const data = await appviewClient.call(
com.atproto.identity.resolveHandle,
{handle: urip.host as HandleString},
)
const data = await appviewClient.call(ComAtprotoIdentityResolveHandle, {
handle: urip.host as HandleString,
})
urip.host = data.did
}
const data = await appviewClient.call(app.bsky.feed.getPosts, {
const data = await appviewClient.call(AppBskyFeedGetPosts, {
uris: [urip.toString()],
})
if (data.posts[0]) {
@@ -223,10 +230,9 @@ export async function resolveLink(
async function fetchDid(handleOrDid: string) {
let identifier = handleOrDid
if (!identifier.startsWith('did:')) {
const data = await appviewClient.call(
com.atproto.identity.resolveHandle,
{handle: identifier as HandleString},
)
const data = await appviewClient.call(ComAtprotoIdentityResolveHandle, {
handle: identifier as HandleString,
})
identifier = data.did
}
return identifier
+19 -12
View File
@@ -9,7 +9,14 @@ import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
import {enforceLen} from '#/lib/strings/helpers'
import {useAppviewClient, usePdsClient} from '#/state/session'
import {app, com} from '#/lexicons'
import type * as AppBskyActorDefs from '#/lexicons/app/bsky/actor/defs'
import * as AppBskyActorGetProfile from '#/lexicons/app/bsky/actor/getProfile'
import * as AppBskyActorSearchActors from '#/lexicons/app/bsky/actor/searchActors'
import * as AppBskyGraphGetStarterPack from '#/lexicons/app/bsky/graph/getStarterPack'
import * as AppBskyGraphList from '#/lexicons/app/bsky/graph/list'
import * as AppBskyGraphStarterpack from '#/lexicons/app/bsky/graph/starterpack'
import type * as AppBskyRichtextFacet from '#/lexicons/app/bsky/richtext/facet'
import * as ComAtprotoRepoApplyWrites from '#/lexicons/com/atproto/repo/applyWrites'
import type * as bsky from '#/types/bsky'
export const createStarterPackList = async ({
@@ -21,13 +28,13 @@ export const createStarterPackList = async ({
}: {
name: string
description?: string
descriptionFacets?: app.bsky.richtext.facet.Main[]
descriptionFacets?: AppBskyRichtextFacet.Main[]
profiles: bsky.profile.AnyProfileView[]
client: Client
}): Promise<{uri: string; cid: string}> => {
if (profiles.length === 0) throw new Error('No profiles given')
const list = await client.create(app.bsky.graph.list, {
const list = await client.create(AppBskyGraphList, {
name,
description,
descriptionFacets,
@@ -36,7 +43,7 @@ export const createStarterPackList = async ({
purpose: 'app.bsky.graph.defs#referencelist',
})
if (!list) throw new Error('List creation failed')
await client.call(com.atproto.repo.applyWrites, {
await client.call(ComAtprotoRepoApplyWrites, {
repo: client.assertDid,
writes: profiles.map(p => createListItem({did: p.did, listUri: list.uri})),
})
@@ -57,18 +64,18 @@ export function useGenerateStarterPackMutation({
return useMutation<{uri: string; cid: string}, Error, void>({
mutationFn: async () => {
let profile: app.bsky.actor.defs.ProfileViewDetailed | undefined
let profiles: app.bsky.actor.defs.ProfileView[] | undefined
let profile: AppBskyActorDefs.ProfileViewDetailed | undefined
let profiles: AppBskyActorDefs.ProfileView[] | undefined
await Promise.all([
(async () => {
profile = await appviewClient.call(app.bsky.actor.getProfile, {
profile = await appviewClient.call(AppBskyActorGetProfile, {
actor: pdsClient.assertDid,
})
})(),
(async () => {
profiles = (
await appviewClient.call(app.bsky.actor.searchActors, {
await appviewClient.call(AppBskyActorSearchActors, {
q: encodeURIComponent('*'),
limit: 49,
})
@@ -100,7 +107,7 @@ export function useGenerateStarterPackMutation({
client: pdsClient,
})
return await pdsClient.create(app.bsky.graph.starterpack, {
return await pdsClient.create(AppBskyGraphStarterpack, {
name: starterPackName,
// `create` returns a plain string uri
list: list.uri as AtUriString,
@@ -125,7 +132,7 @@ function createListItem({
}: {
did: string
listUri: string
}): com.atproto.repo.applyWrites.$InputBody['writes'][number] {
}): ComAtprotoRepoApplyWrites.$InputBody['writes'][number] {
return {
$type: 'com.atproto.repo.applyWrites#create',
collection: 'app.bsky.graph.listitem',
@@ -141,14 +148,14 @@ function createListItem({
async function whenAppViewReady(
client: Client,
uri: string,
fn: (res?: app.bsky.graph.getStarterPack.$OutputBody) => boolean,
fn: (res?: AppBskyGraphGetStarterPack.$OutputBody) => boolean,
) {
await until(
5, // 5 tries
1e3, // 1s delay between tries
fn,
() =>
client.call(app.bsky.graph.getStarterPack, {
client.call(AppBskyGraphGetStarterPack, {
starterPack: uri as AtUriString,
}),
)
+4 -3
View File
@@ -6,7 +6,8 @@ import {msg} from '@lingui/core/macro'
import {VIDEO_SERVICE_DID} from '#/lib/constants'
import {UploadLimitError} from '#/lib/media/video/errors'
import {getServiceAuthAudFromUrl} from '#/lib/strings/url-helpers'
import {app, com} from '#/lexicons'
import * as AppBskyVideoGetUploadLimits from '#/lexicons/app/bsky/video/getUploadLimits'
import * as ComAtprotoServerGetServiceAuth from '#/lexicons/com/atproto/server/getServiceAuth'
import {createVideoServiceClient} from './util'
export async function getServiceAuthToken({
@@ -40,7 +41,7 @@ export async function getServiceAuthToken({
}
resolvedAud = pdsAud
}
const {token} = await client.call(com.atproto.server.getServiceAuth, {
const {token} = await client.call(ComAtprotoServerGetServiceAuth, {
aud: resolvedAud as DidString,
lxm,
exp,
@@ -56,7 +57,7 @@ export async function getVideoUploadLimits(client: Client, i18n: I18n) {
})
const videoClient = createVideoServiceClient(token)
const limits = await videoClient
.call(app.bsky.video.getUploadLimits)
.call(AppBskyVideoGetUploadLimits)
.catch(err => {
if (err instanceof Error) {
throw new UploadLimitError(err.message)
+5 -4
View File
@@ -17,7 +17,8 @@ import BackgroundNotificationHandler from '#/../modules/expo-background-notifica
import {useAgeAssurance} from '#/ageAssurance'
import {useAnalytics} from '#/analytics'
import {IS_DEV, IS_NATIVE} from '#/env'
import {app} from '#/lexicons'
import * as AppBskyNotificationRegisterPush from '#/lexicons/app/bsky/notification/registerPush'
import * as AppBskyNotificationUnregisterPush from '#/lexicons/app/bsky/notification/unregisterPush'
/**
* A resumed single-use account client paired with the account's service origin
@@ -50,7 +51,7 @@ async function _registerPushToken({
}
}) {
try {
const payload: app.bsky.notification.registerPush.$InputBody = {
const payload: AppBskyNotificationRegisterPush.$InputBody = {
serviceDid: currentAccount.service?.includes('staging')
? PUBLIC_STAGING_APPVIEW_DID
: PUBLIC_APPVIEW_DID,
@@ -62,7 +63,7 @@ async function _registerPushToken({
notyLogger.debug(`registerPushToken: registering`, {...payload})
await client.call(app.bsky.notification.registerPush, payload, {
await client.call(AppBskyNotificationRegisterPush, payload, {
service: NOTIF_SERVICE,
})
@@ -348,7 +349,7 @@ export async function unregisterPushToken(clients: TemporaryPushClient[]) {
if (token) {
for (const {client, service, handle} of clients) {
await client.call(
app.bsky.notification.unregisterPush,
AppBskyNotificationUnregisterPush,
{
serviceDid: service.includes('staging')
? PUBLIC_STAGING_APPVIEW_DID
+2 -2
View File
@@ -1,6 +1,6 @@
import {type RichText} from '@bsky/sdk/richtext'
import {app} from '#/lexicons'
import * as AppBskyRichtextFacet from '#/lexicons/app/bsky/richtext/facet'
import * as bsky from '#/types/bsky'
import {linkRequiresWarning} from './url-helpers'
@@ -16,7 +16,7 @@ export function richTextToString(rt: RichText, loose: boolean): string {
for (const segment of rt.segments()) {
const link = segment.link
if (link && bsky.matches(app.bsky.richtext.facet.link, link)) {
if (link && bsky.matches(AppBskyRichtextFacet.link, link)) {
const href = link.uri
const text = segment.text
+3 -3
View File
@@ -1,6 +1,6 @@
import {type RichText, UnicodeString} from '@bsky/sdk/richtext'
import {app} from '#/lexicons'
import * as AppBskyRichtextFacet from '#/lexicons/app/bsky/richtext/facet'
import * as bsky from '#/types/bsky'
import {toShortUrl} from './url-helpers'
@@ -13,7 +13,7 @@ export function shortenLinks(rt: RichText): RichText {
if (rt.facets) {
for (const facet of rt.facets) {
const isLink = !!facet.features.find(f =>
bsky.isType(app.bsky.richtext.facet.link, f),
bsky.isType(AppBskyRichtextFacet.link, f),
)
if (!isLink) {
continue
@@ -45,7 +45,7 @@ export function stripInvalidMentions(rt: RichText): RichText {
if (rt.facets) {
rt.facets = rt.facets?.filter(facet => {
const mention = facet.features.find(f =>
bsky.isType(app.bsky.richtext.facet.mention, f),
bsky.isType(AppBskyRichtextFacet.mention, f),
)
if (mention && !mention.did) {
return false
+2 -2
View File
@@ -9,7 +9,7 @@ import {
XrpcResponseError,
} from '@atproto/lex'
import {com} from '#/lexicons'
import * as ComAtprotoRepoGetRecord from '#/lexicons/com/atproto/repo/getRecord'
/**
* True for an XRPC error from a lex `Client` (`XrpcError` is the abstract base
@@ -104,7 +104,7 @@ export function matchXrpcError<M extends Procedure | Query>(
* turn a previously-handled absence into a thrown error.
*/
export function isRecordNotFoundError(e: unknown): boolean {
if (matchXrpcError(e, com.atproto.repo.getRecord) === 'RecordNotFound') {
if (matchXrpcError(e, ComAtprotoRepoGetRecord) === 'RecordNotFound') {
return true
}
return e instanceof Error && e.message.includes('Could not locate record:')