@atproto/bsky 0.0.240 → 0.0.242

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 (297) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/api/age-assurance/const.d.ts +1 -1
  3. package/dist/api/age-assurance/index.d.ts.map +1 -1
  4. package/dist/api/age-assurance/kws/age-verified.d.ts +13 -13
  5. package/dist/api/age-assurance/kws/age-verified.d.ts.map +1 -1
  6. package/dist/api/age-assurance/kws/external-payload.d.ts +4 -4
  7. package/dist/api/age-assurance/redirects/kws-age-verified.d.ts.map +1 -1
  8. package/dist/api/age-assurance/webhooks/kws-age-verified.d.ts.map +1 -1
  9. package/dist/api/app/bsky/bookmark/util.d.ts.map +1 -1
  10. package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
  11. package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
  12. package/dist/api/app/bsky/feed/getListFeed.d.ts.map +1 -1
  13. package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
  14. package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
  15. package/dist/api/app/bsky/notification/util.d.ts.map +1 -1
  16. package/dist/api/external.d.ts.map +1 -1
  17. package/dist/api/health.d.ts.map +1 -1
  18. package/dist/api/index.d.ts.map +1 -1
  19. package/dist/api/index.js +3 -0
  20. package/dist/api/index.js.map +1 -1
  21. package/dist/api/internal/bsky/actor/getProfiles.d.ts +4 -0
  22. package/dist/api/internal/bsky/actor/getProfiles.d.ts.map +1 -0
  23. package/dist/api/internal/bsky/actor/getProfiles.js +39 -0
  24. package/dist/api/internal/bsky/actor/getProfiles.js.map +1 -0
  25. package/dist/api/kws/api.d.ts.map +1 -1
  26. package/dist/api/kws/index.d.ts.map +1 -1
  27. package/dist/api/kws/types.d.ts +6 -6
  28. package/dist/api/kws/util.d.ts +1 -1
  29. package/dist/api/kws/util.d.ts.map +1 -1
  30. package/dist/api/kws/webhook.d.ts.map +1 -1
  31. package/dist/api/sitemap.d.ts.map +1 -1
  32. package/dist/api/util.d.ts.map +1 -1
  33. package/dist/api/well-known.d.ts.map +1 -1
  34. package/dist/auth-verifier.d.ts +2 -2
  35. package/dist/auth-verifier.d.ts.map +1 -1
  36. package/dist/bsync.d.ts.map +1 -1
  37. package/dist/cache/read-through.d.ts.map +1 -1
  38. package/dist/cache/read-through.js.map +1 -1
  39. package/dist/config.d.ts +4 -4
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js.map +1 -1
  42. package/dist/context.d.ts.map +1 -1
  43. package/dist/context.js.map +1 -1
  44. package/dist/courier.d.ts.map +1 -1
  45. package/dist/data-plane/bsync/index.d.ts.map +1 -1
  46. package/dist/data-plane/bsync/index.js.map +1 -1
  47. package/dist/data-plane/client/hosts.d.ts.map +1 -1
  48. package/dist/data-plane/client/index.d.ts.map +1 -1
  49. package/dist/data-plane/client/util.d.ts.map +1 -1
  50. package/dist/data-plane/server/background.d.ts.map +1 -1
  51. package/dist/data-plane/server/db/db.d.ts.map +1 -1
  52. package/dist/data-plane/server/db/migrations/provider.d.ts.map +1 -1
  53. package/dist/data-plane/server/db/migrations/provider.js.map +1 -1
  54. package/dist/data-plane/server/db/pagination.d.ts +1 -1
  55. package/dist/data-plane/server/db/pagination.d.ts.map +1 -1
  56. package/dist/data-plane/server/db/pagination.js.map +1 -1
  57. package/dist/data-plane/server/db/util.d.ts.map +1 -1
  58. package/dist/data-plane/server/index.d.ts.map +1 -1
  59. package/dist/data-plane/server/index.js.map +1 -1
  60. package/dist/data-plane/server/indexing/index.d.ts +78 -78
  61. package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
  62. package/dist/data-plane/server/indexing/index.js.map +1 -1
  63. package/dist/data-plane/server/indexing/plugins/block.d.ts.map +1 -1
  64. package/dist/data-plane/server/indexing/plugins/chat-declaration.d.ts.map +1 -1
  65. package/dist/data-plane/server/indexing/plugins/feed-generator.d.ts.map +1 -1
  66. package/dist/data-plane/server/indexing/plugins/follow.d.ts.map +1 -1
  67. package/dist/data-plane/server/indexing/plugins/germ-declaration.d.ts.map +1 -1
  68. package/dist/data-plane/server/indexing/plugins/labeler.d.ts.map +1 -1
  69. package/dist/data-plane/server/indexing/plugins/like.d.ts.map +1 -1
  70. package/dist/data-plane/server/indexing/plugins/list-block.d.ts.map +1 -1
  71. package/dist/data-plane/server/indexing/plugins/list-item.d.ts.map +1 -1
  72. package/dist/data-plane/server/indexing/plugins/list.d.ts.map +1 -1
  73. package/dist/data-plane/server/indexing/plugins/notif-declaration.d.ts.map +1 -1
  74. package/dist/data-plane/server/indexing/plugins/post-gate.d.ts.map +1 -1
  75. package/dist/data-plane/server/indexing/plugins/post.d.ts.map +1 -1
  76. package/dist/data-plane/server/indexing/plugins/profile.d.ts.map +1 -1
  77. package/dist/data-plane/server/indexing/plugins/repost.d.ts.map +1 -1
  78. package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts.map +1 -1
  79. package/dist/data-plane/server/indexing/plugins/status.d.ts.map +1 -1
  80. package/dist/data-plane/server/indexing/plugins/thread-gate.d.ts.map +1 -1
  81. package/dist/data-plane/server/indexing/plugins/verification.d.ts.map +1 -1
  82. package/dist/data-plane/server/indexing/processor.d.ts.map +1 -1
  83. package/dist/data-plane/server/indexing/processor.js.map +1 -1
  84. package/dist/data-plane/server/routes/activity-subscription.d.ts.map +1 -1
  85. package/dist/data-plane/server/routes/blocks.d.ts.map +1 -1
  86. package/dist/data-plane/server/routes/bookmarks.d.ts.map +1 -1
  87. package/dist/data-plane/server/routes/drafts.d.ts.map +1 -1
  88. package/dist/data-plane/server/routes/feed-gens.d.ts.map +1 -1
  89. package/dist/data-plane/server/routes/feeds.d.ts.map +1 -1
  90. package/dist/data-plane/server/routes/follows.d.ts.map +1 -1
  91. package/dist/data-plane/server/routes/identity.d.ts.map +1 -1
  92. package/dist/data-plane/server/routes/index.d.ts.map +1 -1
  93. package/dist/data-plane/server/routes/interactions.d.ts.map +1 -1
  94. package/dist/data-plane/server/routes/labels.d.ts.map +1 -1
  95. package/dist/data-plane/server/routes/likes.d.ts.map +1 -1
  96. package/dist/data-plane/server/routes/lists.d.ts.map +1 -1
  97. package/dist/data-plane/server/routes/moderation.d.ts.map +1 -1
  98. package/dist/data-plane/server/routes/mutes.d.ts.map +1 -1
  99. package/dist/data-plane/server/routes/notifs.d.ts.map +1 -1
  100. package/dist/data-plane/server/routes/profile.d.ts.map +1 -1
  101. package/dist/data-plane/server/routes/quotes.d.ts.map +1 -1
  102. package/dist/data-plane/server/routes/records.d.ts.map +1 -1
  103. package/dist/data-plane/server/routes/relationships.d.ts.map +1 -1
  104. package/dist/data-plane/server/routes/reposts.d.ts.map +1 -1
  105. package/dist/data-plane/server/routes/search.d.ts.map +1 -1
  106. package/dist/data-plane/server/routes/site-standard.d.ts.map +1 -1
  107. package/dist/data-plane/server/routes/sitemap.d.ts.map +1 -1
  108. package/dist/data-plane/server/routes/starter-packs.d.ts.map +1 -1
  109. package/dist/data-plane/server/routes/suggestions.d.ts.map +1 -1
  110. package/dist/data-plane/server/routes/sync.d.ts.map +1 -1
  111. package/dist/data-plane/server/routes/threads.d.ts.map +1 -1
  112. package/dist/data-plane/server/subscription.d.ts.map +1 -1
  113. package/dist/data-plane/server/subscription.js.map +1 -1
  114. package/dist/data-plane/server/util.d.ts +7 -7
  115. package/dist/data-plane/server/util.d.ts.map +1 -1
  116. package/dist/etcd.d.ts.map +1 -1
  117. package/dist/etcd.js.map +1 -1
  118. package/dist/feature-gates/index.d.ts.map +1 -1
  119. package/dist/feature-gates/metrics.d.ts.map +1 -1
  120. package/dist/feature-gates/metrics.js.map +1 -1
  121. package/dist/hydration/actor.d.ts.map +1 -1
  122. package/dist/hydration/actor.js.map +1 -1
  123. package/dist/hydration/external.d.ts.map +1 -1
  124. package/dist/hydration/external.js.map +1 -1
  125. package/dist/hydration/feed.d.ts.map +1 -1
  126. package/dist/hydration/feed.js.map +1 -1
  127. package/dist/hydration/graph.d.ts.map +1 -1
  128. package/dist/hydration/graph.js.map +1 -1
  129. package/dist/hydration/hydrator.d.ts +4 -2
  130. package/dist/hydration/hydrator.d.ts.map +1 -1
  131. package/dist/hydration/hydrator.js +20 -18
  132. package/dist/hydration/hydrator.js.map +1 -1
  133. package/dist/hydration/label.d.ts.map +1 -1
  134. package/dist/hydration/label.js.map +1 -1
  135. package/dist/hydration/util.d.ts.map +1 -1
  136. package/dist/image/invalidator.d.ts.map +1 -1
  137. package/dist/image/invalidator.js.map +1 -1
  138. package/dist/image/logger.d.ts.map +1 -1
  139. package/dist/image/server.d.ts.map +1 -1
  140. package/dist/image/server.js.map +1 -1
  141. package/dist/image/sharp.d.ts +1 -1
  142. package/dist/image/uri.d.ts.map +1 -1
  143. package/dist/image/uri.js.map +1 -1
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/kws.d.ts.map +1 -1
  146. package/dist/kws.js.map +1 -1
  147. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +75 -155
  148. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
  149. package/dist/lexicons/app/bsky/actor/profile.defs.d.ts +100 -300
  150. package/dist/lexicons/app/bsky/actor/profile.defs.d.ts.map +1 -1
  151. package/dist/lexicons/app/bsky/actor/status.defs.d.ts +40 -40
  152. package/dist/lexicons/app/bsky/actor/status.defs.d.ts.map +1 -1
  153. package/dist/lexicons/app/bsky/draft/defs.defs.d.ts +4 -4
  154. package/dist/lexicons/app/bsky/draft/defs.defs.d.ts.map +1 -1
  155. package/dist/lexicons/app/bsky/embed/external.defs.d.ts +10 -10
  156. package/dist/lexicons/app/bsky/embed/gallery.defs.d.ts +10 -42
  157. package/dist/lexicons/app/bsky/embed/gallery.defs.d.ts.map +1 -1
  158. package/dist/lexicons/app/bsky/embed/images.defs.d.ts +10 -10
  159. package/dist/lexicons/app/bsky/embed/record.defs.d.ts +10 -10
  160. package/dist/lexicons/app/bsky/embed/recordWithMedia.defs.d.ts +10 -10
  161. package/dist/lexicons/app/bsky/embed/video.defs.d.ts +50 -162
  162. package/dist/lexicons/app/bsky/embed/video.defs.d.ts.map +1 -1
  163. package/dist/lexicons/app/bsky/feed/generator.defs.d.ts +80 -160
  164. package/dist/lexicons/app/bsky/feed/generator.defs.d.ts.map +1 -1
  165. package/dist/lexicons/app/bsky/feed/like.defs.d.ts +30 -30
  166. package/dist/lexicons/app/bsky/feed/like.defs.d.ts.map +1 -1
  167. package/dist/lexicons/app/bsky/feed/post.defs.d.ts +80 -200
  168. package/dist/lexicons/app/bsky/feed/post.defs.d.ts.map +1 -1
  169. package/dist/lexicons/app/bsky/feed/postgate.defs.d.ts +40 -80
  170. package/dist/lexicons/app/bsky/feed/postgate.defs.d.ts.map +1 -1
  171. package/dist/lexicons/app/bsky/feed/repost.defs.d.ts +30 -30
  172. package/dist/lexicons/app/bsky/feed/repost.defs.d.ts.map +1 -1
  173. package/dist/lexicons/app/bsky/feed/threadgate.defs.d.ts +30 -30
  174. package/dist/lexicons/app/bsky/feed/threadgate.defs.d.ts.map +1 -1
  175. package/dist/lexicons/app/bsky/graph/block.defs.d.ts +20 -20
  176. package/dist/lexicons/app/bsky/graph/block.defs.d.ts.map +1 -1
  177. package/dist/lexicons/app/bsky/graph/follow.defs.d.ts +30 -30
  178. package/dist/lexicons/app/bsky/graph/follow.defs.d.ts.map +1 -1
  179. package/dist/lexicons/app/bsky/graph/list.defs.d.ts +70 -70
  180. package/dist/lexicons/app/bsky/graph/list.defs.d.ts.map +1 -1
  181. package/dist/lexicons/app/bsky/graph/listblock.defs.d.ts +20 -20
  182. package/dist/lexicons/app/bsky/graph/listblock.defs.d.ts.map +1 -1
  183. package/dist/lexicons/app/bsky/graph/listitem.defs.d.ts +20 -20
  184. package/dist/lexicons/app/bsky/graph/listitem.defs.d.ts.map +1 -1
  185. package/dist/lexicons/app/bsky/graph/starterpack.defs.d.ts +50 -90
  186. package/dist/lexicons/app/bsky/graph/starterpack.defs.d.ts.map +1 -1
  187. package/dist/lexicons/app/bsky/graph/verification.defs.d.ts +30 -30
  188. package/dist/lexicons/app/bsky/graph/verification.defs.d.ts.map +1 -1
  189. package/dist/lexicons/app/bsky/labeler/service.defs.d.ts +60 -140
  190. package/dist/lexicons/app/bsky/labeler/service.defs.d.ts.map +1 -1
  191. package/dist/lexicons/app/bsky/notification/declaration.defs.d.ts +10 -10
  192. package/dist/lexicons/app/bsky/notification/declaration.defs.d.ts.map +1 -1
  193. package/dist/lexicons/app/bsky/richtext/facet.defs.d.ts +10 -10
  194. package/dist/lexicons/chat/bsky/actor/declaration.defs.d.ts +20 -20
  195. package/dist/lexicons/chat/bsky/actor/declaration.defs.d.ts.map +1 -1
  196. package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts +17 -0
  197. package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts.map +1 -1
  198. package/dist/lexicons/chat/bsky/convo/defs.defs.js +11 -0
  199. package/dist/lexicons/chat/bsky/convo/defs.defs.js.map +1 -1
  200. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.d.ts +3 -0
  201. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.d.ts.map +1 -0
  202. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.d.ts +23 -0
  203. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.d.ts.map +1 -0
  204. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.js +19 -0
  205. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.js.map +1 -0
  206. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.js +6 -0
  207. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.js.map +1 -0
  208. package/dist/lexicons/chat/bsky/convo/sendMessage.defs.d.ts +1 -1
  209. package/dist/lexicons/chat/bsky/convo/sendMessage.defs.d.ts.map +1 -1
  210. package/dist/lexicons/chat/bsky/convo/sendMessage.defs.js +1 -0
  211. package/dist/lexicons/chat/bsky/convo/sendMessage.defs.js.map +1 -1
  212. package/dist/lexicons/chat/bsky/convo/sendMessageBatch.defs.d.ts +1 -1
  213. package/dist/lexicons/chat/bsky/convo/sendMessageBatch.defs.d.ts.map +1 -1
  214. package/dist/lexicons/chat/bsky/convo/sendMessageBatch.defs.js +1 -0
  215. package/dist/lexicons/chat/bsky/convo/sendMessageBatch.defs.js.map +1 -1
  216. package/dist/lexicons/chat/bsky/convo.d.ts +1 -0
  217. package/dist/lexicons/chat/bsky/convo.d.ts.map +1 -1
  218. package/dist/lexicons/chat/bsky/convo.js +1 -0
  219. package/dist/lexicons/chat/bsky/convo.js.map +1 -1
  220. package/dist/lexicons/chat/bsky/embed/joinLink.defs.d.ts +10 -42
  221. package/dist/lexicons/chat/bsky/embed/joinLink.defs.d.ts.map +1 -1
  222. package/dist/lexicons/chat/bsky/group/createGroup.defs.d.ts +1 -1
  223. package/dist/lexicons/chat/bsky/group/createGroup.defs.js +1 -1
  224. package/dist/lexicons/chat/bsky/group/createGroup.defs.js.map +1 -1
  225. package/dist/lexicons/com/atproto/lexicon/schema.defs.d.ts +10 -10
  226. package/dist/lexicons/com/atproto/lexicon/schema.defs.d.ts.map +1 -1
  227. package/dist/lexicons/com/atproto/repo/strongRef.defs.d.ts +10 -10
  228. package/dist/lexicons/com/germnetwork/declaration.defs.d.ts +40 -120
  229. package/dist/lexicons/com/germnetwork/declaration.defs.d.ts.map +1 -1
  230. package/dist/lexicons/index.d.ts +1 -0
  231. package/dist/lexicons/index.d.ts.map +1 -1
  232. package/dist/lexicons/index.js +1 -0
  233. package/dist/lexicons/index.js.map +1 -1
  234. package/dist/lexicons/internal/bsky/actor/getProfiles.d.ts +3 -0
  235. package/dist/lexicons/internal/bsky/actor/getProfiles.d.ts.map +1 -0
  236. package/dist/lexicons/internal/bsky/actor/getProfiles.defs.d.ts +38 -0
  237. package/dist/lexicons/internal/bsky/actor/getProfiles.defs.d.ts.map +1 -0
  238. package/dist/lexicons/internal/bsky/actor/getProfiles.defs.js +26 -0
  239. package/dist/lexicons/internal/bsky/actor/getProfiles.defs.js.map +1 -0
  240. package/dist/lexicons/internal/bsky/actor/getProfiles.js +6 -0
  241. package/dist/lexicons/internal/bsky/actor/getProfiles.js.map +1 -0
  242. package/dist/lexicons/internal/bsky/actor.d.ts +2 -0
  243. package/dist/lexicons/internal/bsky/actor.d.ts.map +1 -0
  244. package/dist/lexicons/internal/bsky/actor.js +5 -0
  245. package/dist/lexicons/internal/bsky/actor.js.map +1 -0
  246. package/dist/lexicons/internal/bsky.d.ts +2 -0
  247. package/dist/lexicons/internal/bsky.d.ts.map +1 -0
  248. package/dist/lexicons/internal/bsky.js +5 -0
  249. package/dist/lexicons/internal/bsky.js.map +1 -0
  250. package/dist/lexicons/internal.d.ts +2 -0
  251. package/dist/lexicons/internal.d.ts.map +1 -0
  252. package/dist/lexicons/internal.js +5 -0
  253. package/dist/lexicons/internal.js.map +1 -0
  254. package/dist/lexicons/site/standard/document.defs.d.ts +140 -460
  255. package/dist/lexicons/site/standard/document.defs.d.ts.map +1 -1
  256. package/dist/lexicons/site/standard/graph/recommend.defs.d.ts +10 -10
  257. package/dist/lexicons/site/standard/graph/recommend.defs.d.ts.map +1 -1
  258. package/dist/lexicons/site/standard/graph/subscription.defs.d.ts +20 -60
  259. package/dist/lexicons/site/standard/graph/subscription.defs.d.ts.map +1 -1
  260. package/dist/lexicons/site/standard/publication.defs.d.ts +60 -220
  261. package/dist/lexicons/site/standard/publication.defs.d.ts.map +1 -1
  262. package/dist/lexicons/site/standard/theme/basic.defs.d.ts +10 -10
  263. package/dist/lexicons/site/standard/theme/basic.defs.d.ts.map +1 -1
  264. package/dist/lexicons/tools/ozone/moderation/queryStatuses.defs.d.ts +2 -2
  265. package/dist/lexicons/tools/ozone/set/querySets.defs.d.ts +2 -2
  266. package/dist/pipeline.d.ts.map +1 -1
  267. package/dist/proto/bsky_connect.d.ts.map +1 -1
  268. package/dist/proto/bsky_pb.d.ts.map +1 -1
  269. package/dist/proto/bsky_pb.js.map +1 -1
  270. package/dist/proto/bsync_connect.d.ts.map +1 -1
  271. package/dist/proto/bsync_pb.d.ts.map +1 -1
  272. package/dist/proto/bsync_pb.js.map +1 -1
  273. package/dist/proto/courier_connect.d.ts.map +1 -1
  274. package/dist/proto/courier_pb.d.ts.map +1 -1
  275. package/dist/proto/courier_pb.js.map +1 -1
  276. package/dist/proto/rolodex_connect.d.ts.map +1 -1
  277. package/dist/proto/rolodex_pb.d.ts.map +1 -1
  278. package/dist/proto/rolodex_pb.js.map +1 -1
  279. package/dist/redis.d.ts.map +1 -1
  280. package/dist/rolodex.d.ts.map +1 -1
  281. package/dist/stash.d.ts.map +1 -1
  282. package/dist/stash.js.map +1 -1
  283. package/dist/util/debug.d.ts.map +1 -1
  284. package/dist/util/standard-site.d.ts.map +1 -1
  285. package/dist/util.d.ts.map +1 -1
  286. package/dist/views/index.d.ts.map +1 -1
  287. package/dist/views/types.d.ts +1 -1
  288. package/dist/views/types.d.ts.map +1 -1
  289. package/dist/views/util.d.ts.map +1 -1
  290. package/dist/views/util.js.map +1 -1
  291. package/package.json +15 -16
  292. package/src/api/index.ts +3 -0
  293. package/src/api/internal/bsky/actor/getProfiles.ts +87 -0
  294. package/src/hydration/hydrator.ts +29 -28
  295. package/tests/data-plane/subscription.test.ts +16 -14
  296. package/tests/views/internal-actor.test.ts +129 -0
  297. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"label.js","sourceRoot":"","sources":["../../src/hydration/label.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,EAAE,MAAM,cAAc,CAAA;AAEvE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAG/C,OAAO,EACL,YAAY,EAGZ,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,WAAW,CAAA;AAWlB,MAAM,OAAO,MACX,SAAQ,YAAsC;IAG9C,MAAM,CAAC,GAAG,CAAC,KAAY;QACrB,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,CAAA;IACrC,CAAC;IACD,KAAK,CAAC,GAAW;QACf,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM;gBAAE,SAAQ;YACrB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,CAAA;gBACzD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAChD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,YAAY,CAAC,GAAc;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;QACzC,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,CAAA;QAClB,MAAM,MAAM,GAAY,EAAE,CAAA;QAC1B,KAAK,MAAM,KAAK,IAAI,EAAE,EAAE,CAAC;YACvB,IAAI,KAAK;gBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAiBD,MAAM,OAAO,aAAa;IACxB,YAAmB,SAA0B;QAA1B,cAAS,GAAT,SAAS,CAAiB;IAAG,CAAC;IAEjD,KAAK,CAAC,oBAAoB,CACxB,QAAqB,EACrB,QAAwB;QAExB,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAA;QAExB,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAA;QAEzD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACzC,QAAQ;YACR,OAAO,EAAE,QAAQ,CAAC,IAAI;SACvB,CAAC,CAAA;QAEF,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAChE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG;gBAAE,SAAQ;YACnC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,CAAA;YACnC,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG;oBACN,eAAe,EAAE,KAAK;oBACtB,WAAW,EAAE,KAAK;oBAClB,WAAW,EAAE,KAAK;oBAClB,MAAM,EAAE,IAAI,YAAY,EAAE;iBAC3B,CAAA;gBACD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YAC3B,CAAC;YAED,MAAM,uBAAuB,GAC3B,KAAK,CAAC,GAAG,KAAK,kBAAkB;gBAChC,CAAC,KAAK,CAAC,GAAG;gBACV,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAEhC,kHAAkH;YAClH,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBAC7B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA;YAC5C,CAAC;YAED,IACE,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;gBACnC,CAAC,KAAK,CAAC,GAAG;gBACV,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAC9B,CAAC;gBACD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;YAC1B,CAAC;YACD,IAAI,uBAAuB,EAAE,CAAC;gBAC5B,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;YAC1B,CAAC;YACD,IACE,KAAK,CAAC,GAAG,KAAK,mBAAmB;gBACjC,CAAC,KAAK,CAAC,GAAG;gBACV,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAC9B,CAAC;gBACD,KAAK,CAAC,eAAe,GAAG,IAAI,CAAA;YAC9B,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,IAAiB,EACjB,gBAAgB,GAAG,KAAK;QAExB,MAAM,GAAG,GAAa,IAAI,YAAY,EAAE,CAAA;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAA;QAE5B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;YACjD,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC;SAChC,CAAC,CAAA;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACnB,MAAM,MAAM,GAAG,WAAW,CACxB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAC7B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EACd,gBAAgB,CACjB,CAAA;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,CAAA;QAC9B,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,sBAAsB,CAC1B,IAAiB,EACjB,MAAiB;QAEjB,MAAM,GAAG,GAAwB,IAAI,YAAY,EAAE,CAAA;QACnD,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAA;QAE5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,0BAA0B,CAAC;YAC5D,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;SACzD,CAAC,CAAA;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACnB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE;gBACX,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACjC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,IAAiB,EACjB,MAAwB;QAExB,MAAM,GAAG,GAAgB,IAAI,YAAY,EAAE,CAAA;QAC3C,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAA;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC;YACvD,IAAI;YACJ,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;SAChD,CAAC,CAAA;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACnB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE;gBACX,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;aAC5B,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAED,SAAS,eAAe,CAAsB,GAAM;IAClD,OAAO,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,mBAAmB,GAAG,eAAe,CAAA;AAC3C,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;AACjD,MAAM,kBAAkB,GAAG,cAAc,CAAA","sourcesContent":["import { AtUriString, DidString, UriString, atUri } from '@atproto/lex'\nimport { DataPlaneClient } from '../data-plane/client/index.js'\nimport { app, com } from '../lexicons/index.js'\nimport { ParsedLabelers } from '../util.js'\nimport { Label, LabelerRecord } from '../views/types.js'\nimport {\n HydrationMap,\n Merges,\n RecordInfo,\n parseJsonBytes,\n parseRecord,\n parseString,\n} from './util.js'\n\nexport type { Label }\n\nexport type SubjectLabels = {\n isImpersonation: boolean\n isTakendown: boolean\n needsReview: boolean\n labels: HydrationMap<`${string}::${string}`, Label> // src + val -> label\n}\n\nexport class Labels\n extends HydrationMap<UriString, SubjectLabels>\n implements Merges\n{\n static key(label: Label): `${string}::${string}` {\n return `${label.src}::${label.val}`\n }\n merge(map: Labels): this {\n for (const [key, theirs] of map) {\n if (!theirs) continue\n const mine = this.get(key)\n if (mine) {\n mine.isTakendown = mine.isTakendown || theirs.isTakendown\n mine.labels = mine.labels.merge(theirs.labels)\n } else {\n this.set(key, theirs)\n }\n }\n return this\n }\n getBySubject(sub: UriString): Label[] {\n const it = this.get(sub)?.labels.values()\n if (!it) return []\n const labels: Label[] = []\n for (const label of it) {\n if (label) labels.push(label)\n }\n return labels\n }\n}\n\nexport type LabelerAgg = {\n likes: number\n}\n\nexport type LabelerAggs = HydrationMap<DidString, LabelerAgg>\n\nexport type Labeler = RecordInfo<LabelerRecord>\nexport type Labelers = HydrationMap<DidString, Labeler>\n\nexport type LabelerViewerState = {\n like?: AtUriString\n}\n\nexport type LabelerViewerStates = HydrationMap<DidString, LabelerViewerState>\n\nexport class LabelHydrator {\n constructor(public dataplane: DataPlaneClient) {}\n\n async getLabelsForSubjects(\n subjects: UriString[],\n labelers: ParsedLabelers,\n ): Promise<Labels> {\n const map = new Labels()\n\n if (!subjects.length || !labelers.dids.length) return map\n\n const res = await this.dataplane.getLabels({\n subjects,\n issuers: labelers.dids,\n })\n\n for (const cur of res.labels) {\n const parsed = parseJsonBytes(com.atproto.label.defs.label, cur)\n if (!parsed || parsed.neg) continue\n const { sig: _, ...label } = parsed\n let entry = map.get(label.uri)\n if (!entry) {\n entry = {\n isImpersonation: false,\n isTakendown: false,\n needsReview: false,\n labels: new HydrationMap(),\n }\n map.set(label.uri, entry)\n }\n\n const isActionableNeedsReview =\n label.val === NEEDS_REVIEW_LABEL &&\n !label.neg &&\n labelers.redact.has(label.src)\n\n // we action needs review labels on backend for now so don't send to client until client has proper logic for them\n if (!isActionableNeedsReview) {\n entry.labels.set(Labels.key(label), label)\n }\n\n if (\n TAKEDOWN_LABELS.includes(label.val) &&\n !label.neg &&\n labelers.redact.has(label.src)\n ) {\n entry.isTakendown = true\n }\n if (isActionableNeedsReview) {\n entry.needsReview = true\n }\n if (\n label.val === IMPERSONATION_LABEL &&\n !label.neg &&\n labelers.redact.has(label.src)\n ) {\n entry.isImpersonation = true\n }\n }\n\n return map\n }\n\n async getLabelers(\n dids: DidString[],\n includeTakedowns = false,\n ): Promise<Labelers> {\n const map: Labelers = new HydrationMap()\n if (!dids.length) return map\n\n const res = await this.dataplane.getLabelerRecords({\n uris: dids.map(labelerDidToUri),\n })\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n const record = parseRecord(\n app.bsky.labeler.service.main,\n res.records[i],\n includeTakedowns,\n )\n map.set(did, record ?? null)\n }\n\n return map\n }\n\n async getLabelerViewerStates(\n dids: DidString[],\n viewer: DidString,\n ): Promise<LabelerViewerStates> {\n const map: LabelerViewerStates = new HydrationMap()\n if (!dids.length) return map\n\n const likes = await this.dataplane.getLikesByActorAndSubjects({\n actorDid: viewer,\n refs: dids.map((did) => ({ uri: labelerDidToUri(did) })),\n })\n\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n map.set(did, {\n like: parseString(likes.uris[i]),\n })\n }\n\n return map\n }\n\n async getLabelerAggregates(\n dids: DidString[],\n viewer: DidString | null,\n ): Promise<LabelerAggs> {\n const map: LabelerAggs = new HydrationMap()\n if (!dids.length) return map\n\n const refs = dids.map((did) => ({ uri: labelerDidToUri(did) }))\n const counts = await this.dataplane.getInteractionCounts({\n refs,\n skipCacheForDids: viewer ? [viewer] : undefined,\n })\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n map.set(did, {\n likes: counts.likes[i] ?? 0,\n })\n }\n\n return map\n }\n}\n\nfunction labelerDidToUri<T extends DidString>(did: T) {\n return atUri(did, app.bsky.labeler.service)\n}\n\nconst IMPERSONATION_LABEL = 'impersonation'\nconst TAKEDOWN_LABELS = ['!takedown', '!suspend']\nconst NEEDS_REVIEW_LABEL = 'needs-review'\n"]}
1
+ {"version":3,"file":"label.js","sourceRoot":"","sources":["../../src/hydration/label.ts"],"names":[],"mappings":"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","sourcesContent":["import { AtUriString, DidString, UriString, atUri } from '@atproto/lex'\nimport { DataPlaneClient } from '../data-plane/client/index.js'\nimport { app, com } from '../lexicons/index.js'\nimport { ParsedLabelers } from '../util.js'\nimport { Label, LabelerRecord } from '../views/types.js'\nimport {\n HydrationMap,\n Merges,\n RecordInfo,\n parseJsonBytes,\n parseRecord,\n parseString,\n} from './util.js'\n\nexport type { Label }\n\nexport type SubjectLabels = {\n isImpersonation: boolean\n isTakendown: boolean\n needsReview: boolean\n labels: HydrationMap<`${string}::${string}`, Label> // src + val -> label\n}\n\nexport class Labels\n extends HydrationMap<UriString, SubjectLabels>\n implements Merges\n{\n static key(label: Label): `${string}::${string}` {\n return `${label.src}::${label.val}`\n }\n merge(map: Labels): this {\n for (const [key, theirs] of map) {\n if (!theirs) continue\n const mine = this.get(key)\n if (mine) {\n mine.isTakendown = mine.isTakendown || theirs.isTakendown\n mine.labels = mine.labels.merge(theirs.labels)\n } else {\n this.set(key, theirs)\n }\n }\n return this\n }\n getBySubject(sub: UriString): Label[] {\n const it = this.get(sub)?.labels.values()\n if (!it) return []\n const labels: Label[] = []\n for (const label of it) {\n if (label) labels.push(label)\n }\n return labels\n }\n}\n\nexport type LabelerAgg = {\n likes: number\n}\n\nexport type LabelerAggs = HydrationMap<DidString, LabelerAgg>\n\nexport type Labeler = RecordInfo<LabelerRecord>\nexport type Labelers = HydrationMap<DidString, Labeler>\n\nexport type LabelerViewerState = {\n like?: AtUriString\n}\n\nexport type LabelerViewerStates = HydrationMap<DidString, LabelerViewerState>\n\nexport class LabelHydrator {\n constructor(public dataplane: DataPlaneClient) {}\n\n async getLabelsForSubjects(\n subjects: UriString[],\n labelers: ParsedLabelers,\n ): Promise<Labels> {\n const map = new Labels()\n\n if (!subjects.length || !labelers.dids.length) return map\n\n const res = await this.dataplane.getLabels({\n subjects,\n issuers: labelers.dids,\n })\n\n for (const cur of res.labels) {\n const parsed = parseJsonBytes(com.atproto.label.defs.label, cur)\n if (!parsed || parsed.neg) continue\n const { sig: _, ...label } = parsed\n let entry = map.get(label.uri)\n if (!entry) {\n entry = {\n isImpersonation: false,\n isTakendown: false,\n needsReview: false,\n labels: new HydrationMap(),\n }\n map.set(label.uri, entry)\n }\n\n const isActionableNeedsReview =\n label.val === NEEDS_REVIEW_LABEL &&\n !label.neg &&\n labelers.redact.has(label.src)\n\n // we action needs review labels on backend for now so don't send to client until client has proper logic for them\n if (!isActionableNeedsReview) {\n entry.labels.set(Labels.key(label), label)\n }\n\n if (\n TAKEDOWN_LABELS.includes(label.val) &&\n !label.neg &&\n labelers.redact.has(label.src)\n ) {\n entry.isTakendown = true\n }\n if (isActionableNeedsReview) {\n entry.needsReview = true\n }\n if (\n label.val === IMPERSONATION_LABEL &&\n !label.neg &&\n labelers.redact.has(label.src)\n ) {\n entry.isImpersonation = true\n }\n }\n\n return map\n }\n\n async getLabelers(\n dids: DidString[],\n includeTakedowns = false,\n ): Promise<Labelers> {\n const map: Labelers = new HydrationMap()\n if (!dids.length) return map\n\n const res = await this.dataplane.getLabelerRecords({\n uris: dids.map(labelerDidToUri),\n })\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n const record = parseRecord(\n app.bsky.labeler.service.main,\n res.records[i],\n includeTakedowns,\n )\n map.set(did, record ?? null)\n }\n\n return map\n }\n\n async getLabelerViewerStates(\n dids: DidString[],\n viewer: DidString,\n ): Promise<LabelerViewerStates> {\n const map: LabelerViewerStates = new HydrationMap()\n if (!dids.length) return map\n\n const likes = await this.dataplane.getLikesByActorAndSubjects({\n actorDid: viewer,\n refs: dids.map((did) => ({ uri: labelerDidToUri(did) })),\n })\n\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n map.set(did, {\n like: parseString(likes.uris[i]),\n })\n }\n\n return map\n }\n\n async getLabelerAggregates(\n dids: DidString[],\n viewer: DidString | null,\n ): Promise<LabelerAggs> {\n const map: LabelerAggs = new HydrationMap()\n if (!dids.length) return map\n\n const refs = dids.map((did) => ({ uri: labelerDidToUri(did) }))\n const counts = await this.dataplane.getInteractionCounts({\n refs,\n skipCacheForDids: viewer ? [viewer] : undefined,\n })\n for (let i = 0; i < dids.length; i++) {\n const did = dids[i]\n map.set(did, {\n likes: counts.likes[i] ?? 0,\n })\n }\n\n return map\n }\n}\n\nfunction labelerDidToUri<T extends DidString>(did: T) {\n return atUri(did, app.bsky.labeler.service)\n}\n\nconst IMPERSONATION_LABEL = 'impersonation'\nconst TAKEDOWN_LABELS = ['!takedown', '!suspend']\nconst NEEDS_REVIEW_LABEL = 'needs-review'\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/hydration/util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/hydration/util.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"invalidator.d.ts","sourceRoot":"","sources":["../../src/image/invalidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAOvC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D;AAED,qBAAa,gCAAiC,YAAW,gBAAgB;IAC3D,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,SAAS;IAC9B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;CAmBnD"}
1
+ {"version":3,"file":"invalidator.d.ts","sourceRoot":"","sources":["../../src/image/invalidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAOvC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D;AAED,qBAAa,gCAAiC,YAAW,gBAAgB;IAC3D,OAAO,CAAC,KAAK;IAAzB,YAAoB,KAAK,EAAE,SAAS,EAAI;IAClC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,iBAkBjD;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"invalidator.js","sourceRoot":"","sources":["../../src/image/invalidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAU1C,MAAM,OAAO,gCAAgC;IAC3C,YAAoB,KAAgB;QAAhB,UAAK,GAAL,KAAK,CAAW;IAAG,CAAC;IACxC,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,KAAe;QAChD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrC,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;YACpD,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YAChD,MAAM,QAAQ,GAAG;gBACf,OAAO,CAAC,GAAG;gBACX,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACtB,OAAO,CAAC,MAAM;aACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACZ,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClC,CAAC,CAAC,CACH,CAAA;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAC5B,CAAC,MAAM,EAAmC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAC1E,CAAA;QACD,IAAI,SAAS;YAAE,MAAM,SAAS,CAAC,MAAM,CAAA;IACvC,CAAC;CACF","sourcesContent":["import { BlobCache } from './server.js'\nimport { ImageUriBuilder } from './uri.js'\n\n// Invalidation is a general interface for propagating an image blob\n// takedown through any caches where a representation of it may be stored.\n// @NOTE this does not remove the blob from storage: just invalidates it from caches.\n// @NOTE keep in sync with same interface in aws/src/cloudfront.ts\nexport interface ImageInvalidator {\n invalidate(subject: string, paths: string[]): Promise<void>\n}\n\nexport class ImageProcessingServerInvalidator implements ImageInvalidator {\n constructor(private cache: BlobCache) {}\n async invalidate(_subject: string, paths: string[]) {\n const results = await Promise.allSettled(\n paths.map(async (path) => {\n const [, signature] = path.split('/')\n if (!signature) throw new Error('Missing signature')\n const options = ImageUriBuilder.getOptions(path)\n const cacheKey = [\n options.did,\n options.cid.toString(),\n options.preset,\n ].join('::')\n await this.cache.clear(cacheKey)\n }),\n )\n const rejection = results.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejection) throw rejection.reason\n }\n}\n"]}
1
+ {"version":3,"file":"invalidator.js","sourceRoot":"","sources":["../../src/image/invalidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAU1C,MAAM,OAAO,gCAAgC;IAC3C,YAAoB,KAAgB;qBAAhB,KAAK;IAAc,CAAC;IACxC,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,KAAe;QAChD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrC,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;YACpD,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YAChD,MAAM,QAAQ,GAAG;gBACf,OAAO,CAAC,GAAG;gBACX,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACtB,OAAO,CAAC,MAAM;aACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACZ,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClC,CAAC,CAAC,CACH,CAAA;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAC5B,CAAC,MAAM,EAAmC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAC1E,CAAA;QACD,IAAI,SAAS;YAAE,MAAM,SAAS,CAAC,MAAM,CAAA;IACvC,CAAC;CACF","sourcesContent":["import { BlobCache } from './server.js'\nimport { ImageUriBuilder } from './uri.js'\n\n// Invalidation is a general interface for propagating an image blob\n// takedown through any caches where a representation of it may be stored.\n// @NOTE this does not remove the blob from storage: just invalidates it from caches.\n// @NOTE keep in sync with same interface in aws/src/cloudfront.ts\nexport interface ImageInvalidator {\n invalidate(subject: string, paths: string[]): Promise<void>\n}\n\nexport class ImageProcessingServerInvalidator implements ImageInvalidator {\n constructor(private cache: BlobCache) {}\n async invalidate(_subject: string, paths: string[]) {\n const results = await Promise.allSettled(\n paths.map(async (path) => {\n const [, signature] = path.split('/')\n if (!signature) throw new Error('Missing signature')\n const options = ImageUriBuilder.getOptions(path)\n const cacheKey = [\n options.did,\n options.cid.toString(),\n options.preset,\n ].join('::')\n await this.cache.clear(cacheKey)\n }),\n )\n const rejection = results.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejection) throw rejection.reason\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/image/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CACvB,CAAA;AAE/B,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/image/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CACvB,CAAA;eAEhB,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/image/server.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAA;AAI5B,OAAO,EAAU,QAAQ,EAAE,MAAM,aAAa,CAAA;AAY9C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAkB,MAAM,iBAAiB,CAAA;AAM5D,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,UAAU,EACf,EAAE,MAAY,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACzC,UAAU,CA0HZ;AAsBD,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,EAAE,MAAM,CAAA;gBACH,QAAQ,CAAC,EAAE,MAAM;IAavB,GAAG,CAAC,MAAM,EAAE,MAAM;;;IAgBlB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ;IAWpC,KAAK,CAAC,MAAM,EAAE,MAAM;IAKpB,QAAQ;CAGf"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/image/server.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAA;AAI5B,OAAO,EAAU,QAAQ,EAAE,MAAM,aAAa,CAAA;AAY9C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAkB,MAAM,iBAAiB,CAAA;AAM5D,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,UAAU,EACf,EAAE,MAAY,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACzC,UAAU,CA0HZ;AAsBD,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,QAAQ,CAAC,EAAE,MAAM,EAW5B;IAEK,GAAG,CAAC,MAAM,EAAE,MAAM;;OAcvB;IAEK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,iBASzC;IAEK,KAAK,CAAC,MAAM,EAAE,MAAM,iBAGzB;IAEK,QAAQ,kBAEb;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/image/server.ts"],"names":[],"mappings":"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","sourcesContent":["import fsSync from 'node:fs'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Duplex, Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport createError, { isHttpError } from 'http-errors'\nimport {\n VerifyCidError,\n VerifyCidTransform,\n cloneStream,\n createDecoders,\n isErrnoException,\n} from '@atproto/common'\nimport { BlobNotFoundError } from '@atproto/repo'\nimport { StreamBlobOptions, streamBlob } from '../api/blob-resolver.js'\nimport { AppContext } from '../context.js'\nimport { Middleware, responseSignal } from '../util/http.js'\nimport log from './logger.js'\nimport { createImageProcessor, createImageUpscaler } from './sharp.js'\nimport { BadPathError, ImageUriBuilder } from './uri.js'\nimport { Options, SharpInfo, formatsToMimes } from './util.js'\n\nexport function createMiddleware(\n ctx: AppContext,\n { prefix = '/' }: { prefix?: string } = {},\n): Middleware {\n if (!prefix.startsWith('/') || !prefix.endsWith('/')) {\n throw new TypeError('Prefix must start and end with a slash')\n }\n\n // If there is a CDN, we don't need to serve images\n if (ctx.cfg.cdnUrl) {\n return (req, res, next) => next()\n }\n\n const cache = new BlobDiskCache(ctx.cfg.blobCacheLocation)\n\n return async (req, res, next) => {\n if (res.destroyed) return\n if (req.method !== 'GET' && req.method !== 'HEAD') return next()\n if (!req.url?.startsWith(prefix)) return next()\n const { 0: path, 1: _search } = req.url.slice(prefix.length - 1).split('?')\n if (!path.startsWith('/') || path === '/') return next()\n\n try {\n const options = ImageUriBuilder.getOptions(path)\n\n const cacheKey = [options.did, options.cid, options.preset].join('::')\n\n // Cached flow\n\n try {\n const cachedImage = await cache.get(cacheKey)\n res.statusCode = 200\n res.setHeader('x-cache', 'hit')\n res.setHeader('content-type', getMime(options.format))\n res.setHeader('cache-control', `public, max-age=31536000`) // 1 year\n res.setHeader('content-length', cachedImage.size)\n await pipeline(cachedImage, res)\n return\n } catch (err) {\n if (!(err instanceof BlobNotFoundError)) {\n log.error({ cacheKey, err }, 'failed to serve cached image')\n }\n\n if (res.headersSent || res.destroyed) {\n res.destroy()\n return // nothing we can do...\n } else {\n // Ignore and move on to non-cached flow.\n res.removeHeader('x-cache')\n res.removeHeader('content-type')\n res.removeHeader('cache-control')\n res.removeHeader('content-length')\n }\n }\n\n // Non-cached flow\n\n const streamOptions: StreamBlobOptions = {\n did: options.did,\n cid: options.cid,\n signal: responseSignal(res),\n }\n\n await streamBlob(ctx, streamOptions, (upstream, { did, cid, url }) => {\n // Definitely not an image ? Let's fail right away.\n if (isImageMime(upstream.headers['content-type']) === false) {\n throw createError(400, 'Not an image')\n }\n\n // Let's transform (decompress, verify CID, upscale), process and respond\n\n const transforms: Duplex[] = [\n ...createDecoders(upstream.headers['content-encoding']),\n new VerifyCidTransform(cid),\n createImageUpscaler(options),\n ]\n const processor = createImageProcessor(options)\n\n // Cache in the background\n cache\n .put(cacheKey, cloneStream(processor))\n .catch((err) => log.error({ err }, 'failed to cache image'))\n\n res.statusCode = 200\n res.setHeader('cache-control', `public, max-age=31536000`) // 1 year\n res.setHeader('x-cache', 'miss')\n processor.once('info', ({ size, format }: SharpInfo) => {\n const type = formatsToMimes.get(format) || 'application/octet-stream'\n\n // @NOTE sharp does emit this in time to be set as a header\n res.setHeader('content-length', size)\n res.setHeader('content-type', type)\n })\n\n const streams = [...transforms, processor, res]\n void pipeline(streams).catch((err: unknown) => {\n log.warn(\n { err, did, cid: cid.toString(), pds: url.origin },\n 'blob resolution failed during transmission',\n )\n })\n\n return streams[0]!\n })\n } catch (err) {\n if (res.headersSent || res.destroyed) {\n res.destroy()\n } else {\n res.removeHeader('content-type')\n res.removeHeader('content-length')\n res.removeHeader('cache-control')\n res.removeHeader('x-cache')\n\n if (err instanceof BadPathError) {\n next(createError(400, err))\n } else if (err instanceof VerifyCidError) {\n next(createError(404, 'Blob not found', err))\n } else if (isHttpError(err)) {\n next(err)\n } else {\n next(createError(502, 'Upstream Error', { cause: err }))\n }\n }\n }\n }\n}\n\nfunction isImageMime(\n contentType: string | string[] | undefined,\n): undefined | boolean {\n if (contentType == null || contentType === 'application/octet-stream') {\n return undefined // maybe\n }\n if (Array.isArray(contentType)) {\n if (contentType.length === 0) return undefined // should never happen\n if (contentType.length === 1) return isImageMime(contentType[0])\n return contentType.every(isImageMime) // Should we throw a 502 here?\n }\n return contentType.startsWith('image/')\n}\n\nfunction getMime(format: Options['format']) {\n const mime = formatsToMimes.get(format)\n if (!mime) throw new Error('Unknown format')\n return mime\n}\n\nexport interface BlobCache {\n get(fileId: string): Promise<Readable & { size: number }>\n put(fileId: string, stream: Readable): Promise<void>\n clear(fileId: string): Promise<void>\n clearAll(): Promise<void>\n}\n\nexport class BlobDiskCache implements BlobCache {\n tempDir: string\n constructor(basePath?: string) {\n this.tempDir = basePath || path.join(os.tmpdir(), 'bsky--processed-images')\n if (!path.isAbsolute(this.tempDir)) {\n throw new Error('Must provide an absolute path')\n }\n try {\n fsSync.mkdirSync(this.tempDir, { recursive: true })\n } catch (err) {\n // All good if cache dir already exists\n if (isErrnoException(err) && err.code === 'EEXIST') return\n }\n }\n\n async get(fileId: string) {\n try {\n const handle = await fs.open(path.join(this.tempDir, fileId), 'r')\n const { size } = await handle.stat()\n if (size === 0) {\n throw new BlobNotFoundError()\n }\n return Object.assign(handle.createReadStream(), { size })\n } catch (err) {\n if (isErrnoException(err) && err.code === 'ENOENT') {\n throw new BlobNotFoundError()\n }\n throw err\n }\n }\n\n async put(fileId: string, stream: Readable) {\n const filename = path.join(this.tempDir, fileId)\n try {\n await fs.writeFile(filename, stream, { flag: 'wx' })\n } catch (err) {\n // Do not overwrite existing file, just ignore the error\n if (isErrnoException(err) && err.code === 'EEXIST') return\n throw err\n }\n }\n\n async clear(fileId: string) {\n const filename = path.join(this.tempDir, fileId)\n await fs.rm(filename, { force: true })\n }\n\n async clearAll() {\n await fs.rm(this.tempDir, { recursive: true, force: true })\n }\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/image/server.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,WAAW,EAAE,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAqB,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEvE,OAAO,EAAc,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACxD,OAAO,EAAsB,cAAc,EAAE,MAAM,WAAW,CAAA;AAE9D,MAAM,UAAU,gBAAgB,CAC9B,GAAe,EACf,EAAE,MAAM,GAAG,GAAG,EAAE,GAAwB,EAAE;IAE1C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAA;IAC/D,CAAC;IAED,mDAAmD;IACnD,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IACnC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAE1D,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,GAAG,CAAC,SAAS;YAAE,OAAM;QACzB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,EAAE,CAAA;QAChE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,EAAE,CAAA;QAC/C,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC3E,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,IAAI,EAAE,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YAEhD,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEtE,cAAc;YAEd,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;gBAC7C,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;gBACpB,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;gBAC/B,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;gBACtD,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAA,CAAC,SAAS;gBACpE,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;gBACjD,MAAM,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;gBAChC,OAAM;YACR,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,GAAG,YAAY,iBAAiB,CAAC,EAAE,CAAC;oBACxC,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,8BAA8B,CAAC,CAAA;gBAC9D,CAAC;gBAED,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;oBACrC,GAAG,CAAC,OAAO,EAAE,CAAA;oBACb,OAAM,CAAC,uBAAuB;gBAChC,CAAC;qBAAM,CAAC;oBACN,yCAAyC;oBACzC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;oBAC3B,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;oBAChC,GAAG,CAAC,YAAY,CAAC,eAAe,CAAC,CAAA;oBACjC,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAA;gBACpC,CAAC;YACH,CAAC;YAED,kBAAkB;YAElB,MAAM,aAAa,GAAsB;gBACvC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC;aAC5B,CAAA;YAED,MAAM,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE;gBACnE,mDAAmD;gBACnD,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;oBAC5D,MAAM,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;gBACxC,CAAC;gBAED,yEAAyE;gBAEzE,MAAM,UAAU,GAAa;oBAC3B,GAAG,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;oBACvD,IAAI,kBAAkB,CAAC,GAAG,CAAC;oBAC3B,mBAAmB,CAAC,OAAO,CAAC;iBAC7B,CAAA;gBACD,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAA;gBAE/C,0BAA0B;gBAC1B,KAAK;qBACF,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;qBACrC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAA;gBAE9D,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;gBACpB,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAA,CAAC,SAAS;gBACpE,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;gBAChC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAa,EAAE,EAAE;oBACrD,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,0BAA0B,CAAA;oBAErE,2DAA2D;oBAC3D,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;oBACrC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;gBACrC,CAAC,CAAC,CAAA;gBAEF,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;gBAC/C,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;oBAC5C,GAAG,CAAC,IAAI,CACN,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,EAClD,4CAA4C,CAC7C,CAAA;gBACH,CAAC,CAAC,CAAA;gBAEF,OAAO,OAAO,CAAC,CAAC,CAAE,CAAA;YACpB,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACrC,GAAG,CAAC,OAAO,EAAE,CAAA;YACf,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;gBAChC,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAA;gBAClC,GAAG,CAAC,YAAY,CAAC,eAAe,CAAC,CAAA;gBACjC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;gBAE3B,IAAI,GAAG,YAAY,YAAY,EAAE,CAAC;oBAChC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;gBAC7B,CAAC;qBAAM,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;oBACzC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAA;gBAC/C,CAAC;qBAAM,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5B,IAAI,CAAC,GAAG,CAAC,CAAA;gBACX,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;gBAC1D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAClB,WAA0C;IAE1C,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,KAAK,0BAA0B,EAAE,CAAC;QACtE,OAAO,SAAS,CAAA,CAAC,QAAQ;IAC3B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA,CAAC,sBAAsB;QACrE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,OAAO,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA,CAAC,8BAA8B;IACtE,CAAC;IACD,OAAO,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;AACzC,CAAC;AAED,SAAS,OAAO,CAAC,MAAyB;IACxC,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAC5C,OAAO,IAAI,CAAA;AACb,CAAC;AASD,MAAM,OAAO,aAAa;IAExB,YAAY,QAAiB;QAC3B,IAAI,CAAC,OAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAA;QAC3E,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;QAClD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uCAAuC;YACvC,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAM;QAC5D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAA;YAClE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;YACpC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,MAAM,IAAI,iBAAiB,EAAE,CAAA;YAC/B,CAAC;YACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnD,MAAM,IAAI,iBAAiB,EAAE,CAAA;YAC/B,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc,EAAE,MAAgB;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAChD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wDAAwD;YACxD,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAM;YAC1D,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAChD,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7D,CAAC;CACF","sourcesContent":["import fsSync from 'node:fs'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Duplex, Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport createError, { isHttpError } from 'http-errors'\nimport {\n VerifyCidError,\n VerifyCidTransform,\n cloneStream,\n createDecoders,\n isErrnoException,\n} from '@atproto/common'\nimport { BlobNotFoundError } from '@atproto/repo'\nimport { StreamBlobOptions, streamBlob } from '../api/blob-resolver.js'\nimport { AppContext } from '../context.js'\nimport { Middleware, responseSignal } from '../util/http.js'\nimport log from './logger.js'\nimport { createImageProcessor, createImageUpscaler } from './sharp.js'\nimport { BadPathError, ImageUriBuilder } from './uri.js'\nimport { Options, SharpInfo, formatsToMimes } from './util.js'\n\nexport function createMiddleware(\n ctx: AppContext,\n { prefix = '/' }: { prefix?: string } = {},\n): Middleware {\n if (!prefix.startsWith('/') || !prefix.endsWith('/')) {\n throw new TypeError('Prefix must start and end with a slash')\n }\n\n // If there is a CDN, we don't need to serve images\n if (ctx.cfg.cdnUrl) {\n return (req, res, next) => next()\n }\n\n const cache = new BlobDiskCache(ctx.cfg.blobCacheLocation)\n\n return async (req, res, next) => {\n if (res.destroyed) return\n if (req.method !== 'GET' && req.method !== 'HEAD') return next()\n if (!req.url?.startsWith(prefix)) return next()\n const { 0: path, 1: _search } = req.url.slice(prefix.length - 1).split('?')\n if (!path.startsWith('/') || path === '/') return next()\n\n try {\n const options = ImageUriBuilder.getOptions(path)\n\n const cacheKey = [options.did, options.cid, options.preset].join('::')\n\n // Cached flow\n\n try {\n const cachedImage = await cache.get(cacheKey)\n res.statusCode = 200\n res.setHeader('x-cache', 'hit')\n res.setHeader('content-type', getMime(options.format))\n res.setHeader('cache-control', `public, max-age=31536000`) // 1 year\n res.setHeader('content-length', cachedImage.size)\n await pipeline(cachedImage, res)\n return\n } catch (err) {\n if (!(err instanceof BlobNotFoundError)) {\n log.error({ cacheKey, err }, 'failed to serve cached image')\n }\n\n if (res.headersSent || res.destroyed) {\n res.destroy()\n return // nothing we can do...\n } else {\n // Ignore and move on to non-cached flow.\n res.removeHeader('x-cache')\n res.removeHeader('content-type')\n res.removeHeader('cache-control')\n res.removeHeader('content-length')\n }\n }\n\n // Non-cached flow\n\n const streamOptions: StreamBlobOptions = {\n did: options.did,\n cid: options.cid,\n signal: responseSignal(res),\n }\n\n await streamBlob(ctx, streamOptions, (upstream, { did, cid, url }) => {\n // Definitely not an image ? Let's fail right away.\n if (isImageMime(upstream.headers['content-type']) === false) {\n throw createError(400, 'Not an image')\n }\n\n // Let's transform (decompress, verify CID, upscale), process and respond\n\n const transforms: Duplex[] = [\n ...createDecoders(upstream.headers['content-encoding']),\n new VerifyCidTransform(cid),\n createImageUpscaler(options),\n ]\n const processor = createImageProcessor(options)\n\n // Cache in the background\n cache\n .put(cacheKey, cloneStream(processor))\n .catch((err) => log.error({ err }, 'failed to cache image'))\n\n res.statusCode = 200\n res.setHeader('cache-control', `public, max-age=31536000`) // 1 year\n res.setHeader('x-cache', 'miss')\n processor.once('info', ({ size, format }: SharpInfo) => {\n const type = formatsToMimes.get(format) || 'application/octet-stream'\n\n // @NOTE sharp does emit this in time to be set as a header\n res.setHeader('content-length', size)\n res.setHeader('content-type', type)\n })\n\n const streams = [...transforms, processor, res]\n void pipeline(streams).catch((err: unknown) => {\n log.warn(\n { err, did, cid: cid.toString(), pds: url.origin },\n 'blob resolution failed during transmission',\n )\n })\n\n return streams[0]!\n })\n } catch (err) {\n if (res.headersSent || res.destroyed) {\n res.destroy()\n } else {\n res.removeHeader('content-type')\n res.removeHeader('content-length')\n res.removeHeader('cache-control')\n res.removeHeader('x-cache')\n\n if (err instanceof BadPathError) {\n next(createError(400, err))\n } else if (err instanceof VerifyCidError) {\n next(createError(404, 'Blob not found', err))\n } else if (isHttpError(err)) {\n next(err)\n } else {\n next(createError(502, 'Upstream Error', { cause: err }))\n }\n }\n }\n }\n}\n\nfunction isImageMime(\n contentType: string | string[] | undefined,\n): undefined | boolean {\n if (contentType == null || contentType === 'application/octet-stream') {\n return undefined // maybe\n }\n if (Array.isArray(contentType)) {\n if (contentType.length === 0) return undefined // should never happen\n if (contentType.length === 1) return isImageMime(contentType[0])\n return contentType.every(isImageMime) // Should we throw a 502 here?\n }\n return contentType.startsWith('image/')\n}\n\nfunction getMime(format: Options['format']) {\n const mime = formatsToMimes.get(format)\n if (!mime) throw new Error('Unknown format')\n return mime\n}\n\nexport interface BlobCache {\n get(fileId: string): Promise<Readable & { size: number }>\n put(fileId: string, stream: Readable): Promise<void>\n clear(fileId: string): Promise<void>\n clearAll(): Promise<void>\n}\n\nexport class BlobDiskCache implements BlobCache {\n tempDir: string\n constructor(basePath?: string) {\n this.tempDir = basePath || path.join(os.tmpdir(), 'bsky--processed-images')\n if (!path.isAbsolute(this.tempDir)) {\n throw new Error('Must provide an absolute path')\n }\n try {\n fsSync.mkdirSync(this.tempDir, { recursive: true })\n } catch (err) {\n // All good if cache dir already exists\n if (isErrnoException(err) && err.code === 'EEXIST') return\n }\n }\n\n async get(fileId: string) {\n try {\n const handle = await fs.open(path.join(this.tempDir, fileId), 'r')\n const { size } = await handle.stat()\n if (size === 0) {\n throw new BlobNotFoundError()\n }\n return Object.assign(handle.createReadStream(), { size })\n } catch (err) {\n if (isErrnoException(err) && err.code === 'ENOENT') {\n throw new BlobNotFoundError()\n }\n throw err\n }\n }\n\n async put(fileId: string, stream: Readable) {\n const filename = path.join(this.tempDir, fileId)\n try {\n await fs.writeFile(filename, stream, { flag: 'wx' })\n } catch (err) {\n // Do not overwrite existing file, just ignore the error\n if (isErrnoException(err) && err.code === 'EEXIST') return\n throw err\n }\n }\n\n async clear(fileId: string) {\n const filename = path.join(this.tempDir, fileId)\n await fs.rm(filename, { force: true })\n }\n\n async clearAll() {\n await fs.rm(this.tempDir, { recursive: true, force: true })\n }\n}\n"]}
@@ -5,7 +5,7 @@ export type { Options };
5
5
  /**
6
6
  * Scale up to hit any specified minimum size
7
7
  */
8
- export declare function createImageUpscaler({ min }: Options): sharp.Sharp | PassThrough;
8
+ export declare function createImageUpscaler({ min }: Options): PassThrough | sharp.Sharp;
9
9
  /**
10
10
  * Scale down (or possibly up if min is true) to desired size, then compress
11
11
  * to the desired format.
@@ -1 +1 @@
1
- {"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/image/uri.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,QAAQ,GACR,gBAAgB,GAChB,eAAe,CAAA;AAInB,qBAAa,eAAe;IACnB,QAAQ,EAAE,SAAS,CAAA;gBAEd,QAAQ,EAAE,MAAM;IAO5B,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,CAK5B;IAED,YAAY,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS;IAelE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,YAAY;IAI3D,MAAM,CAAC,UAAU,CACf,IAAI,EAAE,MAAM,GACX,OAAO,GAAG,YAAY,GAAG;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE;CA0BpD;AAED,KAAK,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhD,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAI1C,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CA6BhD,CAAA"}
1
+ {"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/image/uri.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,QAAQ,GACR,gBAAgB,GAChB,eAAe,CAAA;AAInB,qBAAa,eAAe;IACnB,QAAQ,EAAE,SAAS,CAAA;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAK3B;IAED,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,CAK5B;IAED,YAAY,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAajE;IAED,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,YAAY,UAE1D;IAED,MAAM,CAAC,UAAU,CACf,IAAI,EAAE,MAAM,GACX,OAAO,GAAG,YAAY,GAAG;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAyBlD;CACF;AAED,KAAK,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhD,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAI1C,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CA6BhD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"uri.js","sourceRoot":"","sources":["../../src/image/uri.ts"],"names":[],"mappings":"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","sourcesContent":["import { UriString, isUriString } from '@atproto/lex'\nimport { Options } from './util.js'\n\n// @NOTE if there are any additions here, ensure to include them on ImageUriBuilder.presets\nexport type ImagePreset =\n | 'avatar'\n | 'banner'\n | 'feed_thumbnail'\n | 'feed_fullsize'\n\nconst PATH_REGEX = /^\\/(.+?)\\/plain\\/(.+?)\\/(.+?)(?:@(.+?))?$/\n\nexport class ImageUriBuilder {\n public endpoint: UriString\n\n constructor(endpoint: string) {\n if (!isUriString(endpoint)) {\n throw new Error('ImageUriBuilder endpoint must be a valid UriString')\n }\n this.endpoint = endpoint\n }\n\n static presets: ImagePreset[] = [\n 'avatar',\n 'banner',\n 'feed_thumbnail',\n 'feed_fullsize',\n ]\n\n getPresetUri(id: ImagePreset, did: string, cid: string): UriString {\n const options = presets[id]\n if (!options) {\n throw new Error(`Unrecognized requested common uri type: ${id}`)\n }\n\n const path = ImageUriBuilder.getPath({\n preset: id,\n did,\n cid,\n })\n\n return `${this.endpoint}${path}`\n }\n\n static getPath(opts: { preset: ImagePreset } & BlobLocation) {\n return `/${opts.preset}/plain/${opts.did}/${opts.cid}`\n }\n\n static getOptions(\n path: string,\n ): Options & BlobLocation & { preset: ImagePreset } {\n const match = path.match(PATH_REGEX)\n if (!match) {\n throw new BadPathError('Invalid path')\n }\n const [, presetUnsafe, did, cid, formatUnsafe] = match\n if (!(ImageUriBuilder.presets as string[]).includes(presetUnsafe)) {\n throw new BadPathError('Invalid path: bad preset')\n }\n if (\n formatUnsafe !== undefined &&\n formatUnsafe !== 'jpeg' &&\n formatUnsafe !== 'webp'\n ) {\n throw new BadPathError('Invalid path: bad format')\n }\n const preset = presetUnsafe as ImagePreset\n const format = formatUnsafe as Options['format']\n return {\n ...presets[preset],\n format: format ?? presets[preset].format,\n did,\n cid,\n preset,\n }\n }\n}\n\ntype BlobLocation = { cid: string; did: string }\n\nexport class BadPathError extends Error {}\n\n// @NOTE these prefix settings don't get used anywhere in this package,\n// but they serve as soft documentation of the behavior in production.\nexport const presets: Record<ImagePreset, Options> = {\n avatar: {\n format: 'webp',\n fit: 'cover',\n height: 1000,\n width: 1000,\n min: true,\n },\n banner: {\n format: 'webp',\n fit: 'cover',\n height: 1000,\n width: 3000,\n min: true,\n },\n feed_thumbnail: {\n format: 'webp',\n fit: 'inside',\n height: 2000,\n width: 2000,\n min: true,\n },\n feed_fullsize: {\n format: 'webp',\n fit: 'inside',\n height: 1000,\n width: 1000,\n min: true,\n },\n}\n"]}
1
+ {"version":3,"file":"uri.js","sourceRoot":"","sources":["../../src/image/uri.ts"],"names":[],"mappings":"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","sourcesContent":["import { UriString, isUriString } from '@atproto/lex'\nimport { Options } from './util.js'\n\n// @NOTE if there are any additions here, ensure to include them on ImageUriBuilder.presets\nexport type ImagePreset =\n | 'avatar'\n | 'banner'\n | 'feed_thumbnail'\n | 'feed_fullsize'\n\nconst PATH_REGEX = /^\\/(.+?)\\/plain\\/(.+?)\\/(.+?)(?:@(.+?))?$/\n\nexport class ImageUriBuilder {\n public endpoint: UriString\n\n constructor(endpoint: string) {\n if (!isUriString(endpoint)) {\n throw new Error('ImageUriBuilder endpoint must be a valid UriString')\n }\n this.endpoint = endpoint\n }\n\n static presets: ImagePreset[] = [\n 'avatar',\n 'banner',\n 'feed_thumbnail',\n 'feed_fullsize',\n ]\n\n getPresetUri(id: ImagePreset, did: string, cid: string): UriString {\n const options = presets[id]\n if (!options) {\n throw new Error(`Unrecognized requested common uri type: ${id}`)\n }\n\n const path = ImageUriBuilder.getPath({\n preset: id,\n did,\n cid,\n })\n\n return `${this.endpoint}${path}`\n }\n\n static getPath(opts: { preset: ImagePreset } & BlobLocation) {\n return `/${opts.preset}/plain/${opts.did}/${opts.cid}`\n }\n\n static getOptions(\n path: string,\n ): Options & BlobLocation & { preset: ImagePreset } {\n const match = path.match(PATH_REGEX)\n if (!match) {\n throw new BadPathError('Invalid path')\n }\n const [, presetUnsafe, did, cid, formatUnsafe] = match\n if (!(ImageUriBuilder.presets as string[]).includes(presetUnsafe)) {\n throw new BadPathError('Invalid path: bad preset')\n }\n if (\n formatUnsafe !== undefined &&\n formatUnsafe !== 'jpeg' &&\n formatUnsafe !== 'webp'\n ) {\n throw new BadPathError('Invalid path: bad format')\n }\n const preset = presetUnsafe as ImagePreset\n const format = formatUnsafe as Options['format']\n return {\n ...presets[preset],\n format: format ?? presets[preset].format,\n did,\n cid,\n preset,\n }\n }\n}\n\ntype BlobLocation = { cid: string; did: string }\n\nexport class BadPathError extends Error {}\n\n// @NOTE these prefix settings don't get used anywhere in this package,\n// but they serve as soft documentation of the behavior in production.\nexport const presets: Record<ImagePreset, Options> = {\n avatar: {\n format: 'webp',\n fit: 'cover',\n height: 1000,\n width: 1000,\n min: true,\n },\n banner: {\n format: 'webp',\n fit: 'cover',\n height: 1000,\n width: 3000,\n min: true,\n },\n feed_thumbnail: {\n format: 'webp',\n fit: 'inside',\n height: 2000,\n width: 2000,\n min: true,\n },\n feed_fullsize: {\n format: 'webp',\n fit: 'inside',\n height: 1000,\n width: 1000,\n min: true,\n },\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAK5B,OAAO,OAAO,MAAM,SAAS,CAAA;AAO7B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAczC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAyBzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,qBAAa,WAAW;IACf,GAAG,EAAE,UAAU,CAAA;IACf,GAAG,EAAE,OAAO,CAAC,WAAW,CAAA;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAA;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAgB;gBAEvB,IAAI,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC,WAAW,CAAA;KAAE;IAK/D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,YAAY,CAAA;QACpB,UAAU,EAAE,OAAO,CAAA;KACpB,GAAG,WAAW;IA+MT,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;IAe7B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B;AAED,eAAe,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAK5B,OAAO,OAAO,MAAM,SAAS,CAAA;AAO7B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAczC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAyBzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,qBAAa,WAAW;IACf,GAAG,EAAE,UAAU,CAAA;IACf,GAAG,EAAE,OAAO,CAAC,WAAW,CAAA;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAA;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAgB;IAEnC,YAAY,IAAI,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC,WAAW,CAAA;KAAE,EAG9D;IAED,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,YAAY,CAAA;QACpB,UAAU,EAAE,OAAO,CAAA;KACpB,GAAG,WAAW,CA6Md;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAalC;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAI7B;CACF;eAEc,WAAW"}
package/dist/kws.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kws.d.ts","sourceRoot":"","sources":["../src/kws.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,eAAO,MAAM,eAAe,GAAI,KAAK,SAAS,KAAG,SAEhD,CAAA;AAQD;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;CAAG;AAErD,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B,CAAC,yBAAyB,GAAG;IAC3B,WAAW,EAAE,OAAO,CAAA;CACrB,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,WAAW,EAAE,KAAK,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEN,qBAAa,SAAS;IACD,GAAG,EAAE,SAAS;gBAAd,GAAG,EAAE,SAAS;YAEnB,IAAI;YAiCJ,aAAa;IAe3B;;OAEG;IACG,SAAS,CAAC,EACd,WAAW,EACX,KAAK,EACL,eAAe,EACf,QAAQ,GACT,EAAE;QACD,WAAW,EAAE,MAAM,CAAA;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,eAAe,EAAE,kBAAkB,CAAA;QACnC,QAAQ,EAAE,MAAM,CAAA;KACjB;IAoCD;;OAEG;IACG,KAAK,CAAC,KAAK,EAAE,mBAAmB;IA8BtC;;;OAGG;IACG,0BAA0B,CAAC,KAAK,EAAE,yBAAyB;IAOjE;;;OAGG;IACG,wBAAwB,CAAC,KAAK,EAAE,yBAAyB;CAOhE"}
1
+ {"version":3,"file":"kws.d.ts","sourceRoot":"","sources":["../src/kws.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,eAAO,MAAM,eAAe,QAAS,SAAS,KAAG,SAEhD,CAAA;AAQD;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;CAAG;AAErD,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B,CAAC,yBAAyB,GAAG;IAC3B,WAAW,EAAE,OAAO,CAAA;CACrB,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,WAAW,EAAE,KAAK,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEN,qBAAa,SAAS;IACD,GAAG,EAAE,SAAS;IAAjC,YAAmB,GAAG,EAAE,SAAS,EAAI;YAEvB,IAAI;YAiCJ,aAAa;IAe3B;;OAEG;IACG,SAAS,CAAC,EACd,WAAW,EACX,KAAK,EACL,eAAe,EACf,QAAQ,GACT,EAAE;QACD,WAAW,EAAE,MAAM,CAAA;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,eAAe,EAAE,kBAAkB,CAAA;QACnC,QAAQ,EAAE,MAAM,CAAA;KACjB,oBAkCA;IAED;;OAEG;IACG,KAAK,CAAC,KAAK,EAAE,mBAAmB,oBA4BrC;IAED;;;OAGG;IACG,0BAA0B,CAAC,KAAK,EAAE,yBAAyB,oBAKhE;IAED;;;OAGG;IACG,wBAAwB,CAAC,KAAK,EAAE,yBAAyB,oBAM9D;CACF"}
package/dist/kws.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kws.js","sourceRoot":"","sources":["../src/kws.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { KwsExternalPayload } from './api/kws/types.js'\nimport { serializeExternalPayload } from './api/kws/util.js'\nimport { buildBasicAuth } from './auth-verifier.js'\nimport { KwsConfig } from './config.js'\nimport { httpLogger as log } from './logger.js'\n\nexport const createKwsClient = (cfg: KwsConfig): KwsClient => {\n return new KwsClient(cfg)\n}\n\n// Not `.strict()` to avoid breaking if KWS adds fields.\nconst authResponseSchema = z.object({\n access_token: z.string(),\n})\n\nconst EXTERNAL_PAYLOAD_CHAR_LIMIT = 200\n/**\n * Thrown when the provided external payload exceeds KWS's character limit.\n * This is most commonly caused by DIDs that are too long, such as for\n * `did:web` DIDs. But it's very rare, and the client has special handling for\n * this case.\n */\nexport class KwsExternalPayloadError extends Error {}\n\nexport type KWSSendEmailRequestCommon = {\n email: string\n location: string\n language: string\n externalPayload: string\n}\n\nexport type KWSSendEmailRequest =\n | (KWSSendEmailRequestCommon & {\n userContext: 'adult'\n })\n | (KWSSendEmailRequestCommon & {\n userContext: 'age'\n minimumAge: number\n })\n\nexport class KwsClient {\n constructor(public cfg: KwsConfig) {}\n\n private async auth() {\n try {\n const res = await fetch(\n `${this.cfg.authOrigin}/auth/realms/kws/protocol/openid-connect/token`,\n {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: buildBasicAuth(this.cfg.clientId, this.cfg.apiKey),\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n scope: 'verification',\n }),\n },\n )\n if (!res.ok) {\n const errorText = await res.text()\n throw new Error(\n `Failed to fetch age assurance access token: status: ${res.status}, statusText: ${res.statusText}, errorText: ${errorText}`,\n )\n }\n\n const auth = await res.json()\n const authResponse = authResponseSchema.parse(auth)\n return authResponse.access_token\n } catch (err) {\n log.error({ err }, 'Failed to authenticate with KWS')\n throw err\n }\n }\n\n private async fetchWithAuth(\n url: string,\n init: RequestInit,\n ): Promise<Response> {\n const accessToken = await this.auth()\n\n return fetch(url, {\n ...init,\n headers: {\n ...(init.headers ?? {}),\n Authorization: `Bearer ${accessToken}`,\n },\n })\n }\n\n /**\n * @deprecated Use `sendAdultVerifiedFlowEmail` or `sendAgeVerifiedFlowEmail` instead.\n */\n async sendEmail({\n countryCode,\n email,\n externalPayload,\n language,\n }: {\n countryCode: string\n email: string\n externalPayload: KwsExternalPayload\n language: string\n }) {\n const serializedExternalPayload = serializeExternalPayload(externalPayload)\n if (serializedExternalPayload.length > EXTERNAL_PAYLOAD_CHAR_LIMIT) {\n throw new KwsExternalPayloadError()\n }\n\n const res = await this.fetchWithAuth(\n `${this.cfg.apiOrigin}/v1/verifications/send-email`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': this.cfg.userAgent,\n },\n body: JSON.stringify({\n email,\n externalPayload: serializedExternalPayload,\n language,\n location: countryCode,\n userContext: 'adult',\n }),\n },\n )\n\n if (!res.ok) {\n const errorText = await res.text()\n log.error(\n { status: res.status, statusText: res.statusText, errorText },\n 'Failed to send age assurance email',\n )\n throw new Error('Failed to send age assurance email')\n }\n\n return res.json()\n }\n\n /**\n * Sends a KWS verification email with the given properties.\n */\n async email(props: KWSSendEmailRequest) {\n const res = await this.fetchWithAuth(\n `${this.cfg.apiOrigin}/v1/verifications/send-email`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': this.cfg.userAgent,\n },\n body: JSON.stringify(props),\n },\n )\n\n if (!res.ok) {\n const errorText = await res.text()\n log.error(\n {\n status: res.status,\n statusText: res.statusText,\n errorText,\n flow: props.userContext,\n },\n 'Failed to send KWS email',\n )\n throw new Error('Failed to send KWS email')\n }\n\n return res.json()\n }\n\n /**\n * Sends an email to the user initiating an `adult` verification flow, which\n * results in `adult-verified` events/webhooks.\n */\n async sendAdultVerifiedFlowEmail(props: KWSSendEmailRequestCommon) {\n return this.email({\n ...props,\n userContext: 'adult',\n })\n }\n\n /**\n * Sends an email to the user initiating an `age` verification flow, which\n * results in `age-verified` events/webhooks.\n */\n async sendAgeVerifiedFlowEmail(props: KWSSendEmailRequestCommon) {\n return this.email({\n ...props,\n userContext: 'age',\n minimumAge: 16, // KWS required value\n })\n }\n}\n"]}
1
+ {"version":3,"file":"kws.js","sourceRoot":"","sources":["../src/kws.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { KwsExternalPayload } from './api/kws/types.js'\nimport { serializeExternalPayload } from './api/kws/util.js'\nimport { buildBasicAuth } from './auth-verifier.js'\nimport { KwsConfig } from './config.js'\nimport { httpLogger as log } from './logger.js'\n\nexport const createKwsClient = (cfg: KwsConfig): KwsClient => {\n return new KwsClient(cfg)\n}\n\n// Not `.strict()` to avoid breaking if KWS adds fields.\nconst authResponseSchema = z.object({\n access_token: z.string(),\n})\n\nconst EXTERNAL_PAYLOAD_CHAR_LIMIT = 200\n/**\n * Thrown when the provided external payload exceeds KWS's character limit.\n * This is most commonly caused by DIDs that are too long, such as for\n * `did:web` DIDs. But it's very rare, and the client has special handling for\n * this case.\n */\nexport class KwsExternalPayloadError extends Error {}\n\nexport type KWSSendEmailRequestCommon = {\n email: string\n location: string\n language: string\n externalPayload: string\n}\n\nexport type KWSSendEmailRequest =\n | (KWSSendEmailRequestCommon & {\n userContext: 'adult'\n })\n | (KWSSendEmailRequestCommon & {\n userContext: 'age'\n minimumAge: number\n })\n\nexport class KwsClient {\n constructor(public cfg: KwsConfig) {}\n\n private async auth() {\n try {\n const res = await fetch(\n `${this.cfg.authOrigin}/auth/realms/kws/protocol/openid-connect/token`,\n {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: buildBasicAuth(this.cfg.clientId, this.cfg.apiKey),\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n scope: 'verification',\n }),\n },\n )\n if (!res.ok) {\n const errorText = await res.text()\n throw new Error(\n `Failed to fetch age assurance access token: status: ${res.status}, statusText: ${res.statusText}, errorText: ${errorText}`,\n )\n }\n\n const auth = await res.json()\n const authResponse = authResponseSchema.parse(auth)\n return authResponse.access_token\n } catch (err) {\n log.error({ err }, 'Failed to authenticate with KWS')\n throw err\n }\n }\n\n private async fetchWithAuth(\n url: string,\n init: RequestInit,\n ): Promise<Response> {\n const accessToken = await this.auth()\n\n return fetch(url, {\n ...init,\n headers: {\n ...(init.headers ?? {}),\n Authorization: `Bearer ${accessToken}`,\n },\n })\n }\n\n /**\n * @deprecated Use `sendAdultVerifiedFlowEmail` or `sendAgeVerifiedFlowEmail` instead.\n */\n async sendEmail({\n countryCode,\n email,\n externalPayload,\n language,\n }: {\n countryCode: string\n email: string\n externalPayload: KwsExternalPayload\n language: string\n }) {\n const serializedExternalPayload = serializeExternalPayload(externalPayload)\n if (serializedExternalPayload.length > EXTERNAL_PAYLOAD_CHAR_LIMIT) {\n throw new KwsExternalPayloadError()\n }\n\n const res = await this.fetchWithAuth(\n `${this.cfg.apiOrigin}/v1/verifications/send-email`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': this.cfg.userAgent,\n },\n body: JSON.stringify({\n email,\n externalPayload: serializedExternalPayload,\n language,\n location: countryCode,\n userContext: 'adult',\n }),\n },\n )\n\n if (!res.ok) {\n const errorText = await res.text()\n log.error(\n { status: res.status, statusText: res.statusText, errorText },\n 'Failed to send age assurance email',\n )\n throw new Error('Failed to send age assurance email')\n }\n\n return res.json()\n }\n\n /**\n * Sends a KWS verification email with the given properties.\n */\n async email(props: KWSSendEmailRequest) {\n const res = await this.fetchWithAuth(\n `${this.cfg.apiOrigin}/v1/verifications/send-email`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': this.cfg.userAgent,\n },\n body: JSON.stringify(props),\n },\n )\n\n if (!res.ok) {\n const errorText = await res.text()\n log.error(\n {\n status: res.status,\n statusText: res.statusText,\n errorText,\n flow: props.userContext,\n },\n 'Failed to send KWS email',\n )\n throw new Error('Failed to send KWS email')\n }\n\n return res.json()\n }\n\n /**\n * Sends an email to the user initiating an `adult` verification flow, which\n * results in `adult-verified` events/webhooks.\n */\n async sendAdultVerifiedFlowEmail(props: KWSSendEmailRequestCommon) {\n return this.email({\n ...props,\n userContext: 'adult',\n })\n }\n\n /**\n * Sends an email to the user initiating an `age` verification flow, which\n * results in `age-verified` events/webhooks.\n */\n async sendAgeVerifiedFlowEmail(props: KWSSendEmailRequestCommon) {\n return this.email({\n ...props,\n userContext: 'age',\n minimumAge: 16, // KWS required value\n })\n }\n}\n"]}
@@ -206,211 +206,131 @@ export { verificationView };
206
206
  type Preferences = (l.$Typed<AdultContentPref> | l.$Typed<ContentLabelPref> | l.$Typed<SavedFeedsPref> | l.$Typed<SavedFeedsPrefV2> | l.$Typed<PersonalDetailsPref> | l.$Typed<DeclaredAgePref> | l.$Typed<FeedViewPref> | l.$Typed<ThreadViewPref> | l.$Typed<InterestsPref> | l.$Typed<MutedWordsPref> | l.$Typed<HiddenPostsPref> | l.$Typed<BskyAppStatePref> | l.$Typed<LabelersPref> | l.$Typed<PostInteractionSettingsPref> | l.$Typed<VerificationPrefs> | l.$Typed<LiveEventPreferences> | l.Unknown$TypedObject)[];
207
207
  export type { Preferences };
208
208
  declare const preferences: l.ArraySchema<l.Validator<l.Unknown$TypedObject | {
209
- $type: "app.bsky.actor.defs#adultContentPref";
209
+ $type: 'app.bsky.actor.defs#adultContentPref';
210
210
  enabled: boolean;
211
211
  } | {
212
- $type: "app.bsky.actor.defs#contentLabelPref";
213
- labelerDid?: l.DidString | undefined;
212
+ $type: 'app.bsky.actor.defs#contentLabelPref';
213
+ labelerDid?: l.DidString;
214
214
  label: string;
215
- visibility: "ignore" | "show" | "warn" | "hide" | l.UnknownString;
215
+ visibility: 'ignore' | 'show' | 'warn' | 'hide' | l.UnknownString;
216
216
  } | {
217
- $type: "app.bsky.actor.defs#savedFeedsPref";
217
+ $type: 'app.bsky.actor.defs#savedFeedsPref';
218
218
  pinned: l.AtUriString[];
219
219
  saved: l.AtUriString[];
220
- timelineIndex?: number | undefined;
220
+ timelineIndex?: number;
221
221
  } | {
222
- $type: "app.bsky.actor.defs#savedFeedsPrefV2";
222
+ $type: 'app.bsky.actor.defs#savedFeedsPrefV2';
223
223
  items: SavedFeed[];
224
224
  } | {
225
- $type: "app.bsky.actor.defs#personalDetailsPref";
226
- birthDate?: l.DatetimeString | undefined;
225
+ $type: 'app.bsky.actor.defs#personalDetailsPref';
226
+ birthDate?: l.DatetimeString;
227
227
  } | {
228
- $type: "app.bsky.actor.defs#declaredAgePref";
229
- isOverAge13?: boolean
230
- /**
231
- * Indicates if the user has declared that they are over 16 years of age.
232
- */
233
- | undefined;
234
- isOverAge16?: boolean
235
- /**
236
- * Indicates if the user has declared that they are over 18 years of age.
237
- */
238
- | undefined;
239
- isOverAge18?: boolean | undefined;
228
+ $type: 'app.bsky.actor.defs#declaredAgePref';
229
+ isOverAge13?: boolean;
230
+ isOverAge16?: boolean;
231
+ isOverAge18?: boolean;
240
232
  } | {
241
- $type: "app.bsky.actor.defs#feedViewPref";
233
+ $type: 'app.bsky.actor.defs#feedViewPref';
242
234
  feed: string;
243
- hideReplies?: boolean
244
- /**
245
- * Hide replies in the feed if they are not by followed users.
246
- */
247
- | undefined;
248
- hideRepliesByUnfollowed?: boolean
249
- /**
250
- * Hide replies in the feed if they do not have this number of likes.
251
- */
252
- | undefined;
253
- hideRepliesByLikeCount?: number
254
- /**
255
- * Hide reposts in the feed.
256
- */
257
- | undefined;
258
- hideReposts?: boolean
259
- /**
260
- * Hide quote posts in the feed.
261
- */
262
- | undefined;
263
- hideQuotePosts?: boolean | undefined;
235
+ hideReplies?: boolean;
236
+ hideRepliesByUnfollowed?: boolean;
237
+ hideRepliesByLikeCount?: number;
238
+ hideReposts?: boolean;
239
+ hideQuotePosts?: boolean;
264
240
  } | {
265
- $type: "app.bsky.actor.defs#threadViewPref";
266
- sort?: ("oldest" | "newest" | "most-likes" | "random" | "hotness" | l.UnknownString) | undefined;
241
+ $type: 'app.bsky.actor.defs#threadViewPref';
242
+ sort?: 'oldest' | 'newest' | 'most-likes' | 'random' | 'hotness' | l.UnknownString;
267
243
  } | {
268
- $type: "app.bsky.actor.defs#interestsPref";
244
+ $type: 'app.bsky.actor.defs#interestsPref';
269
245
  tags: string[];
270
246
  } | {
271
- $type: "app.bsky.actor.defs#mutedWordsPref";
247
+ $type: 'app.bsky.actor.defs#mutedWordsPref';
272
248
  items: MutedWord[];
273
249
  } | {
274
- $type: "app.bsky.actor.defs#hiddenPostsPref";
250
+ $type: 'app.bsky.actor.defs#hiddenPostsPref';
275
251
  items: l.AtUriString[];
276
252
  } | {
277
- $type: "app.bsky.actor.defs#bskyAppStatePref";
278
- activeProgressGuide?: BskyAppProgressGuide
279
- /**
280
- * An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user.
281
- */
282
- | undefined;
283
- queuedNudges?: string[]
284
- /**
285
- * Storage for NUXs the user has encountered.
286
- */
287
- | undefined;
288
- nuxs?: Nux[] | undefined;
253
+ $type: 'app.bsky.actor.defs#bskyAppStatePref';
254
+ activeProgressGuide?: BskyAppProgressGuide;
255
+ queuedNudges?: string[];
256
+ nuxs?: Nux[];
289
257
  } | {
290
- $type: "app.bsky.actor.defs#labelersPref";
258
+ $type: 'app.bsky.actor.defs#labelersPref';
291
259
  labelers: LabelerPrefItem[];
292
260
  } | {
293
- $type: "app.bsky.actor.defs#postInteractionSettingsPref";
294
- threadgateAllowRules?: (l.$Typed<FeedThreadgate.MentionRule> | l.$Typed<FeedThreadgate.FollowerRule> | l.$Typed<FeedThreadgate.FollowingRule> | l.$Typed<FeedThreadgate.ListRule> | l.Unknown$TypedObject)[]
295
- /**
296
- * Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.
297
- */
298
- | undefined;
299
- postgateEmbeddingRules?: (l.$Typed<FeedPostgate.DisableRule> | l.Unknown$TypedObject)[] | undefined;
261
+ $type: 'app.bsky.actor.defs#postInteractionSettingsPref';
262
+ threadgateAllowRules?: (l.$Typed<FeedThreadgate.MentionRule> | l.$Typed<FeedThreadgate.FollowerRule> | l.$Typed<FeedThreadgate.FollowingRule> | l.$Typed<FeedThreadgate.ListRule> | l.Unknown$TypedObject)[];
263
+ postgateEmbeddingRules?: (l.$Typed<FeedPostgate.DisableRule> | l.Unknown$TypedObject)[];
300
264
  } | {
301
- $type: "app.bsky.actor.defs#verificationPrefs";
302
- hideBadges?: boolean | undefined;
265
+ $type: 'app.bsky.actor.defs#verificationPrefs';
266
+ hideBadges?: boolean;
303
267
  } | {
304
- $type: "app.bsky.actor.defs#liveEventPreferences";
305
- hiddenFeedIds?: string[]
306
- /**
307
- * Whether to hide all feeds from live events.
308
- */
309
- | undefined;
310
- hideAllFeeds?: boolean | undefined;
268
+ $type: 'app.bsky.actor.defs#liveEventPreferences';
269
+ hiddenFeedIds?: string[];
270
+ hideAllFeeds?: boolean;
311
271
  }, l.Unknown$TypedObject | {
312
- $type: "app.bsky.actor.defs#adultContentPref";
272
+ $type: 'app.bsky.actor.defs#adultContentPref';
313
273
  enabled: boolean;
314
274
  } | {
315
- $type: "app.bsky.actor.defs#contentLabelPref";
316
- labelerDid?: l.DidString | undefined;
275
+ $type: 'app.bsky.actor.defs#contentLabelPref';
276
+ labelerDid?: l.DidString;
317
277
  label: string;
318
- visibility: "ignore" | "show" | "warn" | "hide" | l.UnknownString;
278
+ visibility: 'ignore' | 'show' | 'warn' | 'hide' | l.UnknownString;
319
279
  } | {
320
- $type: "app.bsky.actor.defs#savedFeedsPref";
280
+ $type: 'app.bsky.actor.defs#savedFeedsPref';
321
281
  pinned: l.AtUriString[];
322
282
  saved: l.AtUriString[];
323
- timelineIndex?: number | undefined;
283
+ timelineIndex?: number;
324
284
  } | {
325
- $type: "app.bsky.actor.defs#savedFeedsPrefV2";
285
+ $type: 'app.bsky.actor.defs#savedFeedsPrefV2';
326
286
  items: SavedFeed[];
327
287
  } | {
328
- $type: "app.bsky.actor.defs#personalDetailsPref";
329
- birthDate?: l.DatetimeString | undefined;
288
+ $type: 'app.bsky.actor.defs#personalDetailsPref';
289
+ birthDate?: l.DatetimeString;
330
290
  } | {
331
- $type: "app.bsky.actor.defs#declaredAgePref";
332
- isOverAge13?: boolean
333
- /**
334
- * Indicates if the user has declared that they are over 16 years of age.
335
- */
336
- | undefined;
337
- isOverAge16?: boolean
338
- /**
339
- * Indicates if the user has declared that they are over 18 years of age.
340
- */
341
- | undefined;
342
- isOverAge18?: boolean | undefined;
291
+ $type: 'app.bsky.actor.defs#declaredAgePref';
292
+ isOverAge13?: boolean;
293
+ isOverAge16?: boolean;
294
+ isOverAge18?: boolean;
343
295
  } | {
344
- $type: "app.bsky.actor.defs#feedViewPref";
296
+ $type: 'app.bsky.actor.defs#feedViewPref';
345
297
  feed: string;
346
- hideReplies?: boolean
347
- /**
348
- * Hide replies in the feed if they are not by followed users.
349
- */
350
- | undefined;
351
- hideRepliesByUnfollowed?: boolean
352
- /**
353
- * Hide replies in the feed if they do not have this number of likes.
354
- */
355
- | undefined;
356
- hideRepliesByLikeCount?: number
357
- /**
358
- * Hide reposts in the feed.
359
- */
360
- | undefined;
361
- hideReposts?: boolean
362
- /**
363
- * Hide quote posts in the feed.
364
- */
365
- | undefined;
366
- hideQuotePosts?: boolean | undefined;
298
+ hideReplies?: boolean;
299
+ hideRepliesByUnfollowed?: boolean;
300
+ hideRepliesByLikeCount?: number;
301
+ hideReposts?: boolean;
302
+ hideQuotePosts?: boolean;
367
303
  } | {
368
- $type: "app.bsky.actor.defs#threadViewPref";
369
- sort?: ("oldest" | "newest" | "most-likes" | "random" | "hotness" | l.UnknownString) | undefined;
304
+ $type: 'app.bsky.actor.defs#threadViewPref';
305
+ sort?: 'oldest' | 'newest' | 'most-likes' | 'random' | 'hotness' | l.UnknownString;
370
306
  } | {
371
- $type: "app.bsky.actor.defs#interestsPref";
307
+ $type: 'app.bsky.actor.defs#interestsPref';
372
308
  tags: string[];
373
309
  } | {
374
- $type: "app.bsky.actor.defs#mutedWordsPref";
310
+ $type: 'app.bsky.actor.defs#mutedWordsPref';
375
311
  items: MutedWord[];
376
312
  } | {
377
- $type: "app.bsky.actor.defs#hiddenPostsPref";
313
+ $type: 'app.bsky.actor.defs#hiddenPostsPref';
378
314
  items: l.AtUriString[];
379
315
  } | {
380
- $type: "app.bsky.actor.defs#bskyAppStatePref";
381
- activeProgressGuide?: BskyAppProgressGuide
382
- /**
383
- * An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user.
384
- */
385
- | undefined;
386
- queuedNudges?: string[]
387
- /**
388
- * Storage for NUXs the user has encountered.
389
- */
390
- | undefined;
391
- nuxs?: Nux[] | undefined;
316
+ $type: 'app.bsky.actor.defs#bskyAppStatePref';
317
+ activeProgressGuide?: BskyAppProgressGuide;
318
+ queuedNudges?: string[];
319
+ nuxs?: Nux[];
392
320
  } | {
393
- $type: "app.bsky.actor.defs#labelersPref";
321
+ $type: 'app.bsky.actor.defs#labelersPref';
394
322
  labelers: LabelerPrefItem[];
395
323
  } | {
396
- $type: "app.bsky.actor.defs#postInteractionSettingsPref";
397
- threadgateAllowRules?: (l.$Typed<FeedThreadgate.MentionRule> | l.$Typed<FeedThreadgate.FollowerRule> | l.$Typed<FeedThreadgate.FollowingRule> | l.$Typed<FeedThreadgate.ListRule> | l.Unknown$TypedObject)[]
398
- /**
399
- * Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.
400
- */
401
- | undefined;
402
- postgateEmbeddingRules?: (l.$Typed<FeedPostgate.DisableRule> | l.Unknown$TypedObject)[] | undefined;
324
+ $type: 'app.bsky.actor.defs#postInteractionSettingsPref';
325
+ threadgateAllowRules?: (l.$Typed<FeedThreadgate.MentionRule> | l.$Typed<FeedThreadgate.FollowerRule> | l.$Typed<FeedThreadgate.FollowingRule> | l.$Typed<FeedThreadgate.ListRule> | l.Unknown$TypedObject)[];
326
+ postgateEmbeddingRules?: (l.$Typed<FeedPostgate.DisableRule> | l.Unknown$TypedObject)[];
403
327
  } | {
404
- $type: "app.bsky.actor.defs#verificationPrefs";
405
- hideBadges?: boolean | undefined;
328
+ $type: 'app.bsky.actor.defs#verificationPrefs';
329
+ hideBadges?: boolean;
406
330
  } | {
407
- $type: "app.bsky.actor.defs#liveEventPreferences";
408
- hiddenFeedIds?: string[]
409
- /**
410
- * Whether to hide all feeds from live events.
411
- */
412
- | undefined;
413
- hideAllFeeds?: boolean | undefined;
331
+ $type: 'app.bsky.actor.defs#liveEventPreferences';
332
+ hiddenFeedIds?: string[];
333
+ hideAllFeeds?: boolean;
414
334
  }>>;
415
335
  export { preferences };
416
336
  type AdultContentPref = {
@@ -541,7 +461,7 @@ export { interestsPref };
541
461
  type MutedWordTarget = 'content' | 'tag' | l.UnknownString;
542
462
  export type { MutedWordTarget };
543
463
  declare const mutedWordTarget: l.StringSchema<{
544
- knownValues: ["content", "tag"];
464
+ knownValues: ['content', 'tag'];
545
465
  maxLength: 640;
546
466
  maxGraphemes: 64;
547
467
  }>;