···11+{
22+ "id": "app.bsky.feed.getPostThread",
33+ "defs": {
44+ "main": {
55+ "type": "query",
66+ "errors": [
77+ {
88+ "name": "NotFound"
99+ }
1010+ ],
1111+ "output": {
1212+ "schema": {
1313+ "type": "object",
1414+ "required": ["thread"],
1515+ "properties": {
1616+ "thread": {
1717+ "refs": [
1818+ "app.bsky.feed.defs#threadViewPost",
1919+ "app.bsky.feed.defs#notFoundPost",
2020+ "app.bsky.feed.defs#blockedPost"
2121+ ],
2222+ "type": "union"
2323+ },
2424+ "threadgate": {
2525+ "ref": "app.bsky.feed.defs#threadgateView",
2626+ "type": "ref"
2727+ }
2828+ }
2929+ },
3030+ "encoding": "application/json"
3131+ },
3232+ "parameters": {
3333+ "type": "params",
3434+ "required": ["uri"],
3535+ "properties": {
3636+ "uri": {
3737+ "type": "string",
3838+ "format": "at-uri",
3939+ "description": "Reference (AT-URI) to post record."
4040+ },
4141+ "depth": {
4242+ "type": "integer",
4343+ "default": 6,
4444+ "maximum": 1000,
4545+ "minimum": 0,
4646+ "description": "How many levels of reply depth should be included in response."
4747+ },
4848+ "parentHeight": {
4949+ "type": "integer",
5050+ "default": 80,
5151+ "maximum": 1000,
5252+ "minimum": 0,
5353+ "description": "How many levels of parent (and grandparent, etc) post to include."
5454+ }
5555+ }
5656+ },
5757+ "description": "Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests."
5858+ }
5959+ },
6060+ "$type": "com.atproto.lexicon.schema",
6161+ "lexicon": 1
6262+}
+42
lexicons/app/bsky/feed/getPosts.json
···11+{
22+ "id": "app.bsky.feed.getPosts",
33+ "defs": {
44+ "main": {
55+ "type": "query",
66+ "output": {
77+ "schema": {
88+ "type": "object",
99+ "required": ["posts"],
1010+ "properties": {
1111+ "posts": {
1212+ "type": "array",
1313+ "items": {
1414+ "ref": "app.bsky.feed.defs#postView",
1515+ "type": "ref"
1616+ }
1717+ }
1818+ }
1919+ },
2020+ "encoding": "application/json"
2121+ },
2222+ "parameters": {
2323+ "type": "params",
2424+ "required": ["uris"],
2525+ "properties": {
2626+ "uris": {
2727+ "type": "array",
2828+ "items": {
2929+ "type": "string",
3030+ "format": "at-uri"
3131+ },
3232+ "maxLength": 25,
3333+ "description": "List of post AT-URIs to return hydrated views for."
3434+ }
3535+ }
3636+ },
3737+ "description": "Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'."
3838+ }
3939+ },
4040+ "$type": "com.atproto.lexicon.schema",
4141+ "lexicon": 1
4242+}
+130
lexicons/app/bsky/feed/post.json
···11+{
22+ "id": "app.bsky.feed.post",
33+ "defs": {
44+ "main": {
55+ "key": "tid",
66+ "type": "record",
77+ "record": {
88+ "type": "object",
99+ "required": ["text", "createdAt"],
1010+ "properties": {
1111+ "tags": {
1212+ "type": "array",
1313+ "items": {
1414+ "type": "string",
1515+ "maxLength": 640,
1616+ "maxGraphemes": 64
1717+ },
1818+ "maxLength": 8,
1919+ "description": "Additional hashtags, in addition to any included in post text and facets."
2020+ },
2121+ "text": {
2222+ "type": "string",
2323+ "maxLength": 3000,
2424+ "description": "The primary post content. May be an empty string, if there are embeds.",
2525+ "maxGraphemes": 300
2626+ },
2727+ "embed": {
2828+ "refs": [
2929+ "app.bsky.embed.images",
3030+ "app.bsky.embed.video",
3131+ "app.bsky.embed.external",
3232+ "app.bsky.embed.record",
3333+ "app.bsky.embed.recordWithMedia"
3434+ ],
3535+ "type": "union"
3636+ },
3737+ "langs": {
3838+ "type": "array",
3939+ "items": {
4040+ "type": "string",
4141+ "format": "language"
4242+ },
4343+ "maxLength": 3,
4444+ "description": "Indicates human language of post primary text content."
4545+ },
4646+ "reply": {
4747+ "ref": "#replyRef",
4848+ "type": "ref"
4949+ },
5050+ "facets": {
5151+ "type": "array",
5252+ "items": {
5353+ "ref": "app.bsky.richtext.facet",
5454+ "type": "ref"
5555+ },
5656+ "description": "Annotations of text (mentions, URLs, hashtags, etc)"
5757+ },
5858+ "labels": {
5959+ "refs": ["com.atproto.label.defs#selfLabels"],
6060+ "type": "union",
6161+ "description": "Self-label values for this post. Effectively content warnings."
6262+ },
6363+ "entities": {
6464+ "type": "array",
6565+ "items": {
6666+ "ref": "#entity",
6767+ "type": "ref"
6868+ },
6969+ "description": "DEPRECATED: replaced by app.bsky.richtext.facet."
7070+ },
7171+ "createdAt": {
7272+ "type": "string",
7373+ "format": "datetime",
7474+ "description": "Client-declared timestamp when this post was originally created."
7575+ }
7676+ }
7777+ },
7878+ "description": "Record containing a Bluesky post."
7979+ },
8080+ "entity": {
8181+ "type": "object",
8282+ "required": ["index", "type", "value"],
8383+ "properties": {
8484+ "type": {
8585+ "type": "string",
8686+ "description": "Expected values are 'mention' and 'link'."
8787+ },
8888+ "index": {
8989+ "ref": "#textSlice",
9090+ "type": "ref"
9191+ },
9292+ "value": {
9393+ "type": "string"
9494+ }
9595+ },
9696+ "description": "Deprecated: use facets instead."
9797+ },
9898+ "replyRef": {
9999+ "type": "object",
100100+ "required": ["root", "parent"],
101101+ "properties": {
102102+ "root": {
103103+ "ref": "com.atproto.repo.strongRef",
104104+ "type": "ref"
105105+ },
106106+ "parent": {
107107+ "ref": "com.atproto.repo.strongRef",
108108+ "type": "ref"
109109+ }
110110+ }
111111+ },
112112+ "textSlice": {
113113+ "type": "object",
114114+ "required": ["start", "end"],
115115+ "properties": {
116116+ "end": {
117117+ "type": "integer",
118118+ "minimum": 0
119119+ },
120120+ "start": {
121121+ "type": "integer",
122122+ "minimum": 0
123123+ }
124124+ },
125125+ "description": "Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings."
126126+ }
127127+ },
128128+ "$type": "com.atproto.lexicon.schema",
129129+ "lexicon": 1
130130+}
+50
lexicons/app/bsky/feed/postgate.json
···11+{
22+ "id": "app.bsky.feed.postgate",
33+ "defs": {
44+ "main": {
55+ "key": "tid",
66+ "type": "record",
77+ "record": {
88+ "type": "object",
99+ "required": ["post", "createdAt"],
1010+ "properties": {
1111+ "post": {
1212+ "type": "string",
1313+ "format": "at-uri",
1414+ "description": "Reference (AT-URI) to the post record."
1515+ },
1616+ "createdAt": {
1717+ "type": "string",
1818+ "format": "datetime"
1919+ },
2020+ "embeddingRules": {
2121+ "type": "array",
2222+ "items": {
2323+ "refs": ["#disableRule"],
2424+ "type": "union"
2525+ },
2626+ "maxLength": 5,
2727+ "description": "List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed."
2828+ },
2929+ "detachedEmbeddingUris": {
3030+ "type": "array",
3131+ "items": {
3232+ "type": "string",
3333+ "format": "at-uri"
3434+ },
3535+ "maxLength": 50,
3636+ "description": "List of AT-URIs embedding this post that the author has detached from."
3737+ }
3838+ }
3939+ },
4040+ "description": "Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository."
4141+ },
4242+ "disableRule": {
4343+ "type": "object",
4444+ "properties": {},
4545+ "description": "Disables embedding of this post."
4646+ }
4747+ },
4848+ "$type": "com.atproto.lexicon.schema",
4949+ "lexicon": 1
5050+}
+71
lexicons/app/bsky/feed/threadgate.json
···11+{
22+ "id": "app.bsky.feed.threadgate",
33+ "defs": {
44+ "main": {
55+ "key": "tid",
66+ "type": "record",
77+ "record": {
88+ "type": "object",
99+ "required": ["post", "createdAt"],
1010+ "properties": {
1111+ "post": {
1212+ "type": "string",
1313+ "format": "at-uri",
1414+ "description": "Reference (AT-URI) to the post record."
1515+ },
1616+ "allow": {
1717+ "type": "array",
1818+ "items": {
1919+ "refs": ["#mentionRule", "#followerRule", "#followingRule", "#listRule"],
2020+ "type": "union"
2121+ },
2222+ "maxLength": 5,
2323+ "description": "List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply."
2424+ },
2525+ "createdAt": {
2626+ "type": "string",
2727+ "format": "datetime"
2828+ },
2929+ "hiddenReplies": {
3030+ "type": "array",
3131+ "items": {
3232+ "type": "string",
3333+ "format": "at-uri"
3434+ },
3535+ "maxLength": 300,
3636+ "description": "List of hidden reply URIs."
3737+ }
3838+ }
3939+ },
4040+ "description": "Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository."
4141+ },
4242+ "listRule": {
4343+ "type": "object",
4444+ "required": ["list"],
4545+ "properties": {
4646+ "list": {
4747+ "type": "string",
4848+ "format": "at-uri"
4949+ }
5050+ },
5151+ "description": "Allow replies from actors on a list."
5252+ },
5353+ "mentionRule": {
5454+ "type": "object",
5555+ "properties": {},
5656+ "description": "Allow replies from actors mentioned in your post."
5757+ },
5858+ "followerRule": {
5959+ "type": "object",
6060+ "properties": {},
6161+ "description": "Allow replies from actors who follow you."
6262+ },
6363+ "followingRule": {
6464+ "type": "object",
6565+ "properties": {},
6666+ "description": "Allow replies from actors you follow."
6767+ }
6868+ },
6969+ "$type": "com.atproto.lexicon.schema",
7070+ "lexicon": 1
7171+}
···11+{
22+ "id": "app.bsky.richtext.facet",
33+ "defs": {
44+ "tag": {
55+ "type": "object",
66+ "required": ["tag"],
77+ "properties": {
88+ "tag": {
99+ "type": "string",
1010+ "maxLength": 640,
1111+ "maxGraphemes": 64
1212+ }
1313+ },
1414+ "description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags')."
1515+ },
1616+ "link": {
1717+ "type": "object",
1818+ "required": ["uri"],
1919+ "properties": {
2020+ "uri": {
2121+ "type": "string",
2222+ "format": "uri"
2323+ }
2424+ },
2525+ "description": "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL."
2626+ },
2727+ "main": {
2828+ "type": "object",
2929+ "required": ["index", "features"],
3030+ "properties": {
3131+ "index": {
3232+ "ref": "#byteSlice",
3333+ "type": "ref"
3434+ },
3535+ "features": {
3636+ "type": "array",
3737+ "items": {
3838+ "refs": ["#mention", "#link", "#tag"],
3939+ "type": "union"
4040+ }
4141+ }
4242+ },
4343+ "description": "Annotation of a sub-string within rich text."
4444+ },
4545+ "mention": {
4646+ "type": "object",
4747+ "required": ["did"],
4848+ "properties": {
4949+ "did": {
5050+ "type": "string",
5151+ "format": "did"
5252+ }
5353+ },
5454+ "description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID."
5555+ },
5656+ "byteSlice": {
5757+ "type": "object",
5858+ "required": ["byteStart", "byteEnd"],
5959+ "properties": {
6060+ "byteEnd": {
6161+ "type": "integer",
6262+ "minimum": 0
6363+ },
6464+ "byteStart": {
6565+ "type": "integer",
6666+ "minimum": 0
6767+ }
6868+ },
6969+ "description": "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets."
7070+ }
7171+ },
7272+ "$type": "com.atproto.lexicon.schema",
7373+ "lexicon": 1
7474+}
···6262 filterByDids: [string][] = [],
6363 ttl: number | undefined = undefined,
6464 ) {
6565+ // Note that using Client from @atproto/lex here is kinda "hard" because it
6666+ // expects a native fetch implementation, which is "hard" to provide using
6767+ // this.cachedFetch as underlying fetch implementation. In addition to this,
6868+ // blue.microcosm.links.getBacklinks is not a published lexicon, meaning
6969+ // that we cannot install it using `pnpm exec lex install
7070+ // blue.microcosm.links.getBacklinks` and get generated type definitions,
7171+ // which kinda defeats the purpose of using Client in the first place. For
7272+ // these reasons, we are using this.cachedFetch directly to call the
7373+ // constellation API endpoint, and type casting the response.
6574 const source = encodeURIComponent(`${collection}:${recordPath}`)
6675 let urlToCall = `https://${CONSTELLATION_HOST}/xrpc/blue.microcosm.links.getBacklinks?subject=${encodeURIComponent(subject)}&source=${source}&limit=${limit}`
6776 if (cursor) urlToCall += `&cursor=${cursor}`