@atproto/bsky 0.0.272 → 0.0.274

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 (255) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/api/app/bsky/actor/getSuggestions.d.ts.map +1 -1
  3. package/dist/api/app/bsky/actor/getSuggestions.js +7 -2
  4. package/dist/api/app/bsky/actor/getSuggestions.js.map +1 -1
  5. package/dist/api/app/bsky/actor/searchActors.d.ts.map +1 -1
  6. package/dist/api/app/bsky/actor/searchActors.js +13 -6
  7. package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
  8. package/dist/api/app/bsky/bookmark/getBookmarks.d.ts.map +1 -1
  9. package/dist/api/app/bsky/bookmark/getBookmarks.js +7 -2
  10. package/dist/api/app/bsky/bookmark/getBookmarks.js.map +1 -1
  11. package/dist/api/app/bsky/contact/getMatches.d.ts.map +1 -1
  12. package/dist/api/app/bsky/contact/getMatches.js +8 -2
  13. package/dist/api/app/bsky/contact/getMatches.js.map +1 -1
  14. package/dist/api/app/bsky/feed/getActorFeeds.d.ts.map +1 -1
  15. package/dist/api/app/bsky/feed/getActorFeeds.js +7 -2
  16. package/dist/api/app/bsky/feed/getActorFeeds.js.map +1 -1
  17. package/dist/api/app/bsky/feed/getActorLikes.d.ts.map +1 -1
  18. package/dist/api/app/bsky/feed/getActorLikes.js +7 -2
  19. package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
  20. package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
  21. package/dist/api/app/bsky/feed/getAuthorFeed.js +7 -2
  22. package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
  23. package/dist/api/app/bsky/feed/getFeed.d.ts +13 -0
  24. package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
  25. package/dist/api/app/bsky/feed/getFeed.js +41 -8
  26. package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
  27. package/dist/api/app/bsky/feed/getLikes.d.ts.map +1 -1
  28. package/dist/api/app/bsky/feed/getLikes.js +7 -2
  29. package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
  30. package/dist/api/app/bsky/feed/getListFeed.d.ts.map +1 -1
  31. package/dist/api/app/bsky/feed/getListFeed.js +7 -2
  32. package/dist/api/app/bsky/feed/getListFeed.js.map +1 -1
  33. package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
  34. package/dist/api/app/bsky/feed/getQuotes.js +7 -2
  35. package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
  36. package/dist/api/app/bsky/feed/getRepostedBy.d.ts.map +1 -1
  37. package/dist/api/app/bsky/feed/getRepostedBy.js +7 -2
  38. package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
  39. package/dist/api/app/bsky/feed/getSuggestedFeeds.d.ts.map +1 -1
  40. package/dist/api/app/bsky/feed/getSuggestedFeeds.js +20 -13
  41. package/dist/api/app/bsky/feed/getSuggestedFeeds.js.map +1 -1
  42. package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
  43. package/dist/api/app/bsky/feed/getTimeline.js +7 -2
  44. package/dist/api/app/bsky/feed/getTimeline.js.map +1 -1
  45. package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
  46. package/dist/api/app/bsky/feed/searchPosts.js +14 -7
  47. package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
  48. package/dist/api/app/bsky/feed/searchPostsV2.d.ts.map +1 -1
  49. package/dist/api/app/bsky/feed/searchPostsV2.js +17 -9
  50. package/dist/api/app/bsky/feed/searchPostsV2.js.map +1 -1
  51. package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -1
  52. package/dist/api/app/bsky/graph/getActorStarterPacks.js +7 -2
  53. package/dist/api/app/bsky/graph/getActorStarterPacks.js.map +1 -1
  54. package/dist/api/app/bsky/graph/getBlocks.d.ts.map +1 -1
  55. package/dist/api/app/bsky/graph/getBlocks.js +7 -2
  56. package/dist/api/app/bsky/graph/getBlocks.js.map +1 -1
  57. package/dist/api/app/bsky/graph/getFollowers.d.ts.map +1 -1
  58. package/dist/api/app/bsky/graph/getFollowers.js +12 -2
  59. package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
  60. package/dist/api/app/bsky/graph/getFollows.d.ts.map +1 -1
  61. package/dist/api/app/bsky/graph/getFollows.js +7 -2
  62. package/dist/api/app/bsky/graph/getFollows.js.map +1 -1
  63. package/dist/api/app/bsky/graph/getList.d.ts.map +1 -1
  64. package/dist/api/app/bsky/graph/getList.js +7 -2
  65. package/dist/api/app/bsky/graph/getList.js.map +1 -1
  66. package/dist/api/app/bsky/graph/getListBlocks.d.ts.map +1 -1
  67. package/dist/api/app/bsky/graph/getListBlocks.js +7 -2
  68. package/dist/api/app/bsky/graph/getListBlocks.js.map +1 -1
  69. package/dist/api/app/bsky/graph/getListMutes.d.ts.map +1 -1
  70. package/dist/api/app/bsky/graph/getListMutes.js +7 -2
  71. package/dist/api/app/bsky/graph/getListMutes.js.map +1 -1
  72. package/dist/api/app/bsky/graph/getLists.d.ts.map +1 -1
  73. package/dist/api/app/bsky/graph/getLists.js +9 -4
  74. package/dist/api/app/bsky/graph/getLists.js.map +1 -1
  75. package/dist/api/app/bsky/graph/getListsWithMembership.d.ts.map +1 -1
  76. package/dist/api/app/bsky/graph/getListsWithMembership.js +9 -4
  77. package/dist/api/app/bsky/graph/getListsWithMembership.js.map +1 -1
  78. package/dist/api/app/bsky/graph/getMutes.d.ts.map +1 -1
  79. package/dist/api/app/bsky/graph/getMutes.js +22 -30
  80. package/dist/api/app/bsky/graph/getMutes.js.map +1 -1
  81. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.d.ts.map +1 -1
  82. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js +7 -2
  83. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -1
  84. package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -1
  85. package/dist/api/app/bsky/graph/searchStarterPacks.js +13 -6
  86. package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -1
  87. package/dist/api/app/bsky/graph/searchStarterPacksV2.d.ts.map +1 -1
  88. package/dist/api/app/bsky/graph/searchStarterPacksV2.js +7 -2
  89. package/dist/api/app/bsky/graph/searchStarterPacksV2.js.map +1 -1
  90. package/dist/api/app/bsky/notification/listActivitySubscriptions.d.ts.map +1 -1
  91. package/dist/api/app/bsky/notification/listActivitySubscriptions.js +7 -2
  92. package/dist/api/app/bsky/notification/listActivitySubscriptions.js.map +1 -1
  93. package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
  94. package/dist/api/app/bsky/notification/listNotifications.js +17 -35
  95. package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
  96. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.d.ts.map +1 -1
  97. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js +49 -43
  98. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js.map +1 -1
  99. package/dist/api/app/bsky/unspecced/getTrendingTopics.d.ts.map +1 -1
  100. package/dist/api/app/bsky/unspecced/getTrendingTopics.js +3 -14
  101. package/dist/api/app/bsky/unspecced/getTrendingTopics.js.map +1 -1
  102. package/dist/api/app/bsky/unspecced/getTrends.d.ts.map +1 -1
  103. package/dist/api/app/bsky/unspecced/getTrends.js +3 -14
  104. package/dist/api/app/bsky/unspecced/getTrends.js.map +1 -1
  105. package/dist/api/blob-dispatcher.d.ts.map +1 -1
  106. package/dist/api/blob-dispatcher.js +6 -1
  107. package/dist/api/blob-dispatcher.js.map +1 -1
  108. package/dist/api/util.d.ts +15 -0
  109. package/dist/api/util.d.ts.map +1 -1
  110. package/dist/api/util.js +26 -0
  111. package/dist/api/util.js.map +1 -1
  112. package/dist/config.d.ts +2 -0
  113. package/dist/config.d.ts.map +1 -1
  114. package/dist/config.js +5 -0
  115. package/dist/config.js.map +1 -1
  116. package/dist/data-plane/server/db/pagination.d.ts +8 -0
  117. package/dist/data-plane/server/db/pagination.d.ts.map +1 -1
  118. package/dist/data-plane/server/db/pagination.js +20 -2
  119. package/dist/data-plane/server/db/pagination.js.map +1 -1
  120. package/dist/data-plane/server/op-thread.d.ts +7 -0
  121. package/dist/data-plane/server/op-thread.d.ts.map +1 -0
  122. package/dist/data-plane/server/op-thread.js +71 -0
  123. package/dist/data-plane/server/op-thread.js.map +1 -0
  124. package/dist/data-plane/server/routes/activity-subscription.js +3 -3
  125. package/dist/data-plane/server/routes/activity-subscription.js.map +1 -1
  126. package/dist/data-plane/server/routes/blocks.js +6 -6
  127. package/dist/data-plane/server/routes/blocks.js.map +1 -1
  128. package/dist/data-plane/server/routes/bookmarks.js +3 -3
  129. package/dist/data-plane/server/routes/bookmarks.js.map +1 -1
  130. package/dist/data-plane/server/routes/drafts.js +3 -3
  131. package/dist/data-plane/server/routes/drafts.js.map +1 -1
  132. package/dist/data-plane/server/routes/feed-gens.js +14 -12
  133. package/dist/data-plane/server/routes/feed-gens.js.map +1 -1
  134. package/dist/data-plane/server/routes/feeds.d.ts.map +1 -1
  135. package/dist/data-plane/server/routes/feeds.js +36 -15
  136. package/dist/data-plane/server/routes/feeds.js.map +1 -1
  137. package/dist/data-plane/server/routes/follows.js +6 -6
  138. package/dist/data-plane/server/routes/follows.js.map +1 -1
  139. package/dist/data-plane/server/routes/likes.js +6 -6
  140. package/dist/data-plane/server/routes/likes.js.map +1 -1
  141. package/dist/data-plane/server/routes/lists.js +6 -6
  142. package/dist/data-plane/server/routes/lists.js.map +1 -1
  143. package/dist/data-plane/server/routes/mutes.js +7 -7
  144. package/dist/data-plane/server/routes/mutes.js.map +1 -1
  145. package/dist/data-plane/server/routes/notifs.js +3 -3
  146. package/dist/data-plane/server/routes/notifs.js.map +1 -1
  147. package/dist/data-plane/server/routes/quotes.js +3 -3
  148. package/dist/data-plane/server/routes/quotes.js.map +1 -1
  149. package/dist/data-plane/server/routes/records.d.ts +3 -1
  150. package/dist/data-plane/server/routes/records.d.ts.map +1 -1
  151. package/dist/data-plane/server/routes/records.js +41 -4
  152. package/dist/data-plane/server/routes/records.js.map +1 -1
  153. package/dist/data-plane/server/routes/reposts.js +6 -6
  154. package/dist/data-plane/server/routes/reposts.js.map +1 -1
  155. package/dist/data-plane/server/routes/search.js +9 -9
  156. package/dist/data-plane/server/routes/search.js.map +1 -1
  157. package/dist/data-plane/server/routes/starter-packs.js +3 -3
  158. package/dist/data-plane/server/routes/starter-packs.js.map +1 -1
  159. package/dist/data-plane/server/routes/threads.d.ts.map +1 -1
  160. package/dist/data-plane/server/routes/threads.js +3 -74
  161. package/dist/data-plane/server/routes/threads.js.map +1 -1
  162. package/dist/feature-gates/gates.d.ts +2 -1
  163. package/dist/feature-gates/gates.d.ts.map +1 -1
  164. package/dist/feature-gates/gates.js +2 -1
  165. package/dist/feature-gates/gates.js.map +1 -1
  166. package/dist/hydration/feed.d.ts +3 -0
  167. package/dist/hydration/feed.d.ts.map +1 -1
  168. package/dist/hydration/feed.js +12 -0
  169. package/dist/hydration/feed.js.map +1 -1
  170. package/dist/hydration/hydrator.d.ts.map +1 -1
  171. package/dist/hydration/hydrator.js +4 -2
  172. package/dist/hydration/hydrator.js.map +1 -1
  173. package/dist/image/server.d.ts +1 -1
  174. package/dist/image/server.d.ts.map +1 -1
  175. package/dist/image/server.js +40 -22
  176. package/dist/image/server.js.map +1 -1
  177. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.d.ts +3 -0
  178. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.d.ts.map +1 -0
  179. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.d.ts +66 -0
  180. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.d.ts.map +1 -0
  181. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.js +26 -0
  182. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.js.map +1 -0
  183. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.js +6 -0
  184. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.js.map +1 -0
  185. package/dist/lexicons/app/bsky/actor.d.ts +1 -0
  186. package/dist/lexicons/app/bsky/actor.d.ts.map +1 -1
  187. package/dist/lexicons/app/bsky/actor.js +1 -0
  188. package/dist/lexicons/app/bsky/actor.js.map +1 -1
  189. package/dist/lexicons/app/bsky/authCreatePosts.defs.d.ts.map +1 -1
  190. package/dist/lexicons/app/bsky/authCreatePosts.defs.js +5 -0
  191. package/dist/lexicons/app/bsky/authCreatePosts.defs.js.map +1 -1
  192. package/dist/lexicons/app/bsky/authFullApp.defs.d.ts.map +1 -1
  193. package/dist/lexicons/app/bsky/authFullApp.defs.js +5 -0
  194. package/dist/lexicons/app/bsky/authFullApp.defs.js.map +1 -1
  195. package/dist/lexicons/app/bsky/embed/video.defs.d.ts +1 -1
  196. package/dist/lexicons/app/bsky/embed/video.defs.js +1 -1
  197. package/dist/lexicons/app/bsky/embed/video.defs.js.map +1 -1
  198. package/dist/lexicons/app/bsky/video/abortUpload.d.ts +3 -0
  199. package/dist/lexicons/app/bsky/video/abortUpload.d.ts.map +1 -0
  200. package/dist/lexicons/app/bsky/video/abortUpload.defs.d.ts +53 -0
  201. package/dist/lexicons/app/bsky/video/abortUpload.defs.d.ts.map +1 -0
  202. package/dist/lexicons/app/bsky/video/abortUpload.defs.js +26 -0
  203. package/dist/lexicons/app/bsky/video/abortUpload.defs.js.map +1 -0
  204. package/dist/lexicons/app/bsky/video/abortUpload.js +6 -0
  205. package/dist/lexicons/app/bsky/video/abortUpload.js.map +1 -0
  206. package/dist/lexicons/app/bsky/video/defs.defs.d.ts +1 -1
  207. package/dist/lexicons/app/bsky/video/defs.defs.d.ts.map +1 -1
  208. package/dist/lexicons/app/bsky/video/defs.defs.js.map +1 -1
  209. package/dist/lexicons/app/bsky/video/finishUpload.d.ts +3 -0
  210. package/dist/lexicons/app/bsky/video/finishUpload.d.ts.map +1 -0
  211. package/dist/lexicons/app/bsky/video/finishUpload.defs.d.ts +42 -0
  212. package/dist/lexicons/app/bsky/video/finishUpload.defs.d.ts.map +1 -0
  213. package/dist/lexicons/app/bsky/video/finishUpload.defs.js +30 -0
  214. package/dist/lexicons/app/bsky/video/finishUpload.defs.js.map +1 -0
  215. package/dist/lexicons/app/bsky/video/finishUpload.js +6 -0
  216. package/dist/lexicons/app/bsky/video/finishUpload.js.map +1 -0
  217. package/dist/lexicons/app/bsky/video/getUploadStatus.d.ts +3 -0
  218. package/dist/lexicons/app/bsky/video/getUploadStatus.d.ts.map +1 -0
  219. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.d.ts +73 -0
  220. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.d.ts.map +1 -0
  221. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.js +30 -0
  222. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.js.map +1 -0
  223. package/dist/lexicons/app/bsky/video/getUploadStatus.js +6 -0
  224. package/dist/lexicons/app/bsky/video/getUploadStatus.js.map +1 -0
  225. package/dist/lexicons/app/bsky/video/startUpload.d.ts +3 -0
  226. package/dist/lexicons/app/bsky/video/startUpload.d.ts.map +1 -0
  227. package/dist/lexicons/app/bsky/video/startUpload.defs.d.ts +63 -0
  228. package/dist/lexicons/app/bsky/video/startUpload.defs.d.ts.map +1 -0
  229. package/dist/lexicons/app/bsky/video/startUpload.defs.js +36 -0
  230. package/dist/lexicons/app/bsky/video/startUpload.defs.js.map +1 -0
  231. package/dist/lexicons/app/bsky/video/startUpload.js +6 -0
  232. package/dist/lexicons/app/bsky/video/startUpload.js.map +1 -0
  233. package/dist/lexicons/app/bsky/video/uploadPart.d.ts +3 -0
  234. package/dist/lexicons/app/bsky/video/uploadPart.d.ts.map +1 -0
  235. package/dist/lexicons/app/bsky/video/uploadPart.defs.d.ts +37 -0
  236. package/dist/lexicons/app/bsky/video/uploadPart.defs.d.ts.map +1 -0
  237. package/dist/lexicons/app/bsky/video/uploadPart.defs.js +31 -0
  238. package/dist/lexicons/app/bsky/video/uploadPart.defs.js.map +1 -0
  239. package/dist/lexicons/app/bsky/video/uploadPart.js +6 -0
  240. package/dist/lexicons/app/bsky/video/uploadPart.js.map +1 -0
  241. package/dist/lexicons/app/bsky/video.d.ts +5 -0
  242. package/dist/lexicons/app/bsky/video.d.ts.map +1 -1
  243. package/dist/lexicons/app/bsky/video.js +5 -0
  244. package/dist/lexicons/app/bsky/video.js.map +1 -1
  245. package/dist/proto/bsky_pb.d.ts +39 -0
  246. package/dist/proto/bsky_pb.d.ts.map +1 -1
  247. package/dist/proto/bsky_pb.js +55 -0
  248. package/dist/proto/bsky_pb.js.map +1 -1
  249. package/dist/views/index.d.ts.map +1 -1
  250. package/dist/views/index.js +2 -0
  251. package/dist/views/index.js.map +1 -1
  252. package/dist/views/types.d.ts +4 -1
  253. package/dist/views/types.d.ts.map +1 -1
  254. package/dist/views/types.js.map +1 -1
  255. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"searchStarterPacks.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAI5C,OAAO,EAEL,gBAAgB,GACjB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EAKL,cAAc,GACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAErE,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAEtE,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,kBAAkB,GAAG,cAAc,CACvC,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,CACb,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC5C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,gBAAgB;QACvC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACvC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAClD,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,MAAM;gBACN,QAAQ;gBACR,gBAAgB;gBAChB,gBAAgB;gBAChB,QAAQ,EAAE,GAAG,CAAC,kBAAkB,CAAC,KAAK,CACpC,GAAG,CAAC,kBAAkB,CAAC,2BAA2B,CAAC;oBACjD,MAAM;oBACN,GAAG;iBACJ,CAAC,CACH;aACF,CAAC,CAAA;YACF,MAAM,OAAO,GAAG,MAAM,kBAAkB,CACtC;gBACE,GAAG,MAAM;gBACT,UAAU;gBACV,YAAY,EAAE,uBAAuB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;aACpD,EACD,GAAG,CACJ,CAAA;YACD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC;aACvD,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,GAAG,KAAK,EACtB,MAAwC,EACrB,EAAE;IACrB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IAC9B,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,CAAA;IAEpB,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACrB,6CAA6C;QAC7C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,IAAI,CACrC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,0BAA0B,EAC7C;YACE,CAAC;YACD,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,SAAS;SAC9C,CACF,CAAA;QACD,OAAO;YACL,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC;YAC5C,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;SAChC,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC;QACjD,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAA;IACF,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAqB;QAC/B,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;KAChC,CAAA;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,KAAK,EACtB,MAAwC,EACrB,EAAE;IACrB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IAC9B,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,CAAA;IAEpB,uEAAuE;IACvE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS;SAC5B,oBAAoB,CAAC;QACpB,MAAM,EAAE;YACN,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,SAAS;YAC7C,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB;KACF,CAAC;SACD,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAA;IAC5B,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAkB,CAAC;QAC3D,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1C,CAAA;AACH,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAuC,EAAE,EAAE;IACjE,MAAM,KAAK,GACT,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CACxC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CACrD,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY,CAAA;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAA;IAClD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,KAAK,EACrB,MAAmD,EACnD,EAAE;IACF,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;IACxC,OAAO,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;AAChF,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,MAA+C,EAAE,EAAE;IACnE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;IAC3C,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;IACF,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CACnB,MAAsD,EACtD,EAAE;IACF,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;IAC3C,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CACrD,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAC3C,CAAA;IACD,OAAO;QACL,YAAY,EAAE,YAAY;QAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAA;AACH,CAAC,CAAA","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString, Client } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchStarterPacks = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.graph.searchStarterPacks, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await searchStarterPacks(\n {\n ...params,\n hydrateCtx,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchStarterPacksSkeleton,\n {\n q,\n cursor: params.cursor,\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n uris: res.starterPacks.map(({ uri }) => uri),\n cursor: parseString(res.cursor),\n }\n }\n\n const res = await ctx.dataplane.searchStarterPacks({\n term: q,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n uris: res.uris as AtUriString[],\n cursor: parseString(res.cursor),\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchStarterPacksV2({\n params: {\n query: q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n uris: res.starterPacks.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateStarterPacksBasic(skeleton.uris, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.uris = skeleton.uris.filter((uri) => {\n const creator = creatorFromUri(uri)\n return !ctx.views.viewerBlockExists(creator, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const starterPacks = mapDefined(skeleton.uris, (uri) =>\n ctx.views.starterPackBasic(uri, hydration),\n )\n return {\n starterPacks: starterPacks,\n cursor: skeleton.cursor,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.graph.searchStarterPacks.$Params & {\n hydrateCtx: HydrateCtx\n isV2Override: boolean\n}\n\ntype Skeleton = {\n uris: AtUriString[]\n cursor?: string\n}\n"]}
1
+ {"version":3,"file":"searchStarterPacks.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacks.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString, Client } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { fillPage, resHeaders, resolveSearchV2Override } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchStarterPacks = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.graph.searchStarterPacks, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const results = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: ({ cursor, limit }) =>\n searchStarterPacks(\n {\n ...params,\n cursor,\n limit,\n hydrateCtx,\n isV2Override: resolveSearchV2Override(req, ctx.cfg),\n },\n ctx,\n ),\n items: (r) => r.starterPacks,\n })\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeletonV1 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n if (ctx.searchClient) {\n // @NOTE cursors won't change on appview swap\n const res = await ctx.searchClient.call(\n app.bsky.unspecced.searchStarterPacksSkeleton,\n {\n q,\n cursor: params.cursor,\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n )\n return {\n uris: res.starterPacks.map(({ uri }) => uri),\n cursor: parseString(res.cursor),\n }\n }\n\n const res = await ctx.dataplane.searchStarterPacks({\n term: q,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n uris: res.uris as AtUriString[],\n cursor: parseString(res.cursor),\n }\n}\n\nconst skeletonV2 = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchStarterPacksV2({\n params: {\n query: q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n uris: res.starterPacks.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n }\n}\n\nconst skeleton = async (input: SkeletonFnInput<Context, Params>) => {\n const useV2 =\n input.params.hydrateCtx.features.checkGate(\n input.params.hydrateCtx.features.Gate.SearchV2Enable,\n ) || input.params.isV2Override\n const skeletonFn = useV2 ? skeletonV2 : skeletonV1\n return skeletonFn(input)\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateStarterPacksBasic(skeleton.uris, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.uris = skeleton.uris.filter((uri) => {\n const creator = creatorFromUri(uri)\n return !ctx.views.viewerBlockExists(creator, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const starterPacks = mapDefined(skeleton.uris, (uri) =>\n ctx.views.starterPackBasic(uri, hydration),\n )\n return {\n starterPacks: starterPacks,\n cursor: skeleton.cursor,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n searchClient?: Client\n}\n\ntype Params = app.bsky.graph.searchStarterPacks.$Params & {\n hydrateCtx: HydrateCtx\n isV2Override: boolean\n}\n\ntype Skeleton = {\n uris: AtUriString[]\n cursor?: string\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"searchStarterPacksV2.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacksV2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAmBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAkCvD"}
1
+ {"version":3,"file":"searchStarterPacksV2.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacksV2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAmBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAwCvD"}
@@ -4,7 +4,7 @@ import { parseString } from '../../../../hydration/util.js';
4
4
  import { app } from '../../../../lexicons/index.js';
5
5
  import { createPipeline, } from '../../../../pipeline.js';
6
6
  import { uriToDid as creatorFromUri } from '../../../../util/uris.js';
7
- import { resHeaders } from '../../../util.js';
7
+ import { fillPage, resHeaders } from '../../../util.js';
8
8
  export default function (server, ctx) {
9
9
  const searchStarterPacksV2 = createPipeline(skeleton, hydration, noBlocks, presentation);
10
10
  server.add(app.bsky.graph.searchStarterPacksV2, {
@@ -22,7 +22,12 @@ export default function (server, ctx) {
22
22
  req,
23
23
  })),
24
24
  });
