@fedify/fedify 2.0.0-dev.1593 → 2.0.0-dev.160

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/LICENSE +1 -1
  2. package/README.md +66 -30
  3. package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-Ce45JcFg.js} +1 -1
  4. package/dist/{assert_is_error-BPGph1Jx.js → assert_throws-BNXdRGWP.js} +31 -1
  5. package/dist/{builder-BgzJcrpt.js → builder-C9n2ExVv.js} +15 -8
  6. package/dist/chunk-DqRYRqnO.cjs +34 -0
  7. package/dist/client-94iWEfQa.d.cts +222 -0
  8. package/dist/{client-DF8anIB5.d.ts → client-BivSNrEg.d.ts} +3 -75
  9. package/dist/{client-CpxFv8ft.js → client-CgMTXmAD.js} +3 -22
  10. package/dist/compat/mod.cjs +10 -0
  11. package/dist/compat/mod.d.cts +7 -0
  12. package/dist/compat/mod.d.ts +6 -12
  13. package/dist/compat/mod.js +5 -5
  14. package/dist/compat/transformers.test.js +21 -20
  15. package/dist/compat-DmDDELst.cjs +4 -0
  16. package/dist/compat-nxUqe4Z-.js +4 -0
  17. package/dist/context-Bns6uTJq.js +109 -0
  18. package/dist/{context-9gCpIkiz.d.ts → context-CYZ2i00R.d.ts} +321 -129
  19. package/dist/context-D2MrtLch.d.cts +2447 -0
  20. package/dist/deno-B74l3pXN.js +117 -0
  21. package/dist/{testing-D4xRiVJV.js → dist-B5f6a8Tt.js} +90 -111
  22. package/dist/{authdocloader-DJtdyVPc.js → docloader-eucHnjj4.js} +17 -8
  23. package/dist/{esm-5nsZYnVB.js → esm-DGl7uK1r.js} +32 -17
  24. package/dist/federation/builder.test.js +12 -13
  25. package/dist/federation/collection.test.js +6 -9
  26. package/dist/federation/handler.test.js +115 -148
  27. package/dist/federation/idempotency.test.js +202 -0
  28. package/dist/federation/inbox.test.js +5 -6
  29. package/dist/federation/keycache.test.js +4 -5
  30. package/dist/federation/kv.test.js +61 -9
  31. package/dist/federation/middleware.test.js +311 -131
  32. package/dist/federation/mod.cjs +25 -0
  33. package/dist/federation/mod.d.cts +7 -0
  34. package/dist/federation/mod.d.ts +7 -13
  35. package/dist/federation/mod.js +11 -16
  36. package/dist/federation/mq.test.js +9 -10
  37. package/dist/federation/negotiation.test.js +25 -0
  38. package/dist/federation/retry.test.js +2 -4
  39. package/dist/federation/router.test.js +6 -8
  40. package/dist/federation/send.test.js +55 -15
  41. package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +27 -26
  42. package/dist/federation-B431K2gm.cjs +266 -0
  43. package/dist/{federation-CMX7WzeL.js → federation-BbZwNNWj.js} +31 -9
  44. package/dist/http-ClB3pLcL.d.cts +253 -0
  45. package/dist/{http-CQulyTuw.js → http-CrnYJYhM.js} +3 -2
  46. package/dist/{http-BqklewFY.js → http-DJ7KWfiN.js} +374 -14
  47. package/dist/{http-DqSNLFNY.d.ts → http-DLBDPal9.d.ts} +2 -2
  48. package/dist/http-DtRqZZgP.cjs +1222 -0
  49. package/dist/{inbox-B97Wrppe.js → inbox-6-2rtCJf.js} +25 -7
  50. package/dist/{key-D-s3dQbK.js → key-pYEsD-IB.js} +3 -2
  51. package/dist/{keycache-Br0-hsD5.js → keycache-DRxpZ5r9.js} +1 -1
  52. package/dist/{keys-DSk2aqlj.js → keys-ZbcByPg9.js} +2 -1
  53. package/dist/{kv-C7sopW2E.d.ts → kv-CtOmTRNc.d.ts} +30 -1
  54. package/dist/kv-D8q9fLkA.d.cts +110 -0
  55. package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
  56. package/dist/kv-cache-BEeqyGER.js +107 -0
  57. package/dist/kv-cache-Cr66Hw1w.js +122 -0
  58. package/dist/kv-cache-jKJ4ZH0U.cjs +134 -0
  59. package/dist/{ld-CYUQO1l4.js → ld-Bmrvt1KE.js} +4 -2
  60. package/dist/middleware-BUywt3CE.cjs +4242 -0
  61. package/dist/middleware-Ba1Pxx8r.js +26 -0
  62. package/dist/{middleware-tfSiCl9w.js → middleware-ByNAm2-S.js} +272 -271
  63. package/dist/middleware-D6QDOyQU.cjs +12 -0
  64. package/dist/{middleware-CovCqg8w.js → middleware-D9L8QWDP.js} +230 -327
  65. package/dist/middleware-jJYYmbt6.js +12 -0
  66. package/dist/mod-BrS8tiad.d.cts +266 -0
  67. package/dist/mod-C81L6_lQ.d.cts +1 -0
  68. package/dist/mod-CJgbdSqb.d.ts +109 -0
  69. package/dist/mod-CNNTHyBC.d.cts +80 -0
  70. package/dist/mod-CS-MS7gZ.d.cts +62 -0
  71. package/dist/{mod-Bqxcp7eN.d.ts → mod-D_cmv2il.d.ts} +4 -4
  72. package/dist/mod-DcPRcifg.d.cts +107 -0
  73. package/dist/mod-DqFSzJA0.d.ts +64 -0
  74. package/dist/{mod-Drmz72EK.d.ts → mod-jOa7W503.d.ts} +3 -3
  75. package/dist/mod.cjs +55 -0
  76. package/dist/mod.d.cts +11 -0
  77. package/dist/mod.d.ts +11 -17
  78. package/dist/mod.js +15 -21
  79. package/dist/negotiation-5NPJL6zp.js +71 -0
  80. package/dist/nodeinfo/client.test.js +29 -111
  81. package/dist/nodeinfo/handler.test.js +26 -26
  82. package/dist/nodeinfo/mod.cjs +10 -0
  83. package/dist/nodeinfo/mod.d.cts +3 -0
  84. package/dist/nodeinfo/mod.d.ts +3 -5
  85. package/dist/nodeinfo/mod.js +6 -7
  86. package/dist/nodeinfo/types.test.js +7 -15
  87. package/dist/nodeinfo-BlLsRSiT.js +4 -0
  88. package/dist/nodeinfo-DuMYTpbZ.cjs +4 -0
  89. package/dist/otel/exporter.test.js +899 -0
  90. package/dist/otel/mod.cjs +262 -0
  91. package/dist/otel/mod.d.cts +230 -0
  92. package/dist/otel/mod.d.ts +232 -0
  93. package/dist/otel/mod.js +261 -0
  94. package/dist/{owner-CQPnQVtf.d.ts → owner-BgI8C-VY.d.ts} +2 -3
  95. package/dist/owner-C-zfmVAD.d.cts +66 -0
  96. package/dist/{owner-CBeUJR68.js → owner-vFiFLWHR.js} +45 -8
  97. package/dist/{proof-CHQnDg0z.js → proof-C-k7brtD.js} +3 -2
  98. package/dist/proof-CLwK-TXL.cjs +709 -0
  99. package/dist/{proof-D436ezTT.js → proof-Dp6V6HEi.js} +50 -14
  100. package/dist/router-D9eI0s4b.js +118 -0
  101. package/dist/{send-Bc0QdRlp.js → send-BVXXc0Cn.js} +9 -4
  102. package/dist/sig/http.test.js +11 -13
  103. package/dist/sig/key.test.js +9 -11
  104. package/dist/sig/ld.test.js +8 -10
  105. package/dist/sig/mod.cjs +26 -0
  106. package/dist/sig/mod.d.cts +4 -0
  107. package/dist/sig/mod.d.ts +3 -7
  108. package/dist/sig/mod.js +6 -10
  109. package/dist/sig/owner.test.js +33 -12
  110. package/dist/sig/proof.test.js +13 -14
  111. package/dist/sig-CwuONEzF.js +4 -0
  112. package/dist/sig-DeXX2xnj.cjs +4 -0
  113. package/dist/testing/mod.d.ts +180 -6946
  114. package/dist/testing/mod.js +4 -4
  115. package/dist/transformers-BjBg6Lag.cjs +116 -0
  116. package/dist/{transformers-Dna8Fg7k.js → transformers-N_ip_y4P.js} +5 -5
  117. package/dist/{types-BIgY6c-l.js → types-BEdCLHqP.js} +1 -3
  118. package/dist/types-Q-qkJXBV.cjs +315 -0
  119. package/dist/{types-RbpvCErq.js → types-hKTi53FO.js} +8 -169
  120. package/dist/{runtime/authdocloader.test.js → utils/docloader.test.js} +13 -15
  121. package/dist/utils/kv-cache.test.js +211 -0
  122. package/dist/utils/mod.cjs +10 -0
  123. package/dist/utils/mod.d.cts +4 -0
  124. package/dist/utils/mod.d.ts +6 -0
  125. package/dist/utils/mod.js +9 -0
  126. package/dist/utils-Db0ZmjcD.cjs +4 -0
  127. package/dist/utils-Wranxuoe.js +4 -0
  128. package/package.json +69 -55
  129. package/dist/actor-Bj1Vq2XG.js +0 -146
  130. package/dist/actor-C22bXuuC.d.ts +0 -130
  131. package/dist/actor-DNwcqwPT.js +0 -37312
  132. package/dist/assert_throws-BOO88avQ.js +0 -39
  133. package/dist/authdocloader-qkvj_KZY.js +0 -52
  134. package/dist/compat-Bb5myD13.js +0 -4
  135. package/dist/denokv-Bv33Xxea.js +0 -57
  136. package/dist/docloader-9_osWaaH.js +0 -4615
  137. package/dist/docloader-CxWcuWqQ.d.ts +0 -221
  138. package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
  139. package/dist/fixtures/example.com/announce.json +0 -6
  140. package/dist/fixtures/example.com/collection.json +0 -19
  141. package/dist/fixtures/example.com/create.json +0 -6
  142. package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
  143. package/dist/fixtures/example.com/hong-gildong.json +0 -11
  144. package/dist/fixtures/example.com/invite.json +0 -7
  145. package/dist/fixtures/example.com/key.json +0 -7
  146. package/dist/fixtures/example.com/key2.json +0 -6
  147. package/dist/fixtures/example.com/object.json +0 -6
  148. package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
  149. package/dist/fixtures/example.com/paged/a.json +0 -13
  150. package/dist/fixtures/example.com/paged/b.json +0 -16
  151. package/dist/fixtures/example.com/paged-collection.json +0 -6
  152. package/dist/fixtures/example.com/person.json +0 -22
  153. package/dist/fixtures/example.com/person2.json +0 -40
  154. package/dist/fixtures/example.com/test.json +0 -5
  155. package/dist/fixtures/example.com/users/handle.json +0 -16
  156. package/dist/fixtures/example.com/wrong-type.json +0 -3
  157. package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
  158. package/dist/fixtures/remote.domain/users/bob.json +0 -20
  159. package/dist/fixtures/server.example/users/alice.json +0 -20
  160. package/dist/fixtures/w3id.org/identity/v1.json +0 -152
  161. package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
  162. package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
  163. package/dist/fixtures/w3id.org/security/v1.json +0 -50
  164. package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
  165. package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
  166. package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
  167. package/dist/key-3jGPh5To.js +0 -10
  168. package/dist/key-C3CEOTh7.js +0 -10
  169. package/dist/key-CNCeen0u.js +0 -260
  170. package/dist/lookup-BNFlahf3.js +0 -131
  171. package/dist/lookup-CnJK1NUl.js +0 -322
  172. package/dist/middleware-CJbNYdw9.js +0 -17
  173. package/dist/middleware-zDdNBo-m.js +0 -26
  174. package/dist/mod-Cxt4Kpf6.d.ts +0 -291
  175. package/dist/mod-DBzN0aCM.d.ts +0 -115
  176. package/dist/mod-TFoH2Ql8.d.ts +0 -104
  177. package/dist/mod-g0xFzAP9.d.ts +0 -2
  178. package/dist/mq-CRGm1e_F.d.ts +0 -143
  179. package/dist/nodeinfo/semver.test.js +0 -143
  180. package/dist/nodeinfo-CyEbLjHs.js +0 -4
  181. package/dist/runtime/docloader.test.js +0 -522
  182. package/dist/runtime/key.test.js +0 -103
  183. package/dist/runtime/langstr.test.js +0 -39
  184. package/dist/runtime/mod.d.ts +0 -8
  185. package/dist/runtime/mod.js +0 -13
  186. package/dist/runtime/multibase/multibase.test.d.ts +0 -3
  187. package/dist/runtime/multibase/multibase.test.js +0 -358
  188. package/dist/runtime/url.test.d.ts +0 -3
  189. package/dist/runtime/url.test.js +0 -45
  190. package/dist/runtime-BSkOVUWM.js +0 -4
  191. package/dist/semver-dArNLkR9.js +0 -149
  192. package/dist/sig-BXJO--F9.js +0 -4
  193. package/dist/src/vocab/accept.yaml +0 -15
  194. package/dist/src/vocab/activity.yaml +0 -98
  195. package/dist/src/vocab/add.yaml +0 -16
  196. package/dist/src/vocab/announce.yaml +0 -30
  197. package/dist/src/vocab/application.yaml +0 -324
  198. package/dist/src/vocab/arrive.yaml +0 -15
  199. package/dist/src/vocab/article.yaml +0 -46
  200. package/dist/src/vocab/audio.yaml +0 -11
  201. package/dist/src/vocab/block.yaml +0 -16
  202. package/dist/src/vocab/chatmessage.yaml +0 -50
  203. package/dist/src/vocab/collection.yaml +0 -154
  204. package/dist/src/vocab/collectionpage.yaml +0 -55
  205. package/dist/src/vocab/create.yaml +0 -28
  206. package/dist/src/vocab/dataintegrityproof.yaml +0 -56
  207. package/dist/src/vocab/delete.yaml +0 -27
  208. package/dist/src/vocab/didservice.yaml +0 -22
  209. package/dist/src/vocab/dislike.yaml +0 -14
  210. package/dist/src/vocab/document.yaml +0 -31
  211. package/dist/src/vocab/emoji.yaml +0 -12
  212. package/dist/src/vocab/emojireact.yaml +0 -17
  213. package/dist/src/vocab/endpoints.yaml +0 -85
  214. package/dist/src/vocab/event.yaml +0 -11
  215. package/dist/src/vocab/export.yaml +0 -9
  216. package/dist/src/vocab/flag.yaml +0 -15
  217. package/dist/src/vocab/follow.yaml +0 -19
  218. package/dist/src/vocab/group.yaml +0 -324
  219. package/dist/src/vocab/hashtag.yaml +0 -14
  220. package/dist/src/vocab/ignore.yaml +0 -14
  221. package/dist/src/vocab/image.yaml +0 -9
  222. package/dist/src/vocab/intransitiveactivity.yaml +0 -15
  223. package/dist/src/vocab/invite.yaml +0 -14
  224. package/dist/src/vocab/join.yaml +0 -14
  225. package/dist/src/vocab/key.yaml +0 -28
  226. package/dist/src/vocab/leave.yaml +0 -14
  227. package/dist/src/vocab/like.yaml +0 -16
  228. package/dist/src/vocab/link.yaml +0 -101
  229. package/dist/src/vocab/listen.yaml +0 -12
  230. package/dist/src/vocab/mention.yaml +0 -9
  231. package/dist/src/vocab/move.yaml +0 -15
  232. package/dist/src/vocab/multikey.yaml +0 -36
  233. package/dist/src/vocab/note.yaml +0 -48
  234. package/dist/src/vocab/object.yaml +0 -404
  235. package/dist/src/vocab/offer.yaml +0 -15
  236. package/dist/src/vocab/orderedcollection.yaml +0 -39
  237. package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
  238. package/dist/src/vocab/organization.yaml +0 -324
  239. package/dist/src/vocab/page.yaml +0 -11
  240. package/dist/src/vocab/person.yaml +0 -324
  241. package/dist/src/vocab/place.yaml +0 -75
  242. package/dist/src/vocab/profile.yaml +0 -26
  243. package/dist/src/vocab/propertyvalue.yaml +0 -32
  244. package/dist/src/vocab/question.yaml +0 -103
  245. package/dist/src/vocab/read.yaml +0 -13
  246. package/dist/src/vocab/reject.yaml +0 -14
  247. package/dist/src/vocab/relationship.yaml +0 -52
  248. package/dist/src/vocab/remove.yaml +0 -14
  249. package/dist/src/vocab/service.yaml +0 -324
  250. package/dist/src/vocab/source.yaml +0 -26
  251. package/dist/src/vocab/tentativeaccept.yaml +0 -14
  252. package/dist/src/vocab/tentativereject.yaml +0 -14
  253. package/dist/src/vocab/tombstone.yaml +0 -24
  254. package/dist/src/vocab/travel.yaml +0 -16
  255. package/dist/src/vocab/undo.yaml +0 -26
  256. package/dist/src/vocab/update.yaml +0 -58
  257. package/dist/src/vocab/video.yaml +0 -11
  258. package/dist/src/vocab/view.yaml +0 -13
  259. package/dist/testing/docloader.test.js +0 -24
  260. package/dist/type-qs0mWLTm.js +0 -42007
  261. package/dist/vocab/actor.test.d.ts +0 -3
  262. package/dist/vocab/actor.test.js +0 -5965
  263. package/dist/vocab/lookup.test.d.ts +0 -3
  264. package/dist/vocab/lookup.test.js +0 -206
  265. package/dist/vocab/mod.d.ts +0 -8
  266. package/dist/vocab/mod.js +0 -10
  267. package/dist/vocab/schema.yaml +0 -247
  268. package/dist/vocab/type.test.d.ts +0 -3
  269. package/dist/vocab/type.test.js +0 -25
  270. package/dist/vocab/vocab.test.d.ts +0 -3
  271. package/dist/vocab/vocab.test.js +0 -3363
  272. package/dist/vocab-SOE1ifCr.d.ts +0 -14634
  273. package/dist/vocab-r-I1_ZmK.js +0 -246
  274. package/dist/webfinger/handler.test.d.ts +0 -3
  275. package/dist/webfinger/lookup.test.d.ts +0 -3
  276. package/dist/webfinger/lookup.test.js +0 -195
  277. package/dist/webfinger/mod.d.ts +0 -6
  278. package/dist/webfinger/mod.js +0 -9
  279. package/dist/webfinger-C3GIyXIg.js +0 -4
  280. package/dist/x/cfworkers.d.ts +0 -61
  281. package/dist/x/cfworkers.js +0 -98
  282. package/dist/x/cfworkers.test.d.ts +0 -3
  283. package/dist/x/cfworkers.test.js +0 -179
  284. package/dist/x/hono.d.ts +0 -56
  285. package/dist/x/hono.js +0 -60
  286. package/dist/x/sveltekit.d.ts +0 -48
  287. package/dist/x/sveltekit.js +0 -68
  288. /package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals-C80BG-_5.js} +0 -0
  289. /package/dist/{collection-CSzG2j1P.js → collection-CcnIw1qY.js} +0 -0
  290. /package/dist/{nodeinfo/semver.test.d.ts → federation/idempotency.test.d.ts} +0 -0
  291. /package/dist/{runtime/authdocloader.test.d.ts → federation/negotiation.test.d.ts} +0 -0
  292. /package/dist/{runtime/docloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
  293. /package/dist/{mod-1pDWKvUL.d.ts → mod-1E3W847c.d.ts} +0 -0
  294. /package/dist/{runtime/key.test.d.ts → otel/exporter.test.d.ts} +0 -0
  295. /package/dist/{std__assert-X-_kMxKM.js → std__assert-DWivtrGR.js} +0 -0
  296. /package/dist/{testing → utils}/docloader.test.d.ts +0 -0
  297. /package/dist/{runtime/langstr.test.d.ts → utils/kv-cache.test.d.ts} +0 -0
@@ -3,23 +3,28 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, deno_default, getDocumentLoader, getTypeId, kvCache, lookupWebFinger } from "./type-qs0mWLTm.js";
7
- import { getNodeInfo } from "./client-CpxFv8ft.js";
8
- import { RouterError, lookupObject, traverseCollection } from "./lookup-CnJK1NUl.js";
9
- import { nodeInfoToJson } from "./types-BIgY6c-l.js";
10
- import { exportJwk, importJwk, validateCryptoKey } from "./key-D-s3dQbK.js";
11
- import { verifyRequest } from "./http-CQulyTuw.js";
12
- import { getAuthenticatedDocumentLoader } from "./authdocloader-DJtdyVPc.js";
13
- import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-CYUQO1l4.js";
14
- import { doesActorOwnKey, getKeyOwner } from "./owner-CBeUJR68.js";
15
- import { signObject, verifyObject } from "./proof-CHQnDg0z.js";
16
- import { routeActivity } from "./inbox-B97Wrppe.js";
17
- import { FederationBuilderImpl } from "./builder-BgzJcrpt.js";
18
- import { buildCollectionSynchronizationHeader } from "./collection-CSzG2j1P.js";
19
- import { KvKeyCache } from "./keycache-Br0-hsD5.js";
6
+ import { deno_default } from "./deno-B74l3pXN.js";
7
+ import { getNodeInfo } from "./client-CgMTXmAD.js";
8
+ import { RouterError } from "./router-D9eI0s4b.js";
9
+ import { nodeInfoToJson } from "./types-BEdCLHqP.js";
10
+ import { exportJwk, importJwk, validateCryptoKey } from "./key-pYEsD-IB.js";
11
+ import { verifyRequest } from "./http-CrnYJYhM.js";
12
+ import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-Bmrvt1KE.js";
13
+ import { doesActorOwnKey, getKeyOwner } from "./owner-vFiFLWHR.js";
14
+ import { signObject, verifyObject } from "./proof-C-k7brtD.js";
15
+ import { getAuthenticatedDocumentLoader } from "./docloader-eucHnjj4.js";
16
+ import { kvCache } from "./kv-cache-BEeqyGER.js";
17
+ import { routeActivity } from "./inbox-6-2rtCJf.js";
18
+ import { FederationBuilderImpl } from "./builder-C9n2ExVv.js";
19
+ import { buildCollectionSynchronizationHeader } from "./collection-CcnIw1qY.js";
20
+ import { KvKeyCache } from "./keycache-DRxpZ5r9.js";
21
+ import { acceptsJsonLd } from "./negotiation-5NPJL6zp.js";
20
22
  import { createExponentialBackoffPolicy } from "./retry-D4GJ670a.js";
