@atproto/bsky 0.3.13 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/api/app/bsky/actor/getProfile.d.ts.map +1 -1
  3. package/dist/api/app/bsky/actor/getProfile.js +1 -0
  4. package/dist/api/app/bsky/actor/getProfile.js.map +1 -1
  5. package/dist/api/app/bsky/actor/getProfiles.d.ts.map +1 -1
  6. package/dist/api/app/bsky/actor/getProfiles.js +1 -0
  7. package/dist/api/app/bsky/actor/getProfiles.js.map +1 -1
  8. package/dist/api/app/bsky/actor/getSuggestions.d.ts.map +1 -1
  9. package/dist/api/app/bsky/actor/getSuggestions.js +1 -0
  10. package/dist/api/app/bsky/actor/getSuggestions.js.map +1 -1
  11. package/dist/api/app/bsky/actor/searchActors.d.ts.map +1 -1
  12. package/dist/api/app/bsky/actor/searchActors.js +1 -0
  13. package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
  14. package/dist/api/app/bsky/actor/searchActorsTypeahead.d.ts.map +1 -1
  15. package/dist/api/app/bsky/actor/searchActorsTypeahead.js +1 -0
  16. package/dist/api/app/bsky/actor/searchActorsTypeahead.js.map +1 -1
  17. package/dist/api/app/bsky/bookmark/getBookmarks.d.ts.map +1 -1
  18. package/dist/api/app/bsky/bookmark/getBookmarks.js +1 -0
  19. package/dist/api/app/bsky/bookmark/getBookmarks.js.map +1 -1
  20. package/dist/api/app/bsky/contact/getMatches.d.ts.map +1 -1
  21. package/dist/api/app/bsky/contact/getMatches.js +1 -0
  22. package/dist/api/app/bsky/contact/getMatches.js.map +1 -1
  23. package/dist/api/app/bsky/contact/importContacts.d.ts.map +1 -1
  24. package/dist/api/app/bsky/contact/importContacts.js +1 -0
  25. package/dist/api/app/bsky/contact/importContacts.js.map +1 -1
  26. package/dist/api/app/bsky/feed/getActorFeeds.d.ts.map +1 -1
  27. package/dist/api/app/bsky/feed/getActorFeeds.js +5 -1
  28. package/dist/api/app/bsky/feed/getActorFeeds.js.map +1 -1
  29. package/dist/api/app/bsky/feed/getActorLikes.d.ts.map +1 -1
  30. package/dist/api/app/bsky/feed/getActorLikes.js +1 -0
  31. package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
  32. package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
  33. package/dist/api/app/bsky/feed/getAuthorFeed.js +1 -0
  34. package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
  35. package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
  36. package/dist/api/app/bsky/feed/getFeed.js +1 -0
  37. package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
  38. package/dist/api/app/bsky/feed/getFeedGenerator.d.ts.map +1 -1
  39. package/dist/api/app/bsky/feed/getFeedGenerator.js +5 -1
  40. package/dist/api/app/bsky/feed/getFeedGenerator.js.map +1 -1
  41. package/dist/api/app/bsky/feed/getFeedGenerators.d.ts.map +1 -1
  42. package/dist/api/app/bsky/feed/getFeedGenerators.js +5 -1
  43. package/dist/api/app/bsky/feed/getFeedGenerators.js.map +1 -1
  44. package/dist/api/app/bsky/feed/getLikes.d.ts.map +1 -1
  45. package/dist/api/app/bsky/feed/getLikes.js +1 -0
  46. package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
  47. package/dist/api/app/bsky/feed/getListFeed.d.ts.map +1 -1
  48. package/dist/api/app/bsky/feed/getListFeed.js +1 -0
  49. package/dist/api/app/bsky/feed/getListFeed.js.map +1 -1
  50. package/dist/api/app/bsky/feed/getPostThread.d.ts.map +1 -1
  51. package/dist/api/app/bsky/feed/getPostThread.js +1 -0
  52. package/dist/api/app/bsky/feed/getPostThread.js.map +1 -1
  53. package/dist/api/app/bsky/feed/getPosts.d.ts.map +1 -1
  54. package/dist/api/app/bsky/feed/getPosts.js +5 -1
  55. package/dist/api/app/bsky/feed/getPosts.js.map +1 -1
  56. package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
  57. package/dist/api/app/bsky/feed/getQuotes.js +1 -0
  58. package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
  59. package/dist/api/app/bsky/feed/getRepostedBy.d.ts.map +1 -1
  60. package/dist/api/app/bsky/feed/getRepostedBy.js +1 -0
  61. package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
  62. package/dist/api/app/bsky/feed/getSuggestedFeeds.d.ts.map +1 -1
  63. package/dist/api/app/bsky/feed/getSuggestedFeeds.js +5 -1
  64. package/dist/api/app/bsky/feed/getSuggestedFeeds.js.map +1 -1
  65. package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
  66. package/dist/api/app/bsky/feed/getTimeline.js +1 -0
  67. package/dist/api/app/bsky/feed/getTimeline.js.map +1 -1
  68. package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
  69. package/dist/api/app/bsky/feed/searchPosts.js +1 -0
  70. package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
  71. package/dist/api/app/bsky/feed/searchPostsV2.d.ts.map +1 -1
  72. package/dist/api/app/bsky/feed/searchPostsV2.js +1 -0
  73. package/dist/api/app/bsky/feed/searchPostsV2.js.map +1 -1
  74. package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -1
  75. package/dist/api/app/bsky/graph/getActorStarterPacks.js +1 -0
  76. package/dist/api/app/bsky/graph/getActorStarterPacks.js.map +1 -1
  77. package/dist/api/app/bsky/graph/getBlocks.d.ts.map +1 -1
  78. package/dist/api/app/bsky/graph/getBlocks.js +5 -1
  79. package/dist/api/app/bsky/graph/getBlocks.js.map +1 -1
  80. package/dist/api/app/bsky/graph/getFollowers.d.ts.map +1 -1
  81. package/dist/api/app/bsky/graph/getFollowers.js +1 -0
  82. package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
  83. package/dist/api/app/bsky/graph/getFollows.d.ts.map +1 -1
  84. package/dist/api/app/bsky/graph/getFollows.js +1 -0
  85. package/dist/api/app/bsky/graph/getFollows.js.map +1 -1
  86. package/dist/api/app/bsky/graph/getKnownFollowers.d.ts.map +1 -1
  87. package/dist/api/app/bsky/graph/getKnownFollowers.js +1 -0
  88. package/dist/api/app/bsky/graph/getKnownFollowers.js.map +1 -1
  89. package/dist/api/app/bsky/graph/getList.d.ts.map +1 -1
  90. package/dist/api/app/bsky/graph/getList.js +1 -0
  91. package/dist/api/app/bsky/graph/getList.js.map +1 -1
  92. package/dist/api/app/bsky/graph/getListBlocks.d.ts.map +1 -1
  93. package/dist/api/app/bsky/graph/getListBlocks.js +5 -1
  94. package/dist/api/app/bsky/graph/getListBlocks.js.map +1 -1
  95. package/dist/api/app/bsky/graph/getListMutes.d.ts.map +1 -1
  96. package/dist/api/app/bsky/graph/getListMutes.js +5 -1
  97. package/dist/api/app/bsky/graph/getListMutes.js.map +1 -1
  98. package/dist/api/app/bsky/graph/getLists.d.ts.map +1 -1
  99. package/dist/api/app/bsky/graph/getLists.js +1 -0
  100. package/dist/api/app/bsky/graph/getLists.js.map +1 -1
  101. package/dist/api/app/bsky/graph/getListsWithMembership.d.ts.map +1 -1
  102. package/dist/api/app/bsky/graph/getListsWithMembership.js +1 -0
  103. package/dist/api/app/bsky/graph/getListsWithMembership.js.map +1 -1
  104. package/dist/api/app/bsky/graph/getMutes.d.ts.map +1 -1
  105. package/dist/api/app/bsky/graph/getMutes.js +5 -1
  106. package/dist/api/app/bsky/graph/getMutes.js.map +1 -1
  107. package/dist/api/app/bsky/graph/getStarterPack.d.ts.map +1 -1
  108. package/dist/api/app/bsky/graph/getStarterPack.js +1 -0
  109. package/dist/api/app/bsky/graph/getStarterPack.js.map +1 -1
  110. package/dist/api/app/bsky/graph/getStarterPacks.d.ts.map +1 -1
  111. package/dist/api/app/bsky/graph/getStarterPacks.js +1 -0
  112. package/dist/api/app/bsky/graph/getStarterPacks.js.map +1 -1
  113. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.d.ts.map +1 -1
  114. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js +1 -0
  115. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -1
  116. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.d.ts.map +1 -1
  117. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js +1 -0
  118. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js.map +1 -1
  119. package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -1
  120. package/dist/api/app/bsky/graph/searchStarterPacks.js +1 -0
  121. package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -1
  122. package/dist/api/app/bsky/graph/searchStarterPacksV2.d.ts.map +1 -1
  123. package/dist/api/app/bsky/graph/searchStarterPacksV2.js +1 -0
  124. package/dist/api/app/bsky/graph/searchStarterPacksV2.js.map +1 -1
  125. package/dist/api/app/bsky/labeler/getServices.d.ts.map +1 -1
  126. package/dist/api/app/bsky/labeler/getServices.js +1 -0
  127. package/dist/api/app/bsky/labeler/getServices.js.map +1 -1
  128. package/dist/api/app/bsky/notification/getGroupedNotifications.d.ts.map +1 -1
  129. package/dist/api/app/bsky/notification/getGroupedNotifications.js +41 -20
  130. package/dist/api/app/bsky/notification/getGroupedNotifications.js.map +1 -1
  131. package/dist/api/app/bsky/notification/grouping/algoGravity.d.ts +4 -3
  132. package/dist/api/app/bsky/notification/grouping/algoGravity.d.ts.map +1 -1
  133. package/dist/api/app/bsky/notification/grouping/algoGravity.js +53 -42
  134. package/dist/api/app/bsky/notification/grouping/algoGravity.js.map +1 -1
  135. package/dist/api/app/bsky/notification/grouping/algoLookback.d.ts +4 -3
  136. package/dist/api/app/bsky/notification/grouping/algoLookback.d.ts.map +1 -1
  137. package/dist/api/app/bsky/notification/grouping/algoLookback.js +56 -42
  138. package/dist/api/app/bsky/notification/grouping/algoLookback.js.map +1 -1
  139. package/dist/api/app/bsky/notification/grouping/grouping.d.ts +12 -2
  140. package/dist/api/app/bsky/notification/grouping/grouping.d.ts.map +1 -1
  141. package/dist/api/app/bsky/notification/grouping/grouping.js +20 -6
  142. package/dist/api/app/bsky/notification/grouping/grouping.js.map +1 -1
  143. package/dist/api/app/bsky/notification/grouping/spotlight.d.ts +2 -2
  144. package/dist/api/app/bsky/notification/grouping/spotlight.d.ts.map +1 -1
  145. package/dist/api/app/bsky/notification/grouping/spotlight.js +35 -22
  146. package/dist/api/app/bsky/notification/grouping/spotlight.js.map +1 -1
  147. package/dist/api/app/bsky/notification/listActivitySubscriptions.d.ts.map +1 -1
  148. package/dist/api/app/bsky/notification/listActivitySubscriptions.js +1 -0
  149. package/dist/api/app/bsky/notification/listActivitySubscriptions.js.map +1 -1
  150. package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
  151. package/dist/api/app/bsky/notification/listNotifications.js +5 -1
  152. package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
  153. package/dist/api/app/bsky/unspecced/atmosphere-grouping.d.ts +16 -0
  154. package/dist/api/app/bsky/unspecced/atmosphere-grouping.d.ts.map +1 -0
  155. package/dist/api/app/bsky/unspecced/atmosphere-grouping.js +124 -0
  156. package/dist/api/app/bsky/unspecced/atmosphere-grouping.js.map +1 -0
  157. package/dist/api/app/bsky/unspecced/atmosphere-hydration.d.ts +32 -0
  158. package/dist/api/app/bsky/unspecced/atmosphere-hydration.d.ts.map +1 -0
  159. package/dist/api/app/bsky/unspecced/atmosphere-hydration.js +201 -0
  160. package/dist/api/app/bsky/unspecced/atmosphere-hydration.js.map +1 -0
  161. package/dist/api/app/bsky/unspecced/atmosphere-pagination.d.ts +6 -0
  162. package/dist/api/app/bsky/unspecced/atmosphere-pagination.d.ts.map +1 -0
  163. package/dist/api/app/bsky/unspecced/atmosphere-pagination.js +164 -0
  164. package/dist/api/app/bsky/unspecced/atmosphere-pagination.js.map +1 -0
  165. package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.d.ts.map +1 -1
  166. package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.js +120 -55
  167. package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.js.map +1 -1
  168. package/dist/api/app/bsky/unspecced/getAtmosphereTimeline.d.ts +4 -0
  169. package/dist/api/app/bsky/unspecced/getAtmosphereTimeline.d.ts.map +1 -0
  170. package/dist/api/app/bsky/unspecced/getAtmosphereTimeline.js +30 -0
  171. package/dist/api/app/bsky/unspecced/getAtmosphereTimeline.js.map +1 -0
  172. package/dist/api/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.d.ts.map +1 -1
  173. package/dist/api/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.js +4 -7
  174. package/dist/api/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.js.map +1 -1
  175. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.d.ts.map +1 -1
  176. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js +1 -0
  177. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js.map +1 -1
  178. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -1
  179. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js +1 -0
  180. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -1
  181. package/dist/api/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -1
  182. package/dist/api/app/bsky/unspecced/getPostThreadV2.js +1 -0
  183. package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
  184. package/dist/api/app/bsky/unspecced/getSuggestedFeeds.d.ts.map +1 -1
  185. package/dist/api/app/bsky/unspecced/getSuggestedFeeds.js +4 -7
  186. package/dist/api/app/bsky/unspecced/getSuggestedFeeds.js.map +1 -1
  187. package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts.map +1 -1
  188. package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.js +1 -0
  189. package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.js.map +1 -1
  190. package/dist/api/app/bsky/unspecced/getSuggestedStarterPacks.d.ts.map +1 -1
  191. package/dist/api/app/bsky/unspecced/getSuggestedStarterPacks.js +4 -7
  192. package/dist/api/app/bsky/unspecced/getSuggestedStarterPacks.js.map +1 -1
  193. package/dist/api/app/bsky/unspecced/getSuggestedUsers.d.ts.map +1 -1
  194. package/dist/api/app/bsky/unspecced/getSuggestedUsers.js +2 -19
  195. package/dist/api/app/bsky/unspecced/getSuggestedUsers.js.map +1 -1
  196. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts.map +1 -1
  197. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.js +1 -0
  198. package/dist/api/app/bsky/unspecced/getSuggestedUsersForDiscover.js.map +1 -1
  199. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts.map +1 -1
  200. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.js +1 -0
  201. package/dist/api/app/bsky/unspecced/getSuggestedUsersForExplore.js.map +1 -1
  202. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts.map +1 -1
  203. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.js +1 -0
  204. package/dist/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.js.map +1 -1
  205. package/dist/api/app/bsky/unspecced/getTrendingTopics.d.ts.map +1 -1
  206. package/dist/api/app/bsky/unspecced/getTrendingTopics.js +6 -2
  207. package/dist/api/app/bsky/unspecced/getTrendingTopics.js.map +1 -1
  208. package/dist/api/app/bsky/unspecced/getTrends.d.ts.map +1 -1
  209. package/dist/api/app/bsky/unspecced/getTrends.js +6 -2
  210. package/dist/api/app/bsky/unspecced/getTrends.js.map +1 -1
  211. package/dist/api/blob-resolver.d.ts.map +1 -1
  212. package/dist/api/blob-resolver.js +9 -8
  213. package/dist/api/blob-resolver.js.map +1 -1
  214. package/dist/api/index.d.ts.map +1 -1
  215. package/dist/api/index.js +2 -0
  216. package/dist/api/index.js.map +1 -1
  217. package/dist/api/internal/bsky/actor/getProfiles.d.ts.map +1 -1
  218. package/dist/api/internal/bsky/actor/getProfiles.js +1 -0
  219. package/dist/api/internal/bsky/actor/getProfiles.js.map +1 -1
  220. package/dist/config.d.ts +2 -6
  221. package/dist/config.d.ts.map +1 -1
  222. package/dist/config.js +7 -16
  223. package/dist/config.js.map +1 -1
  224. package/dist/context.d.ts +0 -2
  225. package/dist/context.d.ts.map +1 -1
  226. package/dist/context.js +0 -3
  227. package/dist/context.js.map +1 -1
  228. package/dist/feature-gates/gates.d.ts +0 -4
  229. package/dist/feature-gates/gates.d.ts.map +1 -1
  230. package/dist/feature-gates/gates.js +0 -4
  231. package/dist/feature-gates/gates.js.map +1 -1
  232. package/dist/hydration/external.d.ts +58 -45
  233. package/dist/hydration/external.d.ts.map +1 -1
  234. package/dist/hydration/external.js +134 -114
  235. package/dist/hydration/external.js.map +1 -1
  236. package/dist/hydration/hydrator.d.ts +15 -9
  237. package/dist/hydration/hydrator.d.ts.map +1 -1
  238. package/dist/hydration/hydrator.js +170 -210
  239. package/dist/hydration/hydrator.js.map +1 -1
  240. package/dist/image/server.d.ts.map +1 -1
  241. package/dist/image/server.js +12 -1
  242. package/dist/image/server.js.map +1 -1
  243. package/dist/index.d.ts.map +1 -1
  244. package/dist/index.js +4 -19
  245. package/dist/index.js.map +1 -1
  246. package/dist/lexicons/app/bsky/unspecced/getAtmosphereExploreTab.defs.d.ts +29 -0
  247. package/dist/lexicons/app/bsky/unspecced/getAtmosphereExploreTab.defs.d.ts.map +1 -1
  248. package/dist/lexicons/app/bsky/unspecced/getAtmosphereExploreTab.defs.js +2 -1
  249. package/dist/lexicons/app/bsky/unspecced/getAtmosphereExploreTab.defs.js.map +1 -1
  250. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.d.ts +3 -0
  251. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.d.ts.map +1 -0
  252. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.defs.d.ts +85 -0
  253. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.defs.d.ts.map +1 -0
  254. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.defs.js +29 -0
  255. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.defs.js.map +1 -0
  256. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.js +6 -0
  257. package/dist/lexicons/app/bsky/unspecced/getAtmosphereTimeline.js.map +1 -0
  258. package/dist/lexicons/app/bsky/unspecced.d.ts +1 -0
  259. package/dist/lexicons/app/bsky/unspecced.d.ts.map +1 -1
  260. package/dist/lexicons/app/bsky/unspecced.js +1 -0
  261. package/dist/lexicons/app/bsky/unspecced.js.map +1 -1
  262. package/dist/lexicons/tools/ozone/moderation/emitEvent.defs.d.ts +2 -2
  263. package/dist/lexicons/tools/ozone/moderation/emitEvent.defs.js.map +1 -1
  264. package/dist/lexicons/tools/ozone/report/closeReports.defs.d.ts +1 -1
  265. package/dist/lexicons/tools/ozone/report/closeReports.defs.d.ts.map +1 -1
  266. package/dist/lexicons/tools/ozone/report/closeReports.defs.js +1 -1
  267. package/dist/lexicons/tools/ozone/report/closeReports.defs.js.map +1 -1
  268. package/dist/telemetry/events.d.ts +14 -6
  269. package/dist/telemetry/events.d.ts.map +1 -1
  270. package/dist/telemetry/events.js +40 -5
  271. package/dist/telemetry/events.js.map +1 -1
  272. package/dist/util/external/standard-site.d.ts +2 -3
  273. package/dist/util/external/standard-site.d.ts.map +1 -1
  274. package/dist/util/external/standard-site.js +2 -3
  275. package/dist/util/external/standard-site.js.map +1 -1
  276. package/dist/util/uris.d.ts +5 -2
  277. package/dist/util/uris.d.ts.map +1 -1
  278. package/dist/util/uris.js +14 -1
  279. package/dist/util/uris.js.map +1 -1
  280. package/dist/views/external.d.ts +5 -0
  281. package/dist/views/external.d.ts.map +1 -1
  282. package/dist/views/external.js +38 -11
  283. package/dist/views/external.js.map +1 -1
  284. package/dist/views/index.d.ts +2 -2
  285. package/dist/views/index.d.ts.map +1 -1
  286. package/dist/views/index.js +17 -11
  287. package/dist/views/index.js.map +1 -1
  288. package/package.json +13 -14
@@ -6,12 +6,11 @@ import { NOTIFICATION_REASON } from '../api/app/bsky/notification/constants.js';
6
6
  import { app, chat, com, place, site, social } from '../lexicons/index.js';
7
7
  import { hydrationLogger } from '../logger.js';
8
8
  import { events } from '../telemetry/events.js';
9
- import { SITE_STANDARD_NSID_PREFIX } from '../util/external/standard-site.js';
10
- import { uriToDid, uriToDid as didFromUri } from '../util/uris.js';
9
+ import { recordUriOf, uriToDid, uriToDid as didFromUri } from '../util/uris.js';
11
10
  import { MAX_PROFILE_LINKS } from '../views/profile-link-rules.js';
12
- import { isExternalEmbedType, isListRuleType, isRecordEmbedType, isRecordWithMediaType, } from '../views/types.js';
11
+ import { isListRuleType, isRecordEmbedType, isRecordWithMediaType, } from '../views/types.js';
13
12
  import { ActorHydrator, } from './actor.js';
14
- import { ExternalHydrator, actionExternalRecordTakedowns, genericRecordKey, parseGenericRecordKey, trackExternalHydration, } from './external.js';
13
+ import { EXTERNAL_HYDRATION_LIMITS, ExternalHydrator, MAX_CONCURRENT_BACKLINK_REQUESTS, MAX_EXTERNAL_HYDRATION_PASSES, actionExternalRecordTakedowns, externalAssociatedRefsFromPosts, genericRecordKey, trackExternalHydration, } from './external.js';
15
14
  import { FeedHydrator, } from './feed.js';