25
- const results = await searchStarterPacksV2({ ...params, hydrateCtx }, ctx);
25
+ const results = await fillPage({
26
+ cursor: params.cursor,
27
+ limit: params.limit,
28
+ fetch: ({ cursor, limit }) => searchStarterPacksV2({ ...params, cursor, limit, hydrateCtx }, ctx),
29
+ items: (r) => r.starterPacks,
30
+ });
26
31
  return {
27
32
  encoding: 'application/json',
28
33
  body: results,
@@ -1 +1 @@
1
- {"version":3,"file":"searchStarterPacksV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacksV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchStarterPacksV2 = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.graph.searchStarterPacksV2, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n\n const results = await searchStarterPacksV2({ ...params, hydrateCtx }, ctx)\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchStarterPacksV2({\n params: {\n query: q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n uris: res.starterPacks.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal:\n res.pageInfo?.hitsTotal != null\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateStarterPacks(skeleton.uris, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.uris = skeleton.uris.filter((uri) => {\n const creator = creatorFromUri(uri)\n return !ctx.views.viewerBlockExists(creator, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const starterPacks = mapDefined(skeleton.uris, (uri) =>\n ctx.views.starterPack(uri, hydration),\n )\n return {\n starterPacks,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.graph.searchStarterPacksV2.$Params & {\n hydrateCtx: HydrateCtx\n}\n\ntype Skeleton = {\n uris: AtUriString[]\n cursor?: string\n hitsTotal?: number\n}\n"]}
1
+ {"version":3,"file":"searchStarterPacksV2.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/graph/searchStarterPacksV2.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/lex'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type DataPlaneClient,\n asInvalidRequest,\n} from '../../../../data-plane/index.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport { uriToDid as creatorFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { fillPage, resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const searchStarterPacksV2 = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.graph.searchStarterPacksV2, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const { viewer, includeTakedowns, skipViewerBlocks } =\n ctx.authVerifier.parseCreds(auth)\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n includeTakedowns,\n skipViewerBlocks,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n\n const results = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: ({ cursor, limit }) =>\n searchStarterPacksV2({ ...params, cursor, limit, hydrateCtx }, ctx),\n items: (r) => r.starterPacks,\n })\n return {\n encoding: 'application/json',\n body: results,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n inputs: SkeletonFnInput<Context, Params>,\n): Promise<Skeleton> => {\n const { ctx, params } = inputs\n const { q } = params\n\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n const res = await ctx.dataplane\n .searchStarterPacksV2({\n params: {\n query: q,\n viewer: params.hydrateCtx.viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n },\n })\n .catch(asInvalidRequest())\n return {\n uris: res.starterPacks.map(({ uri }) => uri as AtUriString),\n cursor: parseString(res.pageInfo?.cursor),\n hitsTotal:\n res.pageInfo?.hitsTotal != null\n ? Number(res.pageInfo.hitsTotal)\n : undefined,\n }\n}\n\nconst hydration = async (\n inputs: HydrationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, params, skeleton } = inputs\n return ctx.hydrator.hydrateStarterPacks(skeleton.uris, params.hydrateCtx)\n}\n\nconst noBlocks = (inputs: RulesFnInput<Context, Params, Skeleton>) => {\n const { ctx, skeleton, hydration } = inputs\n skeleton.uris = skeleton.uris.filter((uri) => {\n const creator = creatorFromUri(uri)\n return !ctx.views.viewerBlockExists(creator, hydration)\n })\n return skeleton\n}\n\nconst presentation = (\n inputs: PresentationFnInput<Context, Params, Skeleton>,\n) => {\n const { ctx, skeleton, hydration } = inputs\n const starterPacks = mapDefined(skeleton.uris, (uri) =>\n ctx.views.starterPack(uri, hydration),\n )\n return {\n starterPacks,\n cursor: skeleton.cursor,\n hitsTotal: skeleton.hitsTotal,\n }\n}\n\ntype Context = {\n dataplane: DataPlaneClient\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.graph.searchStarterPacksV2.$Params & {\n hydrateCtx: HydrateCtx\n}\n\ntype Skeleton = {\n uris: AtUriString[]\n cursor?: string\n hitsTotal?: number\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"listActivitySubscriptions.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAgBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA6BvD"}
1
+ {"version":3,"file":"listActivitySubscriptions.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAgBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAmCvD"}
@@ -1,7 +1,7 @@
1
1
  import { mapDefined } from '@atproto/common';
2
2
  import { app } from '../../../../lexicons/index.js';
3
3
  import { createPipeline, } from '../../../../pipeline.js';
4
- import { clearlyBadCursor, resHeaders } from '../../../util.js';
4
+ import { clearlyBadCursor, fillPage, resHeaders } from '../../../util.js';
5
5
  export default function (server, ctx) {
6
6
  const listActivitySubscriptions = createPipeline(skeleton, hydration, noBlocks, presentation);
7
7
  server.add(app.bsky.notification.listActivitySubscriptions, {
@@ -13,7 +13,12 @@ export default function (server, ctx) {
13
13
  labelers,
14
14
  viewer,
15
15
  });
16
- const result = await listActivitySubscriptions({ ...params, hydrateCtx }, ctx);
16
+ const result = await fillPage({
17
+ cursor: params.cursor,
18
+ limit: params.limit,
19
+ fetch: ({ cursor, limit }) => listActivitySubscriptions({ ...params, cursor, limit, hydrateCtx }, ctx),
20
+ items: (r) => r.subscriptions,
21
+ });
17
22
  return {
18
23
  encoding: 'application/json',
19
24
  body: result,
@@ -1 +1 @@
1
- {"version":3,"file":"listActivitySubscriptions.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtxWithViewer,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\nimport { clearlyBadCursor, resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const listActivitySubscriptions = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.notification.listActivitySubscriptions, {\n auth: ctx.authVerifier.standard,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n })\n\n const result = await listActivitySubscriptions(\n { ...params, hydrateCtx },\n ctx,\n )\n\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n const actorDid = params.hydrateCtx.viewer\n if (clearlyBadCursor(params.cursor)) {\n return { actorDid, dids: [] }\n }\n const { dids, cursor } =\n await ctx.hydrator.dataplane.getActivitySubscriptionDids({\n actorDid: params.hydrateCtx.viewer,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n actorDid,\n dids: dids as DidString[],\n cursor: cursor || undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const { dids } = skeleton\n const state = await ctx.hydrator.hydrateProfilesDetailed(\n dids,\n params.hydrateCtx,\n )\n return state\n}\n\nconst noBlocks = (input: RulesFnInput<Context, Params, SkeletonState>) => {\n const { skeleton, hydration, ctx } = input\n skeleton.dids = skeleton.dids.filter(\n (did) => !ctx.views.viewerBlockExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, hydration, skeleton } = input\n const { dids, cursor } = skeleton\n const subscriptions = mapDefined(dids, (did) => {\n return ctx.views.profile(did, hydration)\n })\n return { subscriptions, cursor }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.notification.listActivitySubscriptions.$Params & {\n hydrateCtx: HydrateCtxWithViewer\n}\n\ntype SkeletonState = {\n actorDid: DidString\n dids: DidString[]\n cursor?: string\n}\n"]}
1
+ {"version":3,"file":"listActivitySubscriptions.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtxWithViewer,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\nimport { clearlyBadCursor, fillPage, resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const listActivitySubscriptions = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.notification.listActivitySubscriptions, {\n auth: ctx.authVerifier.standard,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n })\n\n const result = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: ({ cursor, limit }) =>\n listActivitySubscriptions(\n { ...params, cursor, limit, hydrateCtx },\n ctx,\n ),\n items: (r) => r.subscriptions,\n })\n\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n const actorDid = params.hydrateCtx.viewer\n if (clearlyBadCursor(params.cursor)) {\n return { actorDid, dids: [] }\n }\n const { dids, cursor } =\n await ctx.hydrator.dataplane.getActivitySubscriptionDids({\n actorDid: params.hydrateCtx.viewer,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n actorDid,\n dids: dids as DidString[],\n cursor: cursor || undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const { dids } = skeleton\n const state = await ctx.hydrator.hydrateProfilesDetailed(\n dids,\n params.hydrateCtx,\n )\n return state\n}\n\nconst noBlocks = (input: RulesFnInput<Context, Params, SkeletonState>) => {\n const { skeleton, hydration, ctx } = input\n skeleton.dids = skeleton.dids.filter(\n (did) => !ctx.views.viewerBlockExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, hydration, skeleton } = input\n const { dids, cursor } = skeleton\n const subscriptions = mapDefined(dids, (did) => {\n return ctx.views.profile(did, hydration)\n })\n return { subscriptions, cursor }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.notification.listActivitySubscriptions.$Params & {\n hydrateCtx: HydrateCtxWithViewer\n}\n\ntype SkeletonState = {\n actorDid: DidString\n dids: DidString[]\n cursor?: string\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"listNotifications.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listNotifications.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAmBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqBvD;AAoDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,cACX,MAAM,GAAG,SAAS,WACpB,MAAM,KACd,MAMF,CAAA"}
1
+ {"version":3,"file":"listNotifications.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listNotifications.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAmBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA2BvD;AA0BD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,cACX,MAAM,GAAG,SAAS,WACpB,MAAM,KACd,MAMF,CAAA"}
@@ -4,7 +4,7 @@ import { app } from '../../../../lexicons/index.js';
4
4
  import { createPipeline, } from '../../../../pipeline.js';
5
5
  import { uriToDid as didFromUri } from '../../../../util/uris.js';
6
6
  import { isPostRecordType } from '../../../../views/types.js';
7
- import { resHeaders } from '../../../util.js';
7
+ import { fillPage, resHeaders } from '../../../util.js';
8
8
  export default function (server, ctx) {
9
9
  const listNotifications = createPipeline(skeleton, hydration, noBlockOrMutesOrNeedsFiltering, presentation);
10
10
  server.add(app.bsky.notification.listNotifications, {
@@ -13,7 +13,12 @@ export default function (server, ctx) {
13
13
  const viewer = auth.credentials.iss;
14
14
  const labelers = ctx.reqLabelers(req);
15
15
  const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer });
16
- const result = await listNotifications({ ...params, hydrateCtx }, ctx);
16
+ const result = await fillPage({
17
+ cursor: params.cursor,
18
+ limit: params.limit,
19
+ fetch: ({ cursor, limit }) => listNotifications({ ...params, cursor, limit, hydrateCtx }, ctx),
20
+ items: (r) => r.notifications,
21
+ });
17
22
  return {
18
23
  encoding: 'application/json',
19
24
  body: result,
@@ -24,40 +29,17 @@ export default function (server, ctx) {
24
29
  }
25
30
  const paginateNotifications = async (opts) => {
26
31
  const { ctx, priority, reasons, limit, viewer } = opts;
27
- // if not filtering, then just pass through the response from dataplane
28
- if (!reasons) {
29
- const res = await ctx.hydrator.dataplane.getNotifications({
30
- actorDid: viewer,
31
- priority,
32
- cursor: opts.cursor,
33
- limit,
34
- });
35
- return {
36
- notifications: res.notifications,
37
- cursor: res.cursor,
38
- };
39
- }
40
- let nextCursor = opts.cursor;
41
- let toReturn = [];
42
- const maxAttempts = 10;
43
- const attemptSize = Math.ceil(limit / 2);
44
- for (let i = 0; i < maxAttempts; i++) {
45
- const res = await ctx.hydrator.dataplane.getNotifications({
46
- actorDid: viewer,
47
- priority,
48
- cursor: nextCursor,
49
- limit,
50
- });
51
- const filtered = res.notifications.filter((notif) => reasons.includes(notif.reason));
52
- toReturn = [...toReturn, ...filtered];
53
- nextCursor = res.cursor ?? undefined;
54
- if (toReturn.length >= attemptSize || !nextCursor) {
55
- break;
56
- }
57
- }
32
+ const res = await ctx.hydrator.dataplane.getNotifications({
33
+ actorDid: viewer,
34
+ priority,
35
+ cursor: opts.cursor,
36
+ limit,
37
+ });
58
38
  return {
59
- notifications: toReturn,
60
- cursor: nextCursor,
39
+ notifications: reasons
40
+ ? res.notifications.filter((notif) => reasons.includes(notif.reason))
41
+ : res.notifications,
42
+ cursor: res.cursor,
61
43
  };
62
44
  };
63
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"listNotifications.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listNotifications.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString, DatetimeString, DidString } from '@atproto/syntax'\nimport { InvalidRequestError, type Server } from '@atproto/xrpc-server'\nimport type { ServerConfig } from '../../../../config.js'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtxWithViewer,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Notification } from '../../../../proto/bsky_pb.js'\nimport { uriToDid as didFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { isPostRecordType } from '../../../../views/types.js'\nimport { resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const listNotifications = createPipeline(\n skeleton,\n hydration,\n noBlockOrMutesOrNeedsFiltering,\n presentation,\n )\n server.add(app.bsky.notification.listNotifications, {\n auth: ctx.authVerifier.standard,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })\n const result = await listNotifications({ ...params, hydrateCtx }, ctx)\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst paginateNotifications = async (opts: {\n ctx: Context\n priority: boolean\n reasons?: string[]\n cursor?: string\n limit: number\n viewer: string\n}) => {\n const { ctx, priority, reasons, limit, viewer } = opts\n\n // if not filtering, then just pass through the response from dataplane\n if (!reasons) {\n const res = await ctx.hydrator.dataplane.getNotifications({\n actorDid: viewer,\n priority,\n cursor: opts.cursor,\n limit,\n })\n return {\n notifications: res.notifications,\n cursor: res.cursor,\n }\n }\n\n let nextCursor: string | undefined = opts.cursor\n let toReturn: Notification[] = []\n const maxAttempts = 10\n const attemptSize = Math.ceil(limit / 2)\n for (let i = 0; i < maxAttempts; i++) {\n const res = await ctx.hydrator.dataplane.getNotifications({\n actorDid: viewer,\n priority,\n cursor: nextCursor,\n limit,\n })\n const filtered = res.notifications.filter((notif) =>\n reasons.includes(notif.reason),\n )\n toReturn = [...toReturn, ...filtered]\n nextCursor = res.cursor ?? undefined\n if (toReturn.length >= attemptSize || !nextCursor) {\n break\n }\n }\n return {\n notifications: toReturn,\n cursor: nextCursor,\n }\n}\n\n/**\n * Applies a configurable delay to the datetime string of a cursor,\n * effectively allowing for a delay on listing the notifications.\n * This is useful to allow time for services to process notifications\n * before they are listed to the user.\n */\nexport const delayCursor = (\n cursorStr: string | undefined,\n delayMs: number,\n): string => {\n const nowMinusDelay = Date.now() - delayMs\n if (cursorStr === undefined) return new Date(nowMinusDelay).toISOString()\n const cursor = new Date(cursorStr).getTime()\n if (isNaN(cursor)) return cursorStr\n return new Date(Math.min(cursor, nowMinusDelay)).toISOString()\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n if (params.seenAt) {\n throw new InvalidRequestError('The seenAt parameter is unsupported')\n }\n\n const originalCursor = params.cursor\n const delayedCursor = delayCursor(\n originalCursor,\n ctx.cfg.notificationsDelayMs,\n )\n const viewer = params.hydrateCtx.viewer\n const priority = params.priority ?? (await getPriority(ctx, viewer))\n const [res, lastSeenRes] = await Promise.all([\n paginateNotifications({\n ctx,\n priority,\n reasons: params.reasons,\n cursor: delayedCursor,\n limit: params.limit,\n viewer,\n }),\n ctx.hydrator.dataplane.getNotificationSeen({\n actorDid: viewer,\n priority,\n }),\n ])\n // @NOTE for the first page of results if there's no last-seen time, consider top notification unread\n // rather than all notifications. bit of a hack to be more graceful when seen times are out of sync.\n let lastSeenDate = lastSeenRes.timestamp?.toDate()\n if (!lastSeenDate && !originalCursor) {\n lastSeenDate = res.notifications.at(0)?.timestamp?.toDate()\n }\n return {\n notifs: res.notifications,\n cursor: res.cursor || undefined,\n priority,\n lastSeenNotifs: lastSeenDate\n ? (lastSeenDate.toISOString() as DatetimeString)\n : undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { skeleton, params, ctx } = input\n return ctx.hydrator.hydrateNotifications(skeleton.notifs, params.hydrateCtx)\n}\n\nconst noBlockOrMutesOrNeedsFiltering = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { skeleton, hydration, ctx, params } = input\n skeleton.notifs = skeleton.notifs.filter((item) => {\n const uri = item.uri as AtUriString\n const did = didFromUri(uri)\n if (\n ctx.views.viewerBlockExists(did, hydration) ||\n ctx.views.viewerMuteExists(did, hydration)\n ) {\n return false\n }\n // Filter out hidden replies only if the viewer owns\n // the threadgate and they hid the reply.\n if (item.reason === 'reply') {\n const post = hydration.posts?.get(uri)\n if (post) {\n const rootPostUri = isPostRecordType(post.record)\n ? post.record.reply?.root.uri\n : undefined\n const isRootPostByViewer =\n rootPostUri && didFromUri(rootPostUri) === params.hydrateCtx?.viewer\n const isHiddenByThreadgate = isRootPostByViewer\n ? ctx.views.replyIsHiddenByThreadgate(uri, rootPostUri, hydration)\n : false\n if (isHiddenByThreadgate) {\n return false\n }\n }\n }\n // Filter out notifications from users that have thread hide tags and are from people they\n // are not following\n if (\n item.reason === 'reply' ||\n item.reason === 'quote' ||\n item.reason === 'mention'\n ) {\n const post = hydration.posts?.get(uri)\n if (post) {\n for (const [tag] of post.tags.entries()) {\n if (ctx.cfg.threadTagsHide.has(tag)) {\n if (!hydration.profileViewers?.get(did)?.following) {\n return false\n } else {\n break\n }\n }\n }\n }\n }\n // Filter out notifications from users that need review unless moots\n if (\n item.reason === 'reply' ||\n item.reason === 'quote' ||\n item.reason === 'mention' ||\n item.reason === 'like' ||\n item.reason === 'follow'\n ) {\n if (!ctx.views.viewerSeesNeedsReview({ did, uri }, hydration)) {\n return false\n }\n }\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n): app.bsky.notification.listNotifications.$OutputBody => {\n const { skeleton, hydration, ctx } = input\n const { notifs, lastSeenNotifs, cursor } = skeleton\n const notifications = mapDefined(notifs, (notif) =>\n ctx.views.notification(notif, lastSeenNotifs, hydration),\n )\n return {\n notifications,\n cursor,\n priority: skeleton.priority,\n seenAt: skeleton.lastSeenNotifs,\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = app.bsky.notification.listNotifications.$Params & {\n hydrateCtx: HydrateCtxWithViewer\n}\n\ntype SkeletonState = {\n notifs: Notification[]\n priority: boolean\n lastSeenNotifs?: DatetimeString\n cursor?: string\n}\n\nconst getPriority = async (ctx: Context, did: DidString) => {\n const actors = await ctx.hydrator.actor.getActors([did], {\n skipCacheForDids: [did],\n })\n return !!actors.get(did)?.priorityNotifications\n}\n"]}
1
+ {"version":3,"file":"listNotifications.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listNotifications.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString, DatetimeString, DidString } from '@atproto/syntax'\nimport { InvalidRequestError, type Server } from '@atproto/xrpc-server'\nimport type { ServerConfig } from '../../../../config.js'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtxWithViewer,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Notification } from '../../../../proto/bsky_pb.js'\nimport { uriToDid as didFromUri } from '../../../../util/uris.js'\nimport type { Views } from '../../../../views/index.js'\nimport { isPostRecordType } from '../../../../views/types.js'\nimport { fillPage, resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const listNotifications = createPipeline(\n skeleton,\n hydration,\n noBlockOrMutesOrNeedsFiltering,\n presentation,\n )\n server.add(app.bsky.notification.listNotifications, {\n auth: ctx.authVerifier.standard,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })\n const result = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: ({ cursor, limit }) =>\n listNotifications({ ...params, cursor, limit, hydrateCtx }, ctx),\n items: (r) => r.notifications,\n })\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst paginateNotifications = async (opts: {\n ctx: Context\n priority: boolean\n reasons?: string[]\n cursor?: string\n limit: number\n viewer: string\n}) => {\n const { ctx, priority, reasons, limit, viewer } = opts\n\n const res = await ctx.hydrator.dataplane.getNotifications({\n actorDid: viewer,\n priority,\n cursor: opts.cursor,\n limit,\n })\n return {\n notifications: reasons\n ? res.notifications.filter((notif) => reasons.includes(notif.reason))\n : res.notifications,\n cursor: res.cursor,\n }\n}\n\n/**\n * Applies a configurable delay to the datetime string of a cursor,\n * effectively allowing for a delay on listing the notifications.\n * This is useful to allow time for services to process notifications\n * before they are listed to the user.\n */\nexport const delayCursor = (\n cursorStr: string | undefined,\n delayMs: number,\n): string => {\n const nowMinusDelay = Date.now() - delayMs\n if (cursorStr === undefined) return new Date(nowMinusDelay).toISOString()\n const cursor = new Date(cursorStr).getTime()\n if (isNaN(cursor)) return cursorStr\n return new Date(Math.min(cursor, nowMinusDelay)).toISOString()\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n if (params.seenAt) {\n throw new InvalidRequestError('The seenAt parameter is unsupported')\n }\n\n const originalCursor = params.cursor\n const delayedCursor = delayCursor(\n originalCursor,\n ctx.cfg.notificationsDelayMs,\n )\n const viewer = params.hydrateCtx.viewer\n const priority = params.priority ?? (await getPriority(ctx, viewer))\n const [res, lastSeenRes] = await Promise.all([\n paginateNotifications({\n ctx,\n priority,\n reasons: params.reasons,\n cursor: delayedCursor,\n limit: params.limit,\n viewer,\n }),\n ctx.hydrator.dataplane.getNotificationSeen({\n actorDid: viewer,\n priority,\n }),\n ])\n // @NOTE for the first page of results if there's no last-seen time, consider top notification unread\n // rather than all notifications. bit of a hack to be more graceful when seen times are out of sync.\n let lastSeenDate = lastSeenRes.timestamp?.toDate()\n if (!lastSeenDate && !originalCursor) {\n lastSeenDate = res.notifications.at(0)?.timestamp?.toDate()\n }\n return {\n notifs: res.notifications,\n cursor: res.cursor || undefined,\n priority,\n lastSeenNotifs: lastSeenDate\n ? (lastSeenDate.toISOString() as DatetimeString)\n : undefined,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { skeleton, params, ctx } = input\n return ctx.hydrator.hydrateNotifications(skeleton.notifs, params.hydrateCtx)\n}\n\nconst noBlockOrMutesOrNeedsFiltering = (\n input: RulesFnInput<Context, Params, SkeletonState>,\n) => {\n const { skeleton, hydration, ctx, params } = input\n skeleton.notifs = skeleton.notifs.filter((item) => {\n const uri = item.uri as AtUriString\n const did = didFromUri(uri)\n if (\n ctx.views.viewerBlockExists(did, hydration) ||\n ctx.views.viewerMuteExists(did, hydration)\n ) {\n return false\n }\n // Filter out hidden replies only if the viewer owns\n // the threadgate and they hid the reply.\n if (item.reason === 'reply') {\n const post = hydration.posts?.get(uri)\n if (post) {\n const rootPostUri = isPostRecordType(post.record)\n ? post.record.reply?.root.uri\n : undefined\n const isRootPostByViewer =\n rootPostUri && didFromUri(rootPostUri) === params.hydrateCtx?.viewer\n const isHiddenByThreadgate = isRootPostByViewer\n ? ctx.views.replyIsHiddenByThreadgate(uri, rootPostUri, hydration)\n : false\n if (isHiddenByThreadgate) {\n return false\n }\n }\n }\n // Filter out notifications from users that have thread hide tags and are from people they\n // are not following\n if (\n item.reason === 'reply' ||\n item.reason === 'quote' ||\n item.reason === 'mention'\n ) {\n const post = hydration.posts?.get(uri)\n if (post) {\n for (const [tag] of post.tags.entries()) {\n if (ctx.cfg.threadTagsHide.has(tag)) {\n if (!hydration.profileViewers?.get(did)?.following) {\n return false\n } else {\n break\n }\n }\n }\n }\n }\n // Filter out notifications from users that need review unless moots\n if (\n item.reason === 'reply' ||\n item.reason === 'quote' ||\n item.reason === 'mention' ||\n item.reason === 'like' ||\n item.reason === 'follow'\n ) {\n if (!ctx.views.viewerSeesNeedsReview({ did, uri }, hydration)) {\n return false\n }\n }\n return true\n })\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n): app.bsky.notification.listNotifications.$OutputBody => {\n const { skeleton, hydration, ctx } = input\n const { notifs, lastSeenNotifs, cursor } = skeleton\n const notifications = mapDefined(notifs, (notif) =>\n ctx.views.notification(notif, lastSeenNotifs, hydration),\n )\n return {\n notifications,\n cursor,\n priority: skeleton.priority,\n seenAt: skeleton.lastSeenNotifs,\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n cfg: ServerConfig\n}\n\ntype Params = app.bsky.notification.listNotifications.$Params & {\n hydrateCtx: HydrateCtxWithViewer\n}\n\ntype SkeletonState = {\n notifs: Notification[]\n priority: boolean\n lastSeenNotifs?: DatetimeString\n cursor?: string\n}\n\nconst getPriority = async (ctx: Context, did: DidString) => {\n const actors = await ctx.hydrator.actor.getActors([did], {\n skipCacheForDids: [did],\n })\n return !!actors.get(did)?.priorityNotifications\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"getPopularFeedGenerators.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAaxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAgFvD"}
1
+ {"version":3,"file":"getPopularFeedGenerators.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAcxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqFvD"}
@@ -2,7 +2,7 @@ import { mapDefined } from '@atproto/common';
2
2
  import { asInvalidRequest } from '../../../../data-plane/index.js';
3
3
  import { parseString } from '../../../../hydration/util.js';
4
4
  import { app } from '../../../../lexicons/index.js';
5
- import { clearlyBadCursor, resHeaders, resolveSearchV2Override, } from '../../../util.js';
5
+ import { clearlyBadCursor, fillPage, resHeaders, resolveSearchV2Override, } from '../../../util.js';
6
6
  // THIS IS A TEMPORARY UNSPECCED ROUTE
7
7
  // @TODO currently mirrors getSuggestedFeeds and ignores the "query" param.
8
8
  // In the future may take into consideration popularity via likes w/ its own dataplane endpoint.
@@ -27,52 +27,58 @@ export default function (server, ctx) {
27
27
  body: { feeds: [] },
28
28
  };
29
29
  }
30
- let uris;
31
- let cursor;
32
30
  const isV2Override = resolveSearchV2Override(req, ctx.cfg);
33
31
  const query = params.query?.trim() ?? '';
34
- if (query) {
35
- const useV2 = features.checkGate(features.Gate.SearchV2Enable) || isV2Override;
36
- // Surface dataplane InvalidArgument errors as a 400 rather than a 500.
37
- if (useV2) {
38
- const res = await ctx.dataplane
39
- .searchFeedGeneratorsV2({
40
- params: {
41
- query,
42
- viewer: viewer ?? undefined,
43
- limit: params.limit,
44
- },
45
- })
46
- .catch(asInvalidRequest());
47
- uris = res.feedGenerators.map(({ uri }) => uri);
48
- }
49
- else {
50
- const res = await ctx.dataplane
51
- .searchFeedGenerators({
52
- query,
53
- limit: params.limit,
54
- })
55
- .catch(asInvalidRequest());
56
- uris = res.uris;
57
- }
58
- }
59
- else {
60
- const res = await ctx.dataplane.getSuggestedFeeds({
61
- actorDid: viewer ?? undefined,
62
- limit: params.limit,
63
- cursor: params.cursor,
64
- });
65
- uris = res.uris;
66
- cursor = parseString(res.cursor);
67
- }
68
- const hydration = await ctx.hydrator.hydrateFeedGens(uris, hydrateCtx);
69
- const feedViews = mapDefined(uris, (uri) => ctx.views.feedGenerator(uri, hydration));
32
+ const result = await fillPage({
33
+ cursor: params.cursor,
34
+ limit: params.limit,
35
+ fetch: async ({ cursor, limit }) => {
36
+ let uris;
37
+ let nextCursor;
38
+ if (query) {
39
+ const useV2 = features.checkGate(features.Gate.SearchV2Enable) || isV2Override;
40
+ // Surface dataplane InvalidArgument errors as a 400 rather than a 500.
41
+ if (useV2) {
42
+ const res = await ctx.dataplane
43
+ .searchFeedGeneratorsV2({
44
+ params: {
45
+ query,
46
+ viewer: viewer ?? undefined,
47
+ cursor,
48
+ limit,
49
+ },
50
+ })
51
+ .catch(asInvalidRequest());
52
+ uris = res.feedGenerators.map(({ uri }) => uri);
53
+ nextCursor = parseString(res.pageInfo?.cursor);
54
+ }
55
+ else {
56
+ const res = await ctx.dataplane
57
+ .searchFeedGenerators({ query, limit })
58
+ .catch(asInvalidRequest());
59
+ uris = res.uris;
60
+ }
61
+ }
62
+ else {
63
+ const res = await ctx.dataplane.getSuggestedFeeds({
64
+ actorDid: viewer ?? undefined,
65
+ cursor,
66
+ limit,
67
+ });
68
+ uris = res.uris;
69
+ nextCursor = parseString(res.cursor);
70
+ }
71
+ const hydration = await ctx.hydrator.hydrateFeedGens(uris, hydrateCtx);
72
+ return {
73
+ feeds: mapDefined(uris, (uri) => ctx.views.feedGenerator(uri, hydration)),
74
+ cursor: nextCursor,
75
+ };
76
+ },
77
+ items: (r) => r.feeds,
78
+ });
70
79
  return {
71
80
  encoding: 'application/json',
72
- body: {
73
- feeds: feedViews,
74
- cursor,
75
- },
81
+ body: result,
76
82
  headers: resHeaders({ labelers: hydrateCtx.labelers }),
77
83
  };
78
84
  },
@@ -1 +1 @@
1
- {"version":3,"file":"getPopularFeedGenerators.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport { asInvalidRequest } from '../../../../data-plane/index.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n clearlyBadCursor,\n resHeaders,\n resolveSearchV2Override,\n} from '../../../util.js'\n\n// THIS IS A TEMPORARY UNSPECCED ROUTE\n// @TODO currently mirrors getSuggestedFeeds and ignores the \"query\" param.\n// In the future may take into consideration popularity via likes w/ its own dataplane endpoint.\nexport default function (server: Server, ctx: AppContext) {\n server.add(app.bsky.unspecced.getPopularFeedGenerators, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const features = ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n )\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n features,\n })\n\n if (clearlyBadCursor(params.cursor)) {\n return {\n encoding: 'application/json',\n body: { feeds: [] },\n }\n }\n\n let uris: AtUriString[]\n let cursor: string | undefined\n\n const isV2Override = resolveSearchV2Override(req, ctx.cfg)\n\n const query = params.query?.trim() ?? ''\n if (query) {\n const useV2 =\n features.checkGate(features.Gate.SearchV2Enable) || isV2Override\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n if (useV2) {\n const res = await ctx.dataplane\n .searchFeedGeneratorsV2({\n params: {\n query,\n viewer: viewer ?? undefined,\n limit: params.limit,\n },\n })\n .catch(asInvalidRequest())\n uris = res.feedGenerators.map(({ uri }) => uri) as AtUriString[]\n } else {\n const res = await ctx.dataplane\n .searchFeedGenerators({\n query,\n limit: params.limit,\n })\n .catch(asInvalidRequest())\n uris = res.uris as AtUriString[]\n }\n } else {\n const res = await ctx.dataplane.getSuggestedFeeds({\n actorDid: viewer ?? undefined,\n limit: params.limit,\n cursor: params.cursor,\n })\n uris = res.uris as AtUriString[]\n cursor = parseString(res.cursor)\n }\n\n const hydration = await ctx.hydrator.hydrateFeedGens(uris, hydrateCtx)\n const feedViews = mapDefined(uris, (uri) =>\n ctx.views.feedGenerator(uri, hydration),\n )\n\n return {\n encoding: 'application/json',\n body: {\n feeds: feedViews,\n cursor,\n },\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n"]}
1
+ {"version":3,"file":"getPopularFeedGenerators.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getPopularFeedGenerators.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { AtUriString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport { asInvalidRequest } from '../../../../data-plane/index.js'\nimport { parseString } from '../../../../hydration/util.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n clearlyBadCursor,\n fillPage,\n resHeaders,\n resolveSearchV2Override,\n} from '../../../util.js'\n\n// THIS IS A TEMPORARY UNSPECCED ROUTE\n// @TODO currently mirrors getSuggestedFeeds and ignores the \"query\" param.\n// In the future may take into consideration popularity via likes w/ its own dataplane endpoint.\nexport default function (server: Server, ctx: AppContext) {\n server.add(app.bsky.unspecced.getPopularFeedGenerators, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const features = ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n )\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer,\n labelers,\n features,\n })\n\n if (clearlyBadCursor(params.cursor)) {\n return {\n encoding: 'application/json',\n body: { feeds: [] },\n }\n }\n\n const isV2Override = resolveSearchV2Override(req, ctx.cfg)\n\n const query = params.query?.trim() ?? ''\n const result = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: async ({ cursor, limit }) => {\n let uris: AtUriString[]\n let nextCursor: string | undefined\n if (query) {\n const useV2 =\n features.checkGate(features.Gate.SearchV2Enable) || isV2Override\n // Surface dataplane InvalidArgument errors as a 400 rather than a 500.\n if (useV2) {\n const res = await ctx.dataplane\n .searchFeedGeneratorsV2({\n params: {\n query,\n viewer: viewer ?? undefined,\n cursor,\n limit,\n },\n })\n .catch(asInvalidRequest())\n uris = res.feedGenerators.map(({ uri }) => uri) as AtUriString[]\n nextCursor = parseString(res.pageInfo?.cursor)\n } else {\n const res = await ctx.dataplane\n .searchFeedGenerators({ query, limit })\n .catch(asInvalidRequest())\n uris = res.uris as AtUriString[]\n }\n } else {\n const res = await ctx.dataplane.getSuggestedFeeds({\n actorDid: viewer ?? undefined,\n cursor,\n limit,\n })\n uris = res.uris as AtUriString[]\n nextCursor = parseString(res.cursor)\n }\n\n const hydration = await ctx.hydrator.hydrateFeedGens(uris, hydrateCtx)\n return {\n feeds: mapDefined(uris, (uri) =>\n ctx.views.feedGenerator(uri, hydration),\n ),\n cursor: nextCursor,\n }\n },\n items: (r) => r.feeds,\n })\n\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"getTrendingTopics.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAYxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAuCvD"}
1
+ {"version":3,"file":"getTrendingTopics.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAYxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA8BvD"}
@@ -9,14 +9,7 @@ export default function (server, ctx) {
9
9
  handler: async ({ auth, params, req }) => {
10
10
  const viewer = auth.credentials.iss;
11
11
  const labelers = ctx.reqLabelers(req);
12
- const hydrateCtx = await ctx.hydrator.createContext({
13
- labelers,
14
- viewer,
15
- features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
16
- viewer,
17
- req,
18
- })),
19
- });
12
+ const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer });
20
13
  const headers = noUndefinedVals({
21
14
  'accept-language': req.headers['accept-language'],
22
15
  });
@@ -34,15 +27,11 @@ export default function (server, ctx) {
34
27
  }
35
28
  const skeleton = async (input) => {
36
29
  const { params, ctx } = input;
37
- // Route treatment users to iris (trending-topics v2), everyone else stays on
38
- // the existing hot-topic service.
39
- const useIris = params.hydrateCtx.features.checkGate(params.hydrateCtx.features.Gate.TrendingTopicsV2);
40
- const topicsClient = (useIris && ctx.irisClient) || ctx.topicsClient;
41
- if (!topicsClient) {
30
+ if (!ctx.irisClient) {
42
31
  // Use 501 instead of 500 as these are not considered retry-able by clients
43
32
  throw new MethodNotImplementedError('Topics agent not available');
44
33
  }
45
- return topicsClient.call(app.bsky.unspecced.getTrendingTopics, {
34
+ return ctx.irisClient.call(app.bsky.unspecced.getTrendingTopics, {
46
35
  limit: params.limit,
47
36
  viewer: params.hydrateCtx.viewer ?? undefined,
48
37
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"getTrendingTopics.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,yBAAyB,EAAe,MAAM,sBAAsB,CAAA;AAG7E,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EAKL,cAAc,GACf,MAAM,yBAAyB,CAAA;AAGhC,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,iBAAiB,GAAG,cAAc,CACtC,QAAQ,EACR,SAAS,EACT,eAAe,EACf,YAAY,CACb,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAC/C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,gBAAgB;QACvC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAA;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,QAAQ;gBACR,MAAM;gBACN,QAAQ,EAAE,GAAG,CAAC,kBAAkB,CAAC,KAAK,CACpC,GAAG,CAAC,kBAAkB,CAAC,2BAA2B,CAAC;oBACjD,MAAM;oBACN,GAAG;iBACJ,CAAC,CACH;aACF,CAAC,CAAA;YACF,MAAM,OAAO,GAAG,eAAe,CAAC;gBAC9B,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAClD,CAAC,CAAA;YACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,GAAG,MAAM;gBACT,UAAU;gBACV,OAAO;aACR,EACD,GAAG,CACJ,CAAA;YACD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM;aACb,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,QAAQ,GAA+C,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3E,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;IAE7B,6EAA6E;IAC7E,kCAAkC;IAClC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAClD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CACjD,CAAA;IACD,MAAM,YAAY,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,YAAY,CAAA;IAEpE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,2EAA2E;QAC3E,MAAM,IAAI,yBAAyB,CAAC,4BAA4B,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,YAAY,CAAC,IAAI,CACtB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EACpC;QACE,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,SAAS;KAC9C,EACD;QACE,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAgD,KAAK,IAAI,EAAE;IACxE,OAAO,EAAE,CAAA;AACX,CAAC,CAAA;AAED,MAAM,eAAe,GAA4C,CAAC,KAAK,EAAE,EAAE;IACzE,OAAO,KAAK,CAAC,QAAQ,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,YAAY,GAKd,CAAC,KAAK,EAAE,EAAE;IACZ,OAAO,KAAK,CAAC,QAAQ,CAAA;AACvB,CAAC,CAAA","sourcesContent":["import { noUndefinedVals } from '@atproto/common'\nimport type { Client } from '@atproto/lex'\nimport { MethodNotImplementedError, type Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFn,\n type PresentationFn,\n type RulesFn,\n type SkeletonFn,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const getTrendingTopics = createPipeline(\n skeleton,\n hydration,\n noBlocksOrMutes,\n presentation,\n )\n server.add(app.bsky.unspecced.getTrendingTopics, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n })\n const result = await getTrendingTopics(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeleton: SkeletonFn<Context, Params, SkeletonState> = async (input) => {\n const { params, ctx } = input\n\n // Route treatment users to iris (trending-topics v2), everyone else stays on\n // the existing hot-topic service.\n const useIris = params.hydrateCtx.features.checkGate(\n params.hydrateCtx.features.Gate.TrendingTopicsV2,\n )\n const topicsClient = (useIris && ctx.irisClient) || ctx.topicsClient\n\n if (!topicsClient) {\n // Use 501 instead of 500 as these are not considered retry-able by clients\n throw new MethodNotImplementedError('Topics agent not available')\n }\n\n return topicsClient.call(\n app.bsky.unspecced.getTrendingTopics,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\nconst hydration: HydrationFn<Context, Params, SkeletonState> = async () => {\n return {}\n}\n\nconst noBlocksOrMutes: RulesFn<Context, Params, SkeletonState> = (input) => {\n return input.skeleton\n}\n\nconst presentation: PresentationFn<\n Context,\n Params,\n SkeletonState,\n SkeletonState\n> = (input) => {\n return input.skeleton\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n topicsClient: Client | undefined\n irisClient: Client | undefined\n}\n\ntype Params = Omit<app.bsky.unspecced.getTrendingTopics.$Params, 'viewer'> & {\n hydrateCtx: HydrateCtx\n headers: Record<string, string>\n}\n\ntype SkeletonState = app.bsky.unspecced.getTrendingTopics.$OutputBody\n"]}
1
+ {"version":3,"file":"getTrendingTopics.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,yBAAyB,EAAe,MAAM,sBAAsB,CAAA;AAG7E,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EAKL,cAAc,GACf,MAAM,yBAAyB,CAAA;AAGhC,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,iBAAiB,GAAG,cAAc,CACtC,QAAQ,EACR,SAAS,EACT,eAAe,EACf,YAAY,CACb,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAC/C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,gBAAgB;QACvC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAA;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YACzE,MAAM,OAAO,GAAG,eAAe,CAAC;gBAC9B,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAClD,CAAC,CAAA;YACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,GAAG,MAAM;gBACT,UAAU;gBACV,OAAO;aACR,EACD,GAAG,CACJ,CAAA;YACD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM;aACb,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,QAAQ,GAA+C,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3E,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;IAE7B,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QACpB,2EAA2E;QAC3E,MAAM,IAAI,yBAAyB,CAAC,4BAA4B,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CACxB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EACpC;QACE,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,SAAS;KAC9C,EACD;QACE,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAgD,KAAK,IAAI,EAAE;IACxE,OAAO,EAAE,CAAA;AACX,CAAC,CAAA;AAED,MAAM,eAAe,GAA4C,CAAC,KAAK,EAAE,EAAE;IACzE,OAAO,KAAK,CAAC,QAAQ,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,YAAY,GAKd,CAAC,KAAK,EAAE,EAAE;IACZ,OAAO,KAAK,CAAC,QAAQ,CAAA;AACvB,CAAC,CAAA","sourcesContent":["import { noUndefinedVals } from '@atproto/common'\nimport type { Client } from '@atproto/lex'\nimport { MethodNotImplementedError, type Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type { HydrateCtx, Hydrator } from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFn,\n type PresentationFn,\n type RulesFn,\n type SkeletonFn,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const getTrendingTopics = createPipeline(\n skeleton,\n hydration,\n noBlocksOrMutes,\n presentation,\n )\n server.add(app.bsky.unspecced.getTrendingTopics, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n })\n const result = await getTrendingTopics(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeleton: SkeletonFn<Context, Params, SkeletonState> = async (input) => {\n const { params, ctx } = input\n\n if (!ctx.irisClient) {\n // Use 501 instead of 500 as these are not considered retry-able by clients\n throw new MethodNotImplementedError('Topics agent not available')\n }\n\n return ctx.irisClient.call(\n app.bsky.unspecced.getTrendingTopics,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n}\n\nconst hydration: HydrationFn<Context, Params, SkeletonState> = async () => {\n return {}\n}\n\nconst noBlocksOrMutes: RulesFn<Context, Params, SkeletonState> = (input) => {\n return input.skeleton\n}\n\nconst presentation: PresentationFn<\n Context,\n Params,\n SkeletonState,\n SkeletonState\n> = (input) => {\n return input.skeleton\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n irisClient: Client | undefined\n}\n\ntype Params = Omit<app.bsky.unspecced.getTrendingTopics.$Params, 'viewer'> & {\n hydrateCtx: HydrateCtx\n headers: Record<string, string>\n}\n\ntype SkeletonState = app.bsky.unspecced.getTrendingTopics.$OutputBody\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"getTrends.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrends.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAgBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqCvD"}
1
+ {"version":3,"file":"getTrends.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrends.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAgBxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA4BvD"}
@@ -10,14 +10,7 @@ export default function (server, ctx) {
10
10
  handler: async ({ auth, params, req }) => {
11
11
  const viewer = auth.credentials.iss;
12
12
  const labelers = ctx.reqLabelers(req);
13
- const hydrateCtx = await ctx.hydrator.createContext({
14
- labelers,
15
- viewer,
16
- features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
17
- viewer,
18
- req,
19
- })),
20
- });
13
+ const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer });
21
14
  const headers = noUndefinedVals({
22
15
  'accept-language': req.headers['accept-language'],
23
16
  'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])
@@ -38,15 +31,11 @@ export default function (server, ctx) {
38
31
  }
39
32
  const skeleton = async (input) => {
40
33
  const { params, ctx } = input;
41
- // Route treatment users to iris (trending-topics v2), everyone else stays on
42
- // the existing hot-topic service.
43
- const useIris = params.hydrateCtx.features.checkGate(params.hydrateCtx.features.Gate.TrendingTopicsV2);
44
- const topicsClient = (useIris && ctx.irisClient) || ctx.topicsClient;
45
- if (!topicsClient) {
34
+ if (!ctx.irisClient) {
46
35
  // Use 501 instead of 500 as these are not considered retry-able by clients
47
36
  throw new MethodNotImplementedError('Topics agent not available');
48
37
  }
49
- const skeleton = await topicsClient.call(app.bsky.unspecced.getTrendsSkeleton, {
38
+ const skeleton = await ctx.irisClient.call(app.bsky.unspecced.getTrendsSkeleton, {
50
39
  limit: params.limit,
51
40
  viewer: params.hydrateCtx.viewer ?? undefined,
52
41
  }, {