21
- import { extractInboxes, sendActivity } from "./send-Bc0QdRlp.js";
23
+ import { extractInboxes, sendActivity } from "./send-BVXXc0Cn.js";
22
24
  import { getLogger, withContext } from "@logtape/logtape";
25
+ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
26
+ import { getDocumentLoader } from "@fedify/vocab-runtime";
27
+ import { lookupWebFinger } from "@fedify/webfinger";
23
28
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
24
29
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
25
30
  import { domainToASCII } from "node:url";
@@ -60,7 +65,7 @@ function autoIdAssigner(activity, context$1) {
60
65
  * activity like this:
61
66
  *
62
67
  * ```typescript
63
- * import { Follow, Person } from "@fedify/fedify/vocab";
68
+ * import { Follow, Person } from "@fedify/vocab";
64
69
  * const input = new Follow({
65
70
  * id: new URL("http://example.com/activities/1"),
66
71
  * actor: new Person({
@@ -79,7 +84,7 @@ function autoIdAssigner(activity, context$1) {
79
84
  * The result of applying this transformer would be:
80
85
  *
81
86
  * ```typescript
82
- * import { Follow, Person } from "@fedify/fedify/vocab";
87
+ * import { Follow, Person } from "@fedify/vocab";
83
88
  * const output = new Follow({
84
89
  * id: new URL("http://example.com/activities/1"),
85
90
  * actor: new URL("http://example.com/actors/1"),
@@ -152,218 +157,8 @@ function handleNodeInfoJrd(_request, context$1) {
152
157
  return Promise.resolve(response);
153
158
  }
154
159
 
155
- //#endregion
156
- //#region src/vocab/constants.ts
157
- /**
158
- * The special public collection for [public addressing]. *Do not mutate this
159
- * object.*
160
- *
161
- * [public addressing]: https://www.w3.org/TR/activitypub/#public-addressing
162
- *
163
- * @since 0.7.0
164
- */
165
- const PUBLIC_COLLECTION = new URL("https://www.w3.org/ns/activitystreams#Public");
166
-
167
- //#endregion
168
- //#region src/webfinger/handler.ts
169
- const logger = getLogger([
170
- "fedify",
171
- "webfinger",
172
- "server"
173
- ]);
174
- /**
175
- * Handles a WebFinger request. You would not typically call this function
176
- * directly, but instead use {@link Federation.fetch} method.
177
- * @param request The WebFinger request to handle.
178
- * @param parameters The parameters for handling the request.
179
- * @returns The response to the request.
180
- */
181
- async function handleWebFinger(request, options) {
182
- if (options.tracer == null) return await handleWebFingerInternal(request, options);
183
- return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
184
- try {
185
- const response = await handleWebFingerInternal(request, options);
186
- span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
187
- return response;
188
- } catch (error) {
189
- span.setStatus({
190
- code: SpanStatusCode.ERROR,
191
- message: String(error)
192
- });
193
- throw error;
194
- } finally {
195
- span.end();
196
- }
197
- });
198
- }
199
- async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
200
- if (actorDispatcher == null) {
201
- logger.error("Actor dispatcher is not set.");
202
- return await onNotFound(request);
203
- }
204
- const resource = context$1.url.searchParams.get("resource");
205
- if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
206
- span?.setAttribute("webfinger.resource", resource);
207
- let resourceUrl;
208
- try {
209
- resourceUrl = new URL(resource);
210
- } catch (e) {
211
- if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
212
- throw e;
213
- }
214
- span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
215
- async function mapUsernameToIdentifier(username) {
216
- if (actorHandleMapper == null) {
217
- logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
218
- return username;
219
- }
220
- const identifier$1 = await actorHandleMapper(context$1, username);
221
- if (identifier$1 == null) {
222
- logger.error("Actor {username} not found.", { username });
223
- return null;
224
- }
225
- return identifier$1;
226
- }
227
- let identifier = null;
228
- const uriParsed = context$1.parseUri(resourceUrl);
229
- if (uriParsed?.type != "actor") {
230
- const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
231
- if (match == null) {
232
- const result = await actorAliasMapper?.(context$1, resourceUrl);
233
- if (result == null) return await onNotFound(request);
234
- if ("identifier" in result) identifier = result.identifier;
235
- else identifier = await mapUsernameToIdentifier(result.username);
236
- } else {
237
- const portMatch = /:\d+$/.exec(match[2]);
238
- const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
239
- if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
240
- else {
241
- identifier = await mapUsernameToIdentifier(match[1]);
242
- resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
243
- }
244
- }
245
- } else identifier = uriParsed.identifier;
246
- if (identifier == null) return await onNotFound(request);
247
- const actor = await actorDispatcher(context$1, identifier);
248
- if (actor == null) {
249
- logger.error("Actor {identifier} not found.", { identifier });
250
- return await onNotFound(request);
251
- }
252
- const links = [{
253
- rel: "self",
254
- href: context$1.getActorUri(identifier).href,
255
- type: "application/activity+json"
256
- }];
257
- for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
258
- rel: url.rel ?? "http://webfinger.net/rel/profile-page",
259
- href: url.href.href,
260
- type: url.mediaType == null ? void 0 : url.mediaType
261
- });
262
- else if (url instanceof URL) links.push({
263
- rel: "http://webfinger.net/rel/profile-page",
264
- href: url.href
265
- });
266
- for await (const image of actor.getIcons()) {
267
- if (image.url?.href == null) continue;
268
- const link = {
269
- rel: "http://webfinger.net/rel/avatar",
270
- href: image.url.href.toString()
271
- };
272
- if (image.mediaType != null) link.type = image.mediaType;
273
- links.push(link);
274
- }
275
- if (webFingerLinksDispatcher != null) {
276
- const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
277
- if (customLinks != null) for (const link of customLinks) links.push(link);
278
- }
279
- const aliases = [];
280
- if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
281
- aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
282
- if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
283
- }
284
- if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
285
- if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
286
- const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
287
- aliases.push(`acct:${username}@${host}`);
288
- }
289
- const jrd = {
290
- subject: resourceUrl.href,
291
- aliases,
292
- links
293
- };
294
- return new Response(JSON.stringify(jrd), { headers: {
295
- "Content-Type": "application/jrd+json",
296
- "Access-Control-Allow-Origin": "*"
297
- } });
298
- }
299
-
300
- //#endregion
301
- //#region src/federation/negotiation.ts
302
- function compareSpecs(a, b) {
303
- return b.q - a.q || (b.s ?? 0) - (a.s ?? 0) || (a.o ?? 0) - (b.o ?? 0) || a.i - b.i || 0;
304
- }
305
- function isQuality(spec) {
306
- return spec.q > 0;
307
- }
308
- const simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
309
- function splitKeyValuePair(str) {
310
- const [key, value] = str.split("=");
311
- return [key.toLowerCase(), value];
312
- }
313
- function parseMediaType(str, i) {
314
- const match = simpleMediaTypeRegExp.exec(str);
315
- if (!match) return;
316
- const [, type, subtype, parameters] = match;
317
- if (!type || !subtype) return;
318
- const params = Object.create(null);
319
- let q = 1;
320
- if (parameters) {
321
- const kvps = parameters.split(";").map((p) => p.trim()).map(splitKeyValuePair);
322
- for (const [key, val] of kvps) {
323
- const value = val && val[0] === `"` && val[val.length - 1] === `"` ? val.slice(1, val.length - 1) : val;
324
- if (key === "q" && value) {
325
- q = parseFloat(value);
326
- break;
327
- }
328
- params[key] = value;
329
- }
330
- }
331
- return {
332
- type,
333
- subtype,
334
- params,
335
- i,
336
- o: void 0,
337
- q,
338
- s: void 0
339
- };
340
- }
341
- function parseAccept(accept) {
342
- const accepts = accept.split(",").map((p) => p.trim());
343
- const mediaTypes = [];
344
- for (const [index, accept$1] of accepts.entries()) {
345
- const mediaType = parseMediaType(accept$1.trim(), index);
346
- if (mediaType) mediaTypes.push(mediaType);
347
- }
348
- return mediaTypes;
349
- }
350
- function getFullType(spec) {
351
- return `${spec.type}/${spec.subtype}`;
352
- }
353
- function preferredMediaTypes(accept) {
354
- const accepts = parseAccept(accept === void 0 ? "*/*" : accept ?? "");
355
- return accepts.filter(isQuality).sort(compareSpecs).map(getFullType);
356
- }
357
-
358
160
  //#endregion