16
15
  import { GraphHydrator, } from './graph.js';
17
16
  import { LabelHydrator, Labels, } from './label.js';
@@ -424,13 +423,7 @@ export class Hydrator {
424
423
  postUrisWithPostgates.add(uri);
425
424
  }
426
425
  }
427
- const siteStandardRefs = siteStandardRefsFromPosts(postsLayer0, postsLayer1, postsLayer2);
428
- const siteStandardLabelSubjects = dedupeStrs(siteStandardRefs.map((ref) => ref.uri));
429
- // Site-standard record owners need profile basics so we can populate
430
- // `associatedProfiles` on the external embed view. Include them in the
431
- // post-author profile fetch below; any DIDs surfaced later by the
432
- // dataplane are picked up by the top-up after the parallel batch.
433
- const ssRefDids = siteStandardRefs.map((ref) => uriToDid(ref.uri));
426
+ const externalRefs = externalAssociatedRefsFromPosts(postsLayer0, postsLayer1, postsLayer2);
434
427
  // Collect known-liker profiles and author-liker block relationships.
435
428
  const knownLikers = await knownLikersPromise;
436
429
  const knownLikerDids = [];
@@ -446,45 +439,34 @@ export class Hydrator {
446
439
  });
447
440
  const knownProfileDids = dedupeStrs([
448
441
  ...allPostUris.map(didFromUri),
449
- ...ssRefDids,
450
442
  ...knownLikerDids,
451
443
  ]);
452
- const [postAggs, postViewers, labels, { postBlocks, additionalRelationshipsBidirectionalBlocks: authorsAndKnownLikersBidirectionalBlocks, }, profileState, listState, feedGenState, labelerState, starterPackState, postgates, { documents: siteStandardDocuments, publications: siteStandardPublications, },] = await Promise.all([
444
+ const [postAggs, postViewers, labels, { postBlocks, additionalRelationshipsBidirectionalBlocks: authorsAndKnownLikersBidirectionalBlocks, }, profileState, listState, feedGenState, labelerState, starterPackState, postgates, externalState,] = await Promise.all([
453
445
  this.feed.getPostAggregates(allRefs, ctx.viewer),
454
446
  ctx.viewer
455
447
  ? this.feed.getPostViewerStates(threadRefs, ctx.viewer)
456
448
  : undefined,
457
- this.label.getLabelsForSubjects([...allPostUris, ...siteStandardLabelSubjects], ctx.labelers),
458
- this.hydratePostBlocks(posts, ctx, authorsAndKnownLikersRelationships),
449
+ this.label.getLabelsForSubjects(allPostUris, ctx.labelers),
450
+ this.hydratePostBlocks(posts, ctx, authorsAndKnownLikersRelationships, {
451
+ skipReplyBlocks: options.skipReplyBlocks,
452
+ }),
459
453
  this.hydrateProfiles(knownProfileDids, ctx),
460
454
  this.hydrateLists([...nestedListUris, ...threadgateListUris], ctx),
461
455
  this.hydrateFeedGens(nestedFeedGenUris, ctx),
462
456
  this.hydrateLabelers(nestedLabelerDids, ctx),
463
457
  this.hydrateStarterPacksBasic(nestedStarterPackUris, ctx),
464
458
  this.feed.getPostgatesForPosts([...postUrisWithPostgates.values()]),
465
- this.external.getSiteStandardRecordsByRef(siteStandardRefs, ctx.includeTakedowns),
459
+ this.hydrateEmbedExternalViewFromRefs(externalRefs, ctx, {
460
+ hydration: 'basic',
461
+ seenRecordKeys: options.externalSeenRecordKeys,
462
+ publicationSubscriptions: options.externalPublicationSubscriptions,
463
+ }),
466
464
  ]);
467
465
  if (!ctx.includeTakedowns) {
468
466
  actionTakedownLabels(allPostUris, posts, labels);
469
- actionSiteStandardTakedownLabels(siteStandardDocuments, siteStandardPublications, labels);
470
- }
471
- // Defensive top-up: in the unlikely case the dataplane returned a
472
- // publication owned by a DID not present in the post-author or
473
- // pinned-ref sets, fetch its profile serially and fold it in.
474
- const knownProfileDidsSet = new Set(knownProfileDids);
475
- const extraSsDids = [];
476
- for (const key of siteStandardPublications.keys()) {
477
- const did = uriToDid(parseGenericRecordKey(key).uri);
478
- if (!knownProfileDidsSet.has(did)) {
479
- knownProfileDidsSet.add(did);
480
- extraSsDids.push(did);
481
- }
482
467
  }
483
- const mergedProfileState = extraSsDids.length
484
- ? mergeStates(profileState, await this.hydrateProfilesBasic(extraSsDids, ctx))
485
- : profileState;
486
468
  // combine all hydration state
487
- return mergeManyStates(mergedProfileState, listState, feedGenState, labelerState, starterPackState, {
469
+ return mergeManyStates(externalState, profileState, listState, feedGenState, labelerState, starterPackState, {
488
470
  posts,
489
471
  postAggs,
490
472
  postViewers,
@@ -494,12 +476,10 @@ export class Hydrator {
494
476
  labels,
495
477
  threadgates,
496
478
  postgates,
497
- siteStandardDocuments,
498
- siteStandardPublications,
499
479
  ctx,
500
480
  });
501
481
  }
502
- async hydratePostBlocks(posts, ctx, additionalRelationships = []) {
482
+ async hydratePostBlocks(posts, ctx, additionalRelationships = [], opts) {
503
483
  const postBlocks = new HydrationMap();
504
484
  const postBlocksPairs = new Map();
505
485
  const relationships = [];
@@ -510,20 +490,21 @@ export class Hydrator {
510
490
  const creator = didFromUri(uri);
511
491
  const postBlockPairs = {};
512
492
  postBlocksPairs.set(uri, postBlockPairs);
513
- // 3p block for replies
514
- const parentUri = post.reply?.parent.uri;
515
- const parentDid = parentUri && didFromUri(parentUri);
516
- if (parentDid && parentDid !== creator) {
517
- const pair = [creator, parentDid];
518
- relationships.push(pair);
519
- postBlockPairs.parent = pair;
520
- }
521
- const rootUri = post.reply?.root.uri;
522
- const rootDid = rootUri && didFromUri(rootUri);
523
- if (rootDid && rootDid !== creator) {
524
- const pair = [creator, rootDid];
525
- relationships.push(pair);
526
- postBlockPairs.root = pair;
493
+ if (!opts?.skipReplyBlocks) {
494
+ const parentUri = post.reply?.parent.uri;
495
+ const parentDid = parentUri && didFromUri(parentUri);
496
+ if (parentDid && parentDid !== creator) {
497
+ const pair = [creator, parentDid];
498
+ relationships.push(pair);
499
+ postBlockPairs.parent = pair;
500
+ }
501
+ const rootUri = post.reply?.root.uri;
502
+ const rootDid = rootUri && didFromUri(rootUri);
503
+ if (rootDid && rootDid !== creator) {
504
+ const pair = [creator, rootDid];
505
+ relationships.push(pair);
506
+ postBlockPairs.root = pair;
507
+ }
527
508
  }
528
509
  // 3p block for record embeds
529
510
  for (const embedUri of nestedRecordUris(post)) {
@@ -626,27 +607,33 @@ export class Hydrator {
626
607
  * generic batch within the traversal (the root batch is pass 1); nested
627
608
  * batches continue the count. Nested passes share the caller's
628
609
  * `hydrationMetrics` tracker; without one, this call owns the traversal and
629
- * reports its totals.
610
+ * reports its totals. `options.hydration` (default `'detailed'`) applies to
611
+ * the whole traversal and is propagated to every nested pass.
630
612
  */
631
- async hydrateEmbedExternalViewFromUris(uris, ctx, seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics) {
632
- return trackExternalHydration('uris', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.hydrateEmbedExternalView(uris.map(uriToRef), ctx, seenRecordKeys, hydrationPass, hydrationMetrics));
613
+ async hydrateEmbedExternalViewFromUris(uris, ctx, options = {}) {
614
+ const { hydration = 'detailed', seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics, publicationSubscriptions, } = options;
615
+ return trackExternalHydration('uris', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.hydrateEmbedExternalView(uris.map(uriToRef), ctx, hydration, seenRecordKeys, hydrationPass, hydrationMetrics, publicationSubscriptions));
633
616
  }
634
617
  /**
635
618
  * Like `hydrateEmbedExternalViewFromUris`, but for exact record versions
636
619
  * pinned by strong refs. Roots land only in `externalRecordsByRef`; their
637
620
  * URI dependencies are hydrated as latest versions by the URI path.
638
621
  */
639
- async hydrateEmbedExternalViewFromRefs(refs, ctx, seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics) {
640
- return trackExternalHydration('refs', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.hydrateEmbedExternalView(refs, ctx, seenRecordKeys, hydrationPass, hydrationMetrics));
622
+ async hydrateEmbedExternalViewFromRefs(refs, ctx, options = {}) {
623
+ const { hydration = 'detailed', seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics, publicationSubscriptions, } = options;
624
+ return trackExternalHydration('refs', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.hydrateEmbedExternalView(refs, ctx, hydration, seenRecordKeys, hydrationPass, hydrationMetrics, publicationSubscriptions));
641
625
  }
642
- async hydrateEmbedExternalView(refs, ctx, seenRecordKeys, hydrationPass, hydrationMetrics) {
626
+ async hydrateEmbedExternalView(refs, ctx, hydration, seenRecordKeys, hydrationPass, hydrationMetrics, publicationSubscriptions) {
643
627
  // Filter at the entry point so each lookup runs at most once per shared
644
628
  // traversal, even for callers that did not prefilter their input. Null or
645
629
  // unavailable results stay seen as completed lookups. Nothing unseen means
646
630
  // no hydration work, and no pass is consumed.
647
631
  const items = takeUnseenRefs(refs, seenRecordKeys);
648
- if (!items.length)
649
- return { ctx };
632
+ if (!items.length) {
633
+ return publicationSubscriptions
634
+ ? { ctx, externalPublicationSubscriptions: publicationSubscriptions }
635
+ : { ctx };
636
+ }
650
637
  // Get any bare URIs to fetch
651
638
  const byUriValues = items
652
639
  .filter(({ cid }) => cid === undefined)
@@ -696,10 +683,17 @@ export class Hydrator {
696
683
  labels,
697
684
  externalRecords,
698
685
  externalRecordsByRef,
686
+ externalPublicationSubscriptions: publicationSubscriptions,
699
687
  });
700
688
  actionExternalRecordTakedowns(baseState, ctx.includeTakedowns);
701
689
  // Discover and hydrate any additional view dependencies
702
- const depsState = await this.hydrateExternalViewDependencies(baseState, items, ctx, seenRecordKeys, hydrationPass, hydrationMetrics);
690
+ const depsState = await this.hydrateExternalViewDependencies(baseState, items, ctx, {
691
+ hydration,
692
+ seenRecordKeys,
693
+ hydrationPass,
694
+ hydrationMetrics,
695
+ publicationSubscriptions,
696
+ });
703
697
  // A supplemental latest lookup returning the same URI and CID is the same
704
698
  // version, so it may replace an unavailable exact entry; other CIDs have
705
699
  // other keys and never satisfy a pin.
@@ -718,15 +712,21 @@ export class Hydrator {
718
712
  * `hydrationPass` is the number of the generic batch that produced `state`
719
713
  * (1-based, default 1 for prehydrated state, which is treated as the root
720
714
  * batch); the next nested batch is `hydrationPass + 1`. `hydrationMetrics`
721
- * is shared as in `hydrateEmbedExternalViewFromUris`.
715
+ * is shared as in `hydrateEmbedExternalViewFromUris`. `options.hydration`
716
+ * (default `'detailed'`) decides, per collection, whether social-preview
717
+ * samples are scheduled; backlink counts and content dependencies are
718
+ * discovered at both levels.
722
719
  */
723
- async hydrateExternalViewDependencies(state, refs, ctx, seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics) {
724
- return trackExternalHydration('dependencies', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.discoverExternalViewDependencies(state, refs, ctx, seenRecordKeys, hydrationPass, hydrationMetrics));
720
+ async hydrateExternalViewDependencies(state, refs, ctx, options = {}) {
721
+ const { hydration = 'detailed', seenRecordKeys = new Set(), hydrationPass = 1, hydrationMetrics, publicationSubscriptions, } = options;
722
+ return trackExternalHydration('dependencies', ctx.xrpcEndpoint, hydrationMetrics, (hydrationMetrics) => this.discoverExternalViewDependencies(state, refs, ctx, hydration, seenRecordKeys, hydrationPass, hydrationMetrics, publicationSubscriptions));
725
723
  }
726
- async discoverExternalViewDependencies(state, refs, ctx, seenRecordKeys, hydrationPass, hydrationMetrics) {
727
- // Backlink sources to sample per target, each with its own bound.
724
+ async discoverExternalViewDependencies(state, refs, ctx, hydration, seenRecordKeys, hydrationPass, hydrationMetrics, publicationSubscriptions) {
725
+ // Social-preview backlink sources to sample per target, each with its own
726
+ // bound. A target with no samples still gets its aggregate count.
728
727
  const targets = new Map();
729
728
  const discoveredUris = new Set();
729
+ const publicationUris = new Set();
730
730
  const rootBatch = !hydrationMetrics.rootsCounted;
731
731
  hydrationMetrics.rootsCounted = true;
732
732
  for (const ref of refs) {
@@ -756,7 +756,8 @@ export class Hydrator {
756
756
  if (!parsed.success ||
757
757
  !isDidString(parsed.value.authority) ||
758
758
  !parsed.value.rkey ||
759
- parsed.value.hash) {
759
+ parsed.value.query !== undefined ||
760
+ parsed.value.hash !== undefined) {
760
761
  continue;
761
762
  }
762
763
  /*
@@ -765,24 +766,33 @@ export class Hydrator {
765
766
  const { collection } = parsed.value;
766
767
  if (collection === site.standard.document.$type &&
767
768
  site.standard.document.$matches(record, { strict: false })) {
768
- targets.set(uri, [
769
- {
770
- collection: site.standard.graph.recommend.$type,
771
- limit: ExternalHydrator.MAX_BACKLINK_PREVIEWS,
772
- },
773
- ]);
769
+ const limits = EXTERNAL_HYDRATION_LIMITS[site.standard.document.$type];
770
+ targets.set(uri, hydration === 'detailed'
771
+ ? [
772
+ {
773
+ collection: site.standard.graph.recommend.$type,
774
+ limit: limits.recommendationPreviews,
775
+ },
776
+ ]
777
+ : []);
774
778
  const publicationUri = recordUriOf(record.site, site.standard.publication.$type);
775
- if (publicationUri)
779
+ if (publicationUri) {
776
780
  discoveredUris.add(publicationUri);
781
+ publicationUris.add(publicationUri);
782
+ }
777
783
  }
778
784
  else if (collection === site.standard.publication.$type &&
779
785
  site.standard.publication.$matches(record, { strict: false })) {
780
- targets.set(uri, [
781
- {
782
- collection: site.standard.graph.subscription.$type,
783
- limit: ExternalHydrator.MAX_BACKLINK_PREVIEWS,
784
- },
785
- ]);
786
+ publicationUris.add(uri);
787
+ const limits = EXTERNAL_HYDRATION_LIMITS[site.standard.publication.$type];
788
+ targets.set(uri, hydration === 'detailed'
789
+ ? [
790
+ {
791
+ collection: site.standard.graph.subscription.$type,
792
+ limit: limits.subscriberPreviews,
793
+ },
794
+ ]
795
+ : []);
786
796
  }
787
797
  else if (collection === place.stream.livestream.$type &&
788
798
  place.stream.livestream.$matches(record, { strict: false })) {
@@ -790,16 +800,20 @@ export class Hydrator {
790
800
  }
791
801
  else if (collection === social.grain.gallery.$type &&
792
802
  social.grain.gallery.$matches(record, { strict: false })) {
793
- targets.set(uri, [
794
- {
803
+ const limits = EXTERNAL_HYDRATION_LIMITS[social.grain.gallery.$type];
804
+ // Membership items are content, sampled at every level.
805
+ const samples = [];
806
+ if (hydration === 'detailed') {
807
+ samples.push({
795
808
  collection: social.grain.favorite.$type,
796
- limit: ExternalHydrator.MAX_BACKLINK_PREVIEWS,
797
- },
798
- {
799
- collection: social.grain.gallery.item.$type,
800
- limit: ExternalHydrator.MAX_BACKLINK_GALLERY_ITEMS,
801
- },
802
- ]);
809
+ limit: limits.favoritePreviews,
810
+ });
811
+ }
812
+ samples.push({
813
+ collection: social.grain.gallery.item.$type,
814
+ limit: limits.items,
815
+ });
816
+ targets.set(uri, samples);
803
817
  }
804
818
  else if (collection === social.grain.gallery.item.$type &&
805
819
  social.grain.gallery.item.$matches(record, { strict: false })) {
@@ -808,6 +822,52 @@ export class Hydrator {
808
822
  if (photoUri)
809
823
  discoveredUris.add(photoUri);
810
824
  }
825
+ else if (
826
+ // @NOTE Preview actions must not refetch pinned targets as latest.
827
+ rootBatch &&
828
+ collection === site.standard.graph.recommend.$type &&
829
+ site.standard.graph.recommend.$matches(record, { strict: false })) {
830
+ const documentUri = recordUriOf(record.document, site.standard.document.$type);
831
+ if (documentUri)
832
+ discoveredUris.add(documentUri);
833
+ }
834
+ else if (rootBatch &&
835
+ collection === site.standard.graph.subscription.$type &&
836
+ site.standard.graph.subscription.$matches(record, { strict: false })) {
837
+ const publicationUri = recordUriOf(record.publication, site.standard.publication.$type);
838
+ if (publicationUri)
839
+ discoveredUris.add(publicationUri);
840
+ }
841
+ else if (rootBatch &&
842
+ collection === social.grain.favorite.$type &&
843
+ social.grain.favorite.$matches(record, { strict: false })) {
844
+ const galleryUri = recordUriOf(record.subject, social.grain.gallery.$type);
845
+ if (galleryUri)
846
+ discoveredUris.add(galleryUri);
847
+ }
848
+ }
849
+ if (publicationSubscriptions && ctx.viewer) {
850
+ const publications = [...publicationUris].filter((uri) => !publicationSubscriptions.has(uri));
851
+ // @NOTE Reserve even unknown outcomes before awaiting, so concurrent roots
852
+ // sharing this request's cache never repeat a subscription lookup.
853
+ for (const uri of publications)
854
+ publicationSubscriptions.set(uri, null);
855
+ for (const batch of chunkArray(publications, ExternalHydrator.MAX_BACKLINK_ACTOR_TARGETS_PER_REQUEST)) {
856
+ try {
857
+ const result = await this.external.getAtmosphereBacklinksByActor(batch, ctx.viewer, site.standard.graph.subscription.$type);
858
+ for (const publication of batch) {
859
+ const subscribed = result.backlinks
860
+ .get(publication)
861
+ ?.some((uri) => recordUriOf(uri, site.standard.graph.subscription.$type) &&
862
+ uriToDid(uri) === ctx.viewer);
863
+ publicationSubscriptions.set(publication, subscribed ? true : result.truncated ? null : false);
864
+ }
865
+ }
866
+ catch (err) {
867
+ hydrationMetrics.partial = true;
868
+ hydrationLogger.warn({ err }, 'failed to hydrate external publication subscriptions');
869
+ }
870
+ }
811
871
  }
812
872
  let externalRecordBacklinks;
813
873
  let externalRecordBacklinkCounts;
@@ -826,7 +886,7 @@ export class Hydrator {
826
886
  }),
827
887
  (async () => {
828
888
  // @NOTE Bound fan-out as well as each sample; counts are independent.
829
- for (const batch of chunkArray(queries, ExternalHydrator.MAX_BACKLINK_FANOUT)) {
889
+ for (const batch of chunkArray(queries, MAX_CONCURRENT_BACKLINK_REQUESTS)) {
830
890
  await Promise.all(batch.map(async ({ uri, collection, limit }) => {
831
891
  let page;
832
892
  try {
@@ -838,9 +898,11 @@ export class Hydrator {
838
898
  return;
839
899
  }
840
900
  const links = page.backlinks
841
- .filter((b) => parseAtUriString(b.uri).success)
842
- .slice(0, limit)
843
- .map((b) => b.uri);
901
+ .flatMap(({ uri }) => {
902
+ const link = recordUriOf(uri, collection);
903
+ return link ? [link] : [];
904
+ })
905
+ .slice(0, limit);
844
906
  backlinks.set(uri, dedupeStrs([...(backlinks.get(uri) ?? []), ...links]));
845
907
  links.forEach((link) => discoveredUris.add(link));
846
908
  }));
@@ -852,20 +914,25 @@ export class Hydrator {
852
914
  }
853
915
  const newUris = [...discoveredUris].filter((uri) => !seenRecordKeys.has(genericRecordKey({ uri })));
854
916
  let nested = {};
855
- if (newUris.length &&
856
- hydrationPass >= ExternalHydrator.MAX_EXTERNAL_HYDRATION_PASSES) {
917
+ if (newUris.length && hydrationPass >= MAX_EXTERNAL_HYDRATION_PASSES) {
857
918
  // Keep the partial state. Skipped URIs are not marked seen: they were
858
919
  // never fetched.
859
920
  hydrationMetrics.capped = true;
860
921
  hydrationLogger.warn({
861
922
  hydrationPass,
862
- maxPasses: ExternalHydrator.MAX_EXTERNAL_HYDRATION_PASSES,
923
+ maxPasses: MAX_EXTERNAL_HYDRATION_PASSES,
863
924
  skipped: newUris.length,
864
925
  }, 'external hydration pass limit reached, skipping dependencies');
865
926
  }
866
927
  else if (newUris.length) {
867
928
  try {
868
- nested = await this.hydrateEmbedExternalViewFromUris(newUris, ctx, seenRecordKeys, hydrationPass + 1, hydrationMetrics);
929
+ nested = await this.hydrateEmbedExternalViewFromUris(newUris, ctx, {
930
+ hydration,
931
+ seenRecordKeys,
932
+ hydrationPass: hydrationPass + 1,
933
+ hydrationMetrics,
934
+ publicationSubscriptions,
935
+ });
869
936
  }
870
937
  catch (err) {
871
938
  // Skip the whole batch; partial child state could miss moderation.
@@ -873,7 +940,12 @@ export class Hydrator {
873
940
  hydrationLogger.warn({ err, hydrationPass, skipped: newUris.length }, 'failed to hydrate external view dependencies');
874
941
  }
875
942
  }
876
- return mergeStates({ ctx, externalRecordBacklinks, externalRecordBacklinkCounts }, nested);
943
+ return mergeStates({
944
+ ctx,
945
+ externalRecordBacklinks,
946
+ externalRecordBacklinkCounts,
947
+ externalPublicationSubscriptions: publicationSubscriptions,
948
+ }, nested);
877
949
  }
878
950
  // app.bsky.feed.defs#threadViewPost
879
951
  // - post
@@ -1239,7 +1311,7 @@ export class Hydrator {
1239
1311
  postUris.add(parentUri);
1240
1312
  });
1241
1313
  const [postState, feedGenState, starterPackState] = await Promise.all([
1242
- this.hydratePosts([...postUris].map((uri) => ({ uri })), ctx, { posts }),
1314
+ this.hydratePosts([...postUris].map((uri) => ({ uri })), ctx, { posts }, { skipReplyBlocks: true }),
1243
1315
  this.hydrateFeedGens([...feedGenUris], ctx),
1244
1316
  this.hydrateStarterPacksBasic([...starterPackUris], ctx),
1245
1317
  ]);
@@ -1573,52 +1645,6 @@ const nestedRecordUris = (post) => {
1573
1645
  }
1574
1646
  return uris;
1575
1647
  };
1576
- /**
1577
- * Returns every strongRef the post embedded as `external.associatedRefs`,
1578
- * regardless of collection. Callers are responsible for filtering to NSIDs
1579
- * they care about.
1580
- */
1581
- const externalAssociatedRefs = (post) => {
1582
- const embed = post?.embed;
1583
- if (!embed)
1584
- return [];
1585
- if (isExternalEmbedType(embed)) {
1586
- return embed.external.associatedRefs ?? [];
1587
- }
1588
- if (isRecordWithMediaType(embed) && isExternalEmbedType(embed.media)) {
1589
- return embed.media.external.associatedRefs ?? [];
1590
- }
1591
- return [];
1592
- };
1593
- /**
1594
- * Collects standard.site refs across all post layers, deduped by `uri+cid` so
1595
- * the dataplane batch is minimal even if multiple posts in the layer reference
1596
- * the same exact version of an SS record. The same `${uri}@${cid}` keys are
1597
- * what `getSiteStandardRecordsByRef` uses on the resulting hydration maps,
1598
- * which lets `lookupAssociatedSiteStandardRecords` do an O(1) version-exact
1599
- * lookup at view time.
1600
- */
1601
- const siteStandardRefsFromPosts = (...postLayers) => {
1602
- const seen = new Set();
1603
- const out = [];
1604
- for (const layer of postLayers) {
1605
- for (const item of layer.values()) {
1606
- if (!item)
1607
- continue;
1608
- for (const ref of externalAssociatedRefs(item.record)) {
1609
- if (!new AtUri(ref.uri).collection.startsWith(SITE_STANDARD_NSID_PREFIX)) {
1610
- continue;
1611
- }
1612
- const key = `${ref.uri}@${ref.cid}`;
1613
- if (seen.has(key))
1614
- continue;
1615
- seen.add(key);
1616
- out.push({ uri: ref.uri, cid: ref.cid });
1617
- }
1618
- }
1619
- }
1620
- return out;
1621
- };
1622
1648
  const getListUrisFromThreadgates = (gates) => {
1623
1649
  const uris = [];
1624
1650
  for (const gate of gates.values()) {
@@ -1708,8 +1734,7 @@ export const mergeStates = (stateA, stateB) => {
1708
1734
  externalRecordsByRef: mergeMaps(stateA.externalRecordsByRef, stateB.externalRecordsByRef),
1709
1735
  externalRecordBacklinks: mergeMaps(stateA.externalRecordBacklinks, stateB.externalRecordBacklinks),
1710
1736
  externalRecordBacklinkCounts: mergeMaps(stateA.externalRecordBacklinkCounts, stateB.externalRecordBacklinkCounts),
1711
- siteStandardDocuments: mergeMaps(stateA.siteStandardDocuments, stateB.siteStandardDocuments),
1712
- siteStandardPublications: mergeMaps(stateA.siteStandardPublications, stateB.siteStandardPublications),
1737
+ externalPublicationSubscriptions: mergeMaps(stateA.externalPublicationSubscriptions, stateB.externalPublicationSubscriptions),
1713
1738
  };
1714
1739
  };
1715
1740
  export const mergeManyStates = (...states) => {
@@ -1722,71 +1747,6 @@ const actionTakedownLabels = (keys, hydrationMap, labels) => {
1722
1747
  }
1723
1748
  }
1724
1749
  };
1725
- /**
1726
- * The URI when an externally authored reference is a complete DID-based
1727
- * record URI in `collection`, with a record key and no fragment.
1728
- */
1729
- const recordUriOf = (value, collection) => {
1730
- const parsed = parseAtUriString(value);
1731
- return parsed.success &&
1732
- isDidString(parsed.value.authority) &&
1733
- parsed.value.collection === collection &&
1734
- parsed.value.rkey &&
1735
- !parsed.value.hash
1736
- ? value
1737
- : undefined;
1738
- };
1739
- /**
1740
- * Apply takedown labels to the site.standard hydration maps. Per-record
1741
- * takedowns null any entry whose subject URI is taken down; pair takedowns
1742
- * propagate that null across doc/publication pairs so we never render half
1743
- * of a moderated embed. Pairs are discovered via `doc.record.site`; orphan
1744
- * docs and orphan publications are subject only to the per-record sweep.
1745
- */
1746
- const actionSiteStandardTakedownLabels = (documents, publications, labels) => {
1747
- // Pairings have to be captured before nulling — the doc record carries
1748
- // the publication URI in its `site` field, and we lose it once we null.
1749
- const pairings = [];
1750
- if (documents.size > 0 && publications.size > 0) {
1751
- const pubKeysByUri = new Map();
1752
- for (const key of publications.keys()) {
1753
- const { uri } = parseGenericRecordKey(key);
1754
- const list = pubKeysByUri.get(uri);
1755
- if (list)
1756
- list.push(key);
1757
- else
1758
- pubKeysByUri.set(uri, [key]);
1759
- }
1760
- for (const [docKey, doc] of documents) {
1761
- const site = doc?.record.site;
1762
- if (!site || !site.startsWith('at://'))
1763
- continue;
1764
- for (const pubKey of pubKeysByUri.get(site) ?? []) {
1765
- pairings.push({ docKey, pubKey });
1766
- }
1767
- }
1768
- }
1769
- // Per-record takedowns: null any entry whose subject URI is taken down.
1770
- for (const key of documents.keys()) {
1771
- const { uri } = parseGenericRecordKey(key);
1772
- if (labels.get(uri)?.isTakendown)
1773
- documents.set(key, null);
1774
- }
1775
- for (const key of publications.keys()) {
1776
- const { uri } = parseGenericRecordKey(key);
1777
- if (labels.get(uri)?.isTakendown)
1778
- publications.set(key, null);
1779
- }
1780
- // Pair takedowns: if exactly one side of a pair was nulled above, mirror.
1781
- for (const { docKey, pubKey } of pairings) {
1782
- const doc = documents.get(docKey);
1783
- const pub = publications.get(pubKey);
1784
- if (doc === null && pub !== null)
1785
- publications.set(pubKey, null);
1786
- if (pub === null && doc !== null)
1787
- documents.set(docKey, null);
1788
- }
1789
- };
1790
1750
  const uriToRef = (uri) => {
1791
1751
  return { uri };
1792
1752
  };