359
161
  //#region src/federation/handler.ts
360
- function acceptsJsonLd(request) {
361
- const accept = request.headers.get("Accept");
362
- const types = accept ? preferredMediaTypes(accept) : ["*/*"];
363
- if (types == null) return true;
364
- if (types[0] === "text/html" || types[0] === "application/xhtml+xml") return false;
365
- return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
366
- }
367
162
  /**
368
163
  * Handles an actor request.
369
164
  * @template TContextData The context data to pass to the context.
@@ -371,7 +166,7 @@ function acceptsJsonLd(request) {
371
166
  * @param parameters The parameters for handling the actor.
372
167
  * @returns A promise that resolves to an HTTP response.
373
168
  */
374
- async function handleActor(request, { identifier, context: context$1, actorDispatcher, authorizePredicate, onNotFound, onNotAcceptable, onUnauthorized }) {
169
+ async function handleActor(request, { identifier, context: context$1, actorDispatcher, authorizePredicate, onNotFound, onUnauthorized }) {
375
170
  const logger$2 = getLogger([
376
171
  "fedify",
377
172
  "federation",
@@ -386,7 +181,6 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
386
181
  logger$2.debug("Actor {identifier} not found.", { identifier });
387
182
  return await onNotFound(request);
388
183
  }
389
- if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
390
184
  if (authorizePredicate != null) {
391
185
  let key = await context$1.getSignedKey();
392
186
  key = key?.clone({}, { $warning: {
@@ -421,11 +215,10 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
421
215
  * @param parameters The parameters for handling the object.
422
216
  * @returns A promise that resolves to an HTTP response.
423
217
  */
424
- async function handleObject(request, { values, context: context$1, objectDispatcher, authorizePredicate, onNotFound, onNotAcceptable, onUnauthorized }) {
218
+ async function handleObject(request, { values, context: context$1, objectDispatcher, authorizePredicate, onNotFound, onUnauthorized }) {
425
219
  if (objectDispatcher == null) return await onNotFound(request);
426
220
  const object = await objectDispatcher(context$1, values);
427
221
  if (object == null) return await onNotFound(request);
428
- if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
429
222
  if (authorizePredicate != null) {
430
223
  let key = await context$1.getSignedKey();
431
224
  key = key?.clone({}, { $warning: {
@@ -463,7 +256,7 @@ async function handleObject(request, { values, context: context$1, objectDispatc
463
256
  * @param parameters The parameters for handling the collection.
464
257
  * @returns A promise that resolves to an HTTP response.
465
258
  */
466
- async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context: context$1, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound, onNotAcceptable }) {
259
+ async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context: context$1, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
467
260
  const spanName = name.trim().replace(/\s+/g, "_");
468
261
  tracerProvider = tracerProvider ?? trace.getTracerProvider();
469
262
  const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
@@ -576,7 +369,6 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
576
369
  partOf
577
370
  });
578
371
  }
579
- if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
580
372
  if (collectionCallbacks.authorizePredicate != null) {
581
373
  let key = await context$1.getSignedKey();
582
374
  key = key?.clone({}, { $warning: {
@@ -671,7 +463,8 @@ async function handleInbox(request, options) {
671
463
  * @param span The OpenTelemetry span for tracing.
672
464
  * @returns A promise that resolves to an HTTP response.
673
465
  */
674
- async function handleInboxInternal(request, { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider }, span) {
466
+ async function handleInboxInternal(request, parameters, span) {
467
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
675
468
  const logger$2 = getLogger([
676
469
  "fedify",
677
470
  "federation",
@@ -845,6 +638,13 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
845
638
  }
846
639
  if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
847
640
  span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
641
+ span.addEvent("activitypub.activity.received", {
642
+ "activitypub.activity.json": JSON.stringify(json),
643
+ "activitypub.activity.verified": activity != null,
644
+ "ld_signatures.verified": ldSigVerified,
645
+ "http_signatures.verified": httpSigKey != null,
646
+ "http_signatures.key_id": httpSigKey?.id?.href ?? ""
647
+ });
848
648
  if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
849
649
  logger$2.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
850
650
  activity: json,
@@ -873,7 +673,8 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
873
673
  kvPrefixes,
874
674
  queue,
875
675
  span,
876
- tracerProvider
676
+ tracerProvider,
677
+ idempotencyStrategy: parameters.idempotencyStrategy
877
678
  });
878
679
  if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
879
680
  status: 202,
@@ -903,7 +704,7 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
903
704
  /**
904
705
  * Handles a custom collection request.
905
706
  * @template TItem The type of items in the collection.
906
- * @template TParams The parameter names of the requested URL.
707
+ * @template TParam The parameter names of the requested URL.
907
708
  * @template TContext The type of the context, extending {@link RequestContext}.
908
709
  * @template TContextData The context data to pass to the `TContext`.
909
710
  * @param request The HTTP request.
@@ -914,7 +715,6 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
914
715
  const handleCustomCollection = exceptWrapper(_handleCustomCollection);
915
716
  async function _handleCustomCollection(request, { name, values, context: context$1, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
916
717
  verifyDefined(callbacks);
917
- verifyJsonLdRequest(request);
918
718
  await authIfNeeded(context$1, values, callbacks);
919
719
  const cursor = new URL(request.url).searchParams.get("cursor");
920
720
  return await new CustomCollectionHandler(name, values, context$1, callbacks, tracerProvider, Collection, CollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
@@ -922,7 +722,7 @@ async function _handleCustomCollection(request, { name, values, context: context
922
722
  /**
923
723
  * Handles an ordered collection request.
924
724
  * @template TItem The type of items in the collection.
925
- * @template TParams The parameter names of the requested URL.
725
+ * @template TParam The parameter names of the requested URL.
926
726
  * @template TContext The type of the context, extending {@link RequestContext}.
927
727
  * @template TContextData The context data to pass to the `TContext`.
928
728
  * @param request The HTTP request.
@@ -933,7 +733,6 @@ async function _handleCustomCollection(request, { name, values, context: context
933
733
  const handleOrderedCollection = exceptWrapper(_handleOrderedCollection);
934
734
  async function _handleOrderedCollection(request, { name, values, context: context$1, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
935
735
  verifyDefined(callbacks);
936
- verifyJsonLdRequest(request);
937
736
  await authIfNeeded(context$1, values, callbacks);
938
737
  const cursor = new URL(request.url).searchParams.get("cursor");
939
738
  return await new CustomCollectionHandler(name, values, context$1, callbacks, tracerProvider, OrderedCollection, OrderedCollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
@@ -943,7 +742,7 @@ async function _handleOrderedCollection(request, { name, values, context: contex
943
742
  * The main flow is on `getCollection`, `dispatch`.
944
743
  *
945
744
  * @template TItem The type of items in the collection.
946
- * @template TParams The parameter names of the requested URL.
745
+ * @template TParam The parameter names of the requested URL.
947
746
  * @template TContext The type of the context. {@link Context} or {@link RequestContext}.
948
747
  * @template TContextData The context data to pass to the `TContext`.
949
748
  * @template TCollection The type of the collection, extending {@link Collection}.
@@ -977,14 +776,14 @@ var CustomCollectionHandler = class {
977
776
  #collection = null;
978
777
  /**
979
778
  * Creates a new CustomCollection instance.
980
- * @param {string} name The name of the collection.
981
- * @param {TParams} values The parameter values for the collection.
982
- * @param {TContext} context The request context.
983
- * @param {CustomCollectionCallbacks} callbacks The collection callbacks.
984
- * @param {TracerProvider} tracerProvider The tracer provider for telemetry.
985
- * @param {ConstructorWithTypeId<TCollection>} Collection The Collection constructor.
986
- * @param {ConstructorWithTypeId<TCollectionPage>} CollectionPage The CollectionPage constructor.
987
- * @param {(item: TItem) => boolean} filterPredicate Optional filter predicate for items.
779
+ * @param name The name of the collection.
780
+ * @param values The parameter values for the collection.
781
+ * @param context The request context.
782
+ * @param callbacks The collection callbacks.
783
+ * @param tracerProvider The tracer provider for telemetry.
784
+ * @param Collection The Collection constructor.
785
+ * @param CollectionPage The CollectionPage constructor.
786
+ * @param filterPredicate Optional filter predicate for items.
988
787
  */
989
788
  constructor(name, values, context$1, callbacks, tracerProvider = trace.getTracerProvider(), Collection$1, CollectionPage$1, filterPredicate) {
990
789
  this.name = name;
@@ -1109,7 +908,7 @@ var CustomCollectionHandler = class {
1109
908
  /**
1110
909
  * Creates a function to wrap the dispatcher so tracing can be applied.
1111
910
  * @param params Parameters including cursor and total items.
1112
- * @returns {(span: Span) => Promise<PageItems<TItem>>} A function that handles the span operation.
911
+ * @returns A function that handles the span operation.
1113
912
  */
1114
913
  spanPages = ({ totalItems = null, cursor = null }) => async (span) => {
1115
914
  try {
@@ -1130,23 +929,23 @@ var CustomCollectionHandler = class {
1130
929
  };
1131
930
  /**
1132
931
  * Dispatches the collection request to get items.
1133
- * @param {string | null} cursor The cursor for pagination, or null for the first page.
1134
- * @returns {Promise<PageItems<TItem>>} A promise that resolves to the page items.
932
+ * @param cursor The cursor for pagination, or null for the first page.
933
+ * @returns A promise that resolves to the page items.
1135
934
  */
1136
935
  async dispatch(cursor = null) {
1137
936
  return await this.#dispatcher(this.context, this.values, cursor) ?? new ItemsNotFoundError().throw();
1138
937
  }
1139
938
  /**
1140
939
  * Filters the items in the collection.
1141
- * @param {TItem[]} items The items to filter.
1142
- * @returns {(Object | Link | URL)[]} The filtered items.
940
+ * @param items The items to filter.
941
+ * @returns The filtered items.
1143
942
  */
1144
943
  filterItems(items) {
1145
944
  return filterCollectionItems(items, this.name, this.filterPredicate);
1146
945
  }
1147
946
  /**
1148
947
  * Appends a cursor to the URL if it exists.
1149
- * @param {string | null | undefined} cursor The cursor to append, or null/undefined.
948
+ * @param cursor The cursor to append, or null/undefined.
1150
949
  * @returns The URL with cursor appended, or null if cursor is null/undefined.
1151
950
  */
1152
951
  appendToUrl(cursor) {
@@ -1154,8 +953,7 @@ var CustomCollectionHandler = class {
1154
953
  }
1155
954
  /**
1156
955
  * Gets the stored collection or collection page.
1157
- * @returns {Promise<TCollection | TCollectionPage>} A promise that resolves to
1158
- the collection or collection page.
956
+ * @returns A promise that resolves to the collection or collection page.
1159
957
  */
1160
958
  get collection() {
1161
959
  if (this.#collection === null) this.#collection = this.getCollection();
@@ -1163,8 +961,8 @@ var CustomCollectionHandler = class {
1163
961
  }
1164
962
  /**
1165
963
  * Gets the total number of items in the collection.
1166
- * @returns {Promise<number | null>} A promise that
1167
- resolves to the total items count, or null if not available.
964
+ * @returns A promise that resolves to the total items count,
965
+ * or null if not available.
1168
966
  */
1169
967
  get totalItems() {
1170
968
  if (this.#totalItems === void 0) this.totalItems = this.callbacks.counter?.(this.context, this.values);
@@ -1180,8 +978,8 @@ var CustomCollectionHandler = class {
1180
978
  }
1181
979
  /**
1182
980
  * Gets the first cursor for pagination.
1183
- * @returns {Promise<string | null>} A promise that resolves to the first cursor,
1184
- or null if not available.
981
+ * @returns A promise that resolves to the first cursor,
982
+ * or null if not available.
1185
983
  */
1186
984
  get firstCursor() {
1187
985
  const cursor = this.callbacks.firstCursor?.(this.context, this.values);
@@ -1211,10 +1009,9 @@ function exceptWrapper(handler) {
1211
1009
  try {
1212
1010
  return await handler(request, handlerParams);
1213
1011
  } catch (error) {
1214
- const { onNotFound, onNotAcceptable, onUnauthorized } = handlerParams;
1012
+ const { onNotFound, onUnauthorized } = handlerParams;
1215
1013
  switch (error?.constructor) {
1216
1014
  case ItemsNotFoundError: return await onNotFound(request);
1217
- case NotAcceptableError: return await onNotAcceptable(request);
1218
1015
  case UnauthorizedError: return await onUnauthorized(request);
1219
1016
  default: throw error;
1220
1017
  }
@@ -1232,15 +1029,6 @@ const verifyDefined = (callbacks) => {
1232
1029
  if (callbacks === void 0) throw new ItemsNotFoundError();
1233
1030
  };
1234
1031
  /**
1235
- * Verifies that a request accepts JSON-LD content type.
1236
- * @param request The HTTP request to verify.
1237
- * @throws {NotAcceptableError} If the request doesn't accept JSON-LD.
1238
- * @since 1.8.0
1239
- */
1240
- const verifyJsonLdRequest = (request) => {
1241
- if (!acceptsJsonLd(request)) throw new NotAcceptableError();
1242
- };
1243
- /**
1244
1032
  * Performs authorization if needed based on the authorization predicate.
1245
1033
  * @template TContextData The context data type.
1246
1034
  * @param {RequestContext<TContextData>} context The request context.
@@ -1324,15 +1112,6 @@ var ItemsNotFoundError = class extends HandlerError {
1324
1112
  }
1325
1113
  };
1326
1114
  /**
1327
- * Error thrown when the request is not acceptable (e.g., wrong content type).
1328
- * @since 1.8.0
1329
- */
1330
- var NotAcceptableError = class extends HandlerError {
1331
- constructor() {
1332
- super("The request is not acceptable.");
1333
- }
1334
- };
1335
- /**
1336
1115
  * Error thrown when access to a collection is unauthorized.
1337
1116
  * @since 1.8.0
1338
1117
  */
@@ -1368,6 +1147,139 @@ async function respondWithObjectIfAcceptable(object, request, options) {
1368
1147
  return response;
1369
1148
  }
1370
1149
 
1150
+ //#endregion
1151
+ //#region src/federation/webfinger.ts
1152
+ const logger = getLogger([
1153
+ "fedify",
1154
+ "webfinger",
1155
+ "server"
1156
+ ]);
1157
+ /**
1158
+ * Handles a WebFinger request. You would not typically call this function
1159
+ * directly, but instead use {@link Federation.fetch} method.
1160
+ * @param request The WebFinger request to handle.
1161
+ * @param parameters The parameters for handling the request.
1162
+ * @returns The response to the request.
1163
+ */
1164
+ async function handleWebFinger(request, options) {
1165
+ if (options.tracer == null) return await handleWebFingerInternal(request, options);
1166
+ return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
1167
+ try {
1168
+ const response = await handleWebFingerInternal(request, options);
1169
+ span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
1170
+ return response;
1171
+ } catch (error) {
1172
+ span.setStatus({
1173
+ code: SpanStatusCode.ERROR,
1174
+ message: String(error)
1175
+ });
1176
+ throw error;
1177
+ } finally {
1178
+ span.end();
1179
+ }
1180
+ });
1181
+ }
1182
+ async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
1183
+ if (actorDispatcher == null) {
1184
+ logger.error("Actor dispatcher is not set.");
1185
+ return await onNotFound(request);
1186
+ }
1187
+ const resource = context$1.url.searchParams.get("resource");
1188
+ if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
1189
+ span?.setAttribute("webfinger.resource", resource);
1190
+ let resourceUrl;
1191
+ try {
1192
+ resourceUrl = new URL(resource);
1193
+ } catch (e) {
1194
+ if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
1195
+ throw e;
1196
+ }
1197
+ span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
1198
+ async function mapUsernameToIdentifier(username) {
1199
+ if (actorHandleMapper == null) {
1200
+ logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
1201
+ return username;
1202
+ }
1203
+ const identifier$1 = await actorHandleMapper(context$1, username);
1204
+ if (identifier$1 == null) {
1205
+ logger.error("Actor {username} not found.", { username });
1206
+ return null;
1207
+ }
1208
+ return identifier$1;
1209
+ }
1210
+ let identifier = null;
1211
+ const uriParsed = context$1.parseUri(resourceUrl);
1212
+ if (uriParsed?.type != "actor") {
1213
+ const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
1214
+ if (match == null) {
1215
+ const result = await actorAliasMapper?.(context$1, resourceUrl);
1216
+ if (result == null) return await onNotFound(request);
1217
+ if ("identifier" in result) identifier = result.identifier;
1218
+ else identifier = await mapUsernameToIdentifier(result.username);
1219
+ } else {
1220
+ const portMatch = /:\d+$/.exec(match[2]);
1221
+ const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
1222
+ if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
1223
+ else {
1224
+ identifier = await mapUsernameToIdentifier(match[1]);
1225
+ resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
1226
+ }
1227
+ }
1228
+ } else identifier = uriParsed.identifier;
1229
+ if (identifier == null) return await onNotFound(request);
1230
+ const actor = await actorDispatcher(context$1, identifier);
1231
+ if (actor == null) {
1232
+ logger.error("Actor {identifier} not found.", { identifier });
1233
+ return await onNotFound(request);
1234
+ }
1235
+ const links = [{
1236
+ rel: "self",
1237
+ href: context$1.getActorUri(identifier).href,
1238
+ type: "application/activity+json"
1239
+ }];
1240
+ for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
1241
+ rel: url.rel ?? "http://webfinger.net/rel/profile-page",
1242
+ href: url.href.href,
1243
+ type: url.mediaType == null ? void 0 : url.mediaType
1244
+ });
1245
+ else if (url instanceof URL) links.push({
1246
+ rel: "http://webfinger.net/rel/profile-page",
1247
+ href: url.href
1248
+ });
1249
+ for await (const image of actor.getIcons()) {
1250
+ if (image.url?.href == null) continue;
1251
+ const link = {
1252
+ rel: "http://webfinger.net/rel/avatar",
1253
+ href: image.url.href.toString()
1254
+ };
1255
+ if (image.mediaType != null) link.type = image.mediaType;
1256
+ links.push(link);
1257
+ }
1258
+ if (webFingerLinksDispatcher != null) {
1259
+ const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
1260
+ if (customLinks != null) for (const link of customLinks) links.push(link);
1261
+ }
1262
+ const aliases = [];
1263
+ if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
1264
+ aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
1265
+ if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
1266
+ }
1267
+ if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
1268
+ if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
1269
+ const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
1270
+ aliases.push(`acct:${username}@${host}`);
1271
+ }
1272
+ const jrd = {
1273
+ subject: resourceUrl.href,
1274
+ aliases,
1275
+ links
1276
+ };
1277
+ return new Response(JSON.stringify(jrd), { headers: {
1278
+ "Content-Type": "application/jrd+json",
1279
+ "Access-Control-Allow-Origin": "*"
1280
+ } });
1281
+ }
1282
+
1371
1283
  //#endregion
1372
1284
  //#region src/federation/middleware.ts
1373
1285
  /**
@@ -1405,7 +1317,6 @@ var FederationImpl = class extends FederationBuilderImpl {
1405
1317
  firstKnock;
1406
1318
  constructor(options) {
1407
1319
  super();
1408
- const logger$2 = getLogger(["fedify", "federation"]);
1409
1320
  this.kv = options.kv;
1410
1321
  this.kvPrefixes = {
1411
1322
  activityIdempotence: ["_fedify", "activityIdempotence"],
@@ -1453,8 +1364,9 @@ var FederationImpl = class extends FederationBuilderImpl {
1453
1364
  this.router.trailingSlashInsensitive = options.trailingSlashInsensitive ?? false;
1454
1365
  this._initializeRouter();
1455
1366
  if (options.allowPrivateAddress || options.userAgent != null) {
1456
- if (options.contextLoader != null) throw new TypeError("Cannot set contextLoader with allowPrivateAddress or userAgent options.");
1457
- else if (options.authenticatedDocumentLoaderFactory != null) throw new TypeError("Cannot set authenticatedDocumentLoaderFactory with allowPrivateAddress or userAgent options.");
1367
+ if (options.documentLoaderFactory != null) throw new TypeError("Cannot set documentLoaderFactory with allowPrivateAddress or userAgent options.");
1368
+ if (options.contextLoaderFactory != null) throw new TypeError("Cannot set contextLoaderFactory with allowPrivateAddress or userAgent options.");
1369
+ if (options.authenticatedDocumentLoaderFactory != null) throw new TypeError("Cannot set authenticatedDocumentLoaderFactory with allowPrivateAddress or userAgent options.");
1458
1370
  }
1459
1371
  const { allowPrivateAddress, userAgent } = options;
1460
1372
  this.allowPrivateAddress = allowPrivateAddress ?? false;
@@ -1468,11 +1380,7 @@ var FederationImpl = class extends FederationBuilderImpl {
1468
1380
  prefix: this.kvPrefixes.remoteDocument
1469
1381
  });
1470
1382
  });
1471
- if (options.contextLoader != null) {
1472
- if (options.contextLoaderFactory != null) throw new TypeError("Cannot set both contextLoader and contextLoaderFactory options at a time; use contextLoaderFactory only.");
1473
- this.contextLoaderFactory = () => options.contextLoader;
1474
- logger$2.warn("The contextLoader option is deprecated; use contextLoaderFactory option instead.");
1475
- } else this.contextLoaderFactory = options.contextLoaderFactory ?? this.documentLoaderFactory;
1383
+ this.contextLoaderFactory = options.contextLoaderFactory ?? this.documentLoaderFactory;
1476
1384
  this.authenticatedDocumentLoaderFactory = options.authenticatedDocumentLoaderFactory ?? ((identity) => getAuthenticatedDocumentLoader(identity, {
1477
1385
  allowPrivateAddress,
1478
1386
  userAgent,
@@ -2011,6 +1919,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2011
1919
  span,
2012
1920
  tracer
2013
1921
  });
1922
+ if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
2014
1923
  } catch (error) {
2015
1924
  span.setStatus({
2016
1925
  code: SpanStatusCode.ERROR,
@@ -2074,6 +1983,9 @@ var FederationImpl = class extends FederationBuilderImpl {
2074
1983
  context: context$1,
2075
1984
  nodeInfoDispatcher: this.nodeInfoDispatcher
2076
1985
  });
1986
+ }
1987
+ if (request.method !== "POST" && !acceptsJsonLd(request)) return await onNotAcceptable(request);
1988
+ switch (routeName) {
2077
1989
  case "actor":
2078
1990
  context$1 = this.#createContext(request, contextData, { invokedFromActorDispatcher: { identifier: route.values.identifier ?? route.values.handle } });
2079
1991
  return await handleActor(request, {
@@ -2082,8 +1994,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2082
1994
  actorDispatcher: this.actorCallbacks?.dispatcher,
2083
1995
  authorizePredicate: this.actorCallbacks?.authorizePredicate,
2084
1996
  onUnauthorized,
2085
- onNotFound,
2086
- onNotAcceptable
1997
+ onNotFound
2087
1998
  });
2088
1999
  case "object": {
2089
2000
  const typeId = route.name.replace(/^object:/, "");
@@ -2099,8 +2010,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2099
2010
  objectDispatcher: callbacks?.dispatcher,
2100
2011
  authorizePredicate: callbacks?.authorizePredicate,
2101
2012
  onUnauthorized,
2102
- onNotFound,
2103
- onNotAcceptable
2013
+ onNotFound
2104
2014
  });
2105
2015
  }
2106
2016
  case "outbox": return await handleCollection(request, {
@@ -2111,8 +2021,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2111
2021
  collectionCallbacks: this.outboxCallbacks,
2112
2022
  tracerProvider: this.tracerProvider,
2113
2023
  onUnauthorized,
2114
- onNotFound,
2115
- onNotAcceptable
2024
+ onNotFound
2116
2025
  });
2117
2026
  case "inbox":
2118
2027
  if (request.method !== "POST") return await handleCollection(request, {
@@ -2123,8 +2032,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2123
2032
  collectionCallbacks: this.inboxCallbacks,
2124
2033
  tracerProvider: this.tracerProvider,
2125
2034
  onUnauthorized,
2126
- onNotFound,
2127
- onNotAcceptable
2035
+ onNotFound
2128
2036
  });
2129
2037
  context$1 = this.#createContext(request, contextData, { documentLoader: await context$1.getDocumentLoader({ identifier: route.values.identifier ?? route.values.handle }) });
2130
2038
  case "sharedInbox":
@@ -2146,7 +2054,8 @@ var FederationImpl = class extends FederationBuilderImpl {
2146
2054
  onNotFound,
2147
2055
  signatureTimeWindow: this.signatureTimeWindow,
2148
2056
  skipSignatureVerification: this.skipSignatureVerification,
2149
- tracerProvider: this.tracerProvider
2057
+ tracerProvider: this.tracerProvider,
2058
+ idempotencyStrategy: this.idempotencyStrategy
2150
2059
  });
2151
2060
  case "following": return await handleCollection(request, {
2152
2061
  name: "following",
@@ -2156,8 +2065,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2156
2065
  collectionCallbacks: this.followingCallbacks,
2157
2066
  tracerProvider: this.tracerProvider,
2158
2067
  onUnauthorized,
2159
- onNotFound,
2160
- onNotAcceptable
2068
+ onNotFound
2161
2069
  });
2162
2070
  case "followers": {
2163
2071
  let baseUrl = url.searchParams.get("base-url");
@@ -2180,8 +2088,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2180
2088
  collectionCallbacks: this.followersCallbacks,
2181
2089
  tracerProvider: this.tracerProvider,
2182
2090
  onUnauthorized,
2183
- onNotFound,
2184
- onNotAcceptable
2091
+ onNotFound
2185
2092
  });
2186
2093
  }
2187
2094
  case "liked": return await handleCollection(request, {
@@ -2192,8 +2099,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2192
2099
  collectionCallbacks: this.likedCallbacks,
2193
2100
  tracerProvider: this.tracerProvider,
2194
2101
  onUnauthorized,
2195
- onNotFound,
2196
- onNotAcceptable
2102
+ onNotFound
2197
2103
  });
2198
2104
  case "featured": return await handleCollection(request, {
2199
2105
  name: "featured",
@@ -2203,8 +2109,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2203
2109
  collectionCallbacks: this.featuredCallbacks,
2204
2110
  tracerProvider: this.tracerProvider,
2205
2111
  onUnauthorized,
2206
- onNotFound,
2207
- onNotAcceptable
2112
+ onNotFound
2208
2113
  });
2209
2114
  case "featuredTags": return await handleCollection(request, {
2210
2115
  name: "featured tags",
@@ -2214,8 +2119,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2214
2119
  collectionCallbacks: this.featuredTagsCallbacks,
2215
2120
  tracerProvider: this.tracerProvider,
2216
2121
  onUnauthorized,
2217
- onNotFound,
2218
- onNotAcceptable
2122
+ onNotFound
2219
2123
  });
2220
2124
  case "collection": {
2221
2125
  const name = route.name.replace(/^collection:/, "");
@@ -2227,8 +2131,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2227
2131
  collectionCallbacks: callbacks,
2228
2132
  tracerProvider: this.tracerProvider,
2229
2133
  onUnauthorized,
2230
- onNotFound,
2231
- onNotAcceptable
2134
+ onNotFound
2232
2135
  });
2233
2136
  }
2234
2137
  case "orderedCollection": {
@@ -2241,8 +2144,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2241
2144
  collectionCallbacks: callbacks,
2242
2145
  tracerProvider: this.tracerProvider,
2243
2146
  onUnauthorized,
2244
- onNotFound,
2245
- onNotAcceptable
2147
+ onNotFound
2246
2148
  });
2247
2149
  }
2248
2150
  default: {
@@ -2537,15 +2439,16 @@ var ContextImpl = class ContextImpl {
2537
2439
  "actor"
2538
2440
  ]);
2539
2441
  if (this.federation.actorCallbacks?.keyPairsDispatcher == null) throw new Error("No actor key pairs dispatcher registered.");
2540
- const path = this.federation.router.build("actor", {
2541
- identifier,
2542
- handle: identifier
2543
- });
2544
- if (path == null) {
2545
- logger$2.warn("No actor dispatcher registered.");
2546
- return [];
2442
+ let actorUri;
2443
+ try {
2444
+ actorUri = this.getActorUri(identifier);
2445
+ } catch (error) {
2446
+ if (error instanceof RouterError) {
2447
+ logger$2.warn(error.message);
2448
+ return [];
2449
+ }
2450
+ throw error;
2547
2451
  }
2548
- const actorUri = new URL(path, this.canonicalOrigin);
2549
2452
  const keyPairs = await this.federation.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
2550
2453
  ...this,
2551
2454
  invokedFromActorKeyPairsDispatcher: { identifier }
@@ -2706,12 +2609,11 @@ var ContextImpl = class ContextImpl {
2706
2609
  if (identifier == null) throw new Error("If recipients is \"followers\", sender must be an actor identifier or username.");
2707
2610
  expandedRecipients = [];
2708
2611
  for await (const recipient of this.getFollowers(identifier)) expandedRecipients.push(recipient);
2709
- if (options.syncCollection) {
2710
- const collectionId = this.federation.router.build("followers", {
2711
- identifier,
2712
- handle: identifier
2713
- });
2714
- opts.collectionSync = collectionId == null ? void 0 : new URL(collectionId, this.canonicalOrigin).href;
2612
+ if (options.syncCollection) try {
2613
+ opts.collectionSync = this.getFollowersUri(identifier).href;
2614
+ } catch (error) {
2615
+ if (error instanceof RouterError) opts.collectionSync = void 0;
2616
+ else throw error;
2715
2617
  }
2716
2618
  } else expandedRecipients = [recipients];
2717
2619
  span.setAttribute("activitypub.inboxes", expandedRecipients.length);
@@ -2896,7 +2798,8 @@ var ContextImpl = class ContextImpl {
2896
2798
  kvPrefixes: this.federation.kvPrefixes,
2897
2799
  queue: this.federation.inboxQueue,
2898
2800
  span,
2899
- tracerProvider: options.tracerProvider ?? this.tracerProvider
2801
+ tracerProvider: options.tracerProvider ?? this.tracerProvider,
2802
+ idempotencyStrategy: this.federation.idempotencyStrategy
2900
2803
  });
2901
2804
  return routeResult === "alreadyProcessed" || routeResult === "enqueued" || routeResult === "unsupportedActivity" || routeResult === "success";
2902
2805
  }
@@ -3210,4 +3113,4 @@ function getRequestId(request) {
3210
3113
  }
3211
3114
 
3212
3115
  //#endregion
3213
- export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, acceptsJsonLd, actorDehydrator, autoIdAssigner, createFederation, handleActor, handleCollection, handleCustomCollection, handleInbox, handleNodeInfo, handleNodeInfoJrd, handleObject, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };
3116
+ export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, actorDehydrator, autoIdAssigner, createFederation, handleActor, handleCollection, handleCustomCollection, handleInbox, handleNodeInfo, handleNodeInfoJrd, handleObject, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };