@fedify/fedify 2.0.0-pr.490.2 → 2.0.0-pr.559.4
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.
- package/LICENSE +1 -1
- package/README.md +64 -37
- package/dist/{builder-4syLV1-z.js → builder-DTlQwmVF.js} +10 -3
- package/dist/{client-BsGzbnV-.d.ts → client-CUTUGgvJ.d.ts} +18 -18
- package/dist/{client-pY7-3icS.js → client-Dg7OfUDA.js} +28 -23
- package/dist/{client-94iWEfQa.d.cts → client-by-PEGAJ.d.cts} +18 -18
- package/dist/compat/mod.cjs +1 -1
- package/dist/compat/mod.d.cts +6 -10
- package/dist/compat/mod.d.ts +6 -10
- package/dist/compat/mod.js +1 -1
- package/dist/compat/transformers.test.js +22 -21
- package/dist/{context-PxGADCsD.d.cts → context-B6X-7loD.d.cts} +206 -74
- package/dist/{context-V-XS2_6O.d.ts → context-CJaICYPw.d.ts} +206 -74
- package/dist/context-CZ5llAss.js +109 -0
- package/dist/deno-DGx1JZHr.js +124 -0
- package/dist/{testing-BslrM_9E.js → dist-B5f6a8Tt.js} +90 -110
- package/dist/{docloader-DndkGj0O.js → docloader-D8UHsyqD.js} +3 -3
- package/dist/{esm-VlKMJQqV.js → esm-DGl7uK1r.js} +1 -1
- package/dist/federation/builder.test.js +7 -5
- package/dist/federation/collection.test.js +2 -3
- package/dist/federation/handler.test.js +24 -23
- package/dist/federation/idempotency.test.js +59 -22
- package/dist/federation/inbox.test.js +4 -3
- package/dist/federation/keycache.test.js +4 -4
- package/dist/federation/kv.test.js +56 -3
- package/dist/federation/middleware.test.js +307 -93
- package/dist/federation/mod.cjs +9 -10
- package/dist/federation/mod.d.cts +7 -11
- package/dist/federation/mod.d.ts +7 -11
- package/dist/federation/mod.js +8 -11
- package/dist/federation/mq.test.js +167 -16
- package/dist/federation/negotiation.test.js +2 -3
- package/dist/federation/retry.test.js +2 -3
- package/dist/federation/router.test.js +2 -2
- package/dist/federation/send.test.js +93 -11
- package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +24 -22
- package/dist/{federation-CRpdnOMS.cjs → federation-CE0CJ_0G.cjs} +116 -10
- package/dist/{federation-jcR8-ZxP.js → federation-D6FVaeAR.js} +122 -16
- package/dist/{http-YhR_TMMQ.js → http-CL3G0rnf.js} +126 -9
- package/dist/{http-M8k5mKc0.d.cts → http-ClB3pLcL.d.cts} +1 -1
- package/dist/{http-Dxpqz4hE.cjs → http-DKBUv5zZ.cjs} +139 -16
- package/dist/{http-BbO0ejuk.d.ts → http-DLBDPal9.d.ts} +1 -1
- package/dist/{http-DH47B-h3.js → http-LGtYlSfN.js} +3 -2
- package/dist/{inbox-CEyHvxOo.js → inbox-DbtWQY2D.js} +2 -1
- package/dist/{key-x7E5PYI0.js → key-BCtt1Ugy.js} +3 -3
- package/dist/{keycache-BRXuBDuy.js → keycache-DRxpZ5r9.js} +1 -1
- package/dist/{keys-DLk_8H-l.js → keys-ZbcByPg9.js} +1 -1
- package/dist/{kv-Bxr0Q87_.d.cts → kv-B4vFhIYL.d.cts} +30 -1
- package/dist/{kv-BKNZ-Tb-.d.ts → kv-CYySNrsn.d.ts} +30 -1
- package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
- package/dist/{kv-cache-HFnFIjSD.js → kv-cache-0786BfqY.js} +3 -3
- package/dist/{kv-cache-DN9pfMBe.js → kv-cache-B__dHl7g.js} +15 -2
- package/dist/{kv-cache-BMpfJFTx.cjs → kv-cache-DCJojeTn.cjs} +3 -3
- package/dist/{ld-CRPaU6c8.js → ld-QlZPwGEH.js} +4 -3
- package/dist/middleware-B3jUPnDa.js +12 -0
- package/dist/middleware-BFiwWMA2.cjs +12 -0
- package/dist/middleware-DMx6DyIw.js +26 -0
- package/dist/{middleware-DfLpMu7C.js → middleware-Dm58nObp.js} +280 -166
- package/dist/{middleware-BIqFwRwI.js → middleware-WokE4qxc.js} +245 -178
- package/dist/{middleware-Ck7O6mb0.cjs → middleware-hWyKOO_6.cjs} +332 -206
- package/dist/{mod-DMpuiKXi.d.cts → mod-BHXq4Q3x.d.cts} +7 -7
- package/dist/{mod-DgxG-byT.d.cts → mod-BrS8tiad.d.cts} +2 -2
- package/dist/mod-CoMP50Rf.d.ts +64 -0
- package/dist/{mod-BoRKfJPE.d.cts → mod-DScazwCW.d.cts} +4 -4
- package/dist/mod-DTzN6Pv3.d.cts +62 -0
- package/dist/{mod-aAE2wOWV.d.ts → mod-DZmuPaKv.d.ts} +7 -7
- package/dist/{mod-D5Z2tISD.d.ts → mod-jOa7W503.d.ts} +2 -2
- package/dist/{mod-Cdo6SYlJ.d.ts → mod-xKJ57rwu.d.ts} +4 -4
- package/dist/mod.cjs +12 -93
- package/dist/mod.d.cts +11 -15
- package/dist/mod.d.ts +11 -15
- package/dist/mod.js +11 -15
- package/dist/nodeinfo/client.test.js +3 -4
- package/dist/nodeinfo/handler.test.js +22 -21
- package/dist/nodeinfo/mod.cjs +2 -2
- package/dist/nodeinfo/mod.d.cts +2 -2
- package/dist/nodeinfo/mod.d.ts +2 -2
- package/dist/nodeinfo/mod.js +2 -2
- package/dist/nodeinfo/types.test.js +2 -3
- package/dist/otel/exporter.test.js +893 -0
- package/dist/otel/mod.cjs +256 -0
- package/dist/otel/mod.d.cts +230 -0
- package/dist/otel/mod.d.ts +232 -0
- package/dist/otel/mod.js +255 -0
- package/dist/{owner-kQRGVXG1.d.ts → owner-BgI8C-VY.d.ts} +1 -2
- package/dist/{owner-B4HbyP8s.d.cts → owner-C-zfmVAD.d.cts} +1 -2
- package/dist/{owner-CIWnopkT.js → owner-Cejm-F7S.js} +2 -2
- package/dist/{proof-D-5ri6rf.js → proof-BOQBHd-i.js} +3 -2
- package/dist/{proof-fEwcA7LA.cjs → proof-Bmi8ZIcW.cjs} +24 -25
- package/dist/{proof-C8-2l0zH.js → proof-CnaEQ_Ev.js} +4 -5
- package/dist/router-D9eI0s4b.js +118 -0
- package/dist/{send-CPGk9QKZ.js → send-jFxXfsN8.js} +38 -4
- package/dist/sig/http.test.js +6 -7
- package/dist/sig/key.test.js +5 -5
- package/dist/sig/ld.test.js +6 -6
- package/dist/sig/mod.cjs +3 -5
- package/dist/sig/mod.d.cts +3 -5
- package/dist/sig/mod.d.ts +3 -5
- package/dist/sig/mod.js +3 -5
- package/dist/sig/owner.test.js +6 -7
- package/dist/sig/proof.test.js +6 -6
- package/dist/testing/mod.d.ts +173 -7006
- package/dist/testing/mod.js +4 -3
- package/dist/{transformers-CoBS-oFG.cjs → transformers-BjBg6Lag.cjs} +2 -2
- package/dist/{transformers-BFT6d7J5.js → transformers-N_ip_y4P.js} +2 -2
- package/dist/{types-BtUjyi5y.js → types-8l28uC8o.js} +30 -25
- package/dist/{types-CWgzGaqk.cjs → types-B6z6CqIz.cjs} +30 -25
- package/dist/{types-C2XVl6gj.js → types-CPz01LGH.js} +3 -3
- package/dist/utils/docloader.test.js +7 -8
- package/dist/utils/kv-cache.test.js +5 -3
- package/dist/utils/mod.cjs +3 -5
- package/dist/utils/mod.d.cts +3 -4
- package/dist/utils/mod.d.ts +3 -4
- package/dist/utils/mod.js +3 -5
- package/dist/vocab/mod.cjs +8 -81
- package/dist/vocab/mod.d.cts +1 -4
- package/dist/vocab/mod.d.ts +1 -4
- package/dist/vocab/mod.js +1 -5
- package/package.json +27 -27
- package/dist/actor-BT-e5fn9.js +0 -146
- package/dist/actor-B_gRMloq.js +0 -41647
- package/dist/actor-CBfPjuWj.cjs +0 -42079
- package/dist/actor-DqFajh9s.d.ts +0 -130
- package/dist/actor-f2NtjyCg.d.cts +0 -128
- package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
- package/dist/fixtures/example.com/announce.json +0 -6
- package/dist/fixtures/example.com/collection.json +0 -19
- package/dist/fixtures/example.com/create.json +0 -6
- package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
- package/dist/fixtures/example.com/hong-gildong.json +0 -11
- package/dist/fixtures/example.com/invite.json +0 -7
- package/dist/fixtures/example.com/key.json +0 -7
- package/dist/fixtures/example.com/key2.json +0 -6
- package/dist/fixtures/example.com/object.json +0 -6
- package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
- package/dist/fixtures/example.com/paged/a.json +0 -13
- package/dist/fixtures/example.com/paged/b.json +0 -16
- package/dist/fixtures/example.com/paged-collection.json +0 -6
- package/dist/fixtures/example.com/person.json +0 -22
- package/dist/fixtures/example.com/person2.json +0 -40
- package/dist/fixtures/example.com/test.json +0 -5
- package/dist/fixtures/example.com/users/handle.json +0 -16
- package/dist/fixtures/example.com/wrong-type.json +0 -3
- package/dist/fixtures/media.example.com/avatars/test-avatar.jpg.json +0 -6
- package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
- package/dist/fixtures/remote.domain/users/bob.json +0 -20
- package/dist/fixtures/server.example/users/alice.json +0 -20
- package/dist/fixtures/w3id.org/identity/v1.json +0 -152
- package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
- package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
- package/dist/fixtures/w3id.org/security/v1.json +0 -50
- package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
- package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
- package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
- package/dist/lookup-BTqtVATt.cjs +0 -266
- package/dist/lookup-DOSnR912.js +0 -254
- package/dist/lookup-Dj9-mgOn.js +0 -42184
- package/dist/middleware-CxswDtQn.js +0 -15
- package/dist/middleware-CyITsnX0.js +0 -26
- package/dist/middleware-Z8lc_drL.cjs +0 -15
- package/dist/mod-BlVovdcy.d.ts +0 -309
- package/dist/mod-BxRCHTz-.d.cts +0 -307
- package/dist/mod-C58MZ7Wx.d.cts +0 -113
- package/dist/mod-CcDPcLJW.d.cts +0 -1
- package/dist/mod-Ds0mpFZU.d.ts +0 -115
- package/dist/mod-bjzj5QIb.d.ts +0 -2
- package/dist/otel-1BmGPuZc.js +0 -64
- package/dist/src/vocab/accept.yaml +0 -15
- package/dist/src/vocab/activity.yaml +0 -98
- package/dist/src/vocab/add.yaml +0 -16
- package/dist/src/vocab/announce.yaml +0 -30
- package/dist/src/vocab/application.yaml +0 -324
- package/dist/src/vocab/arrive.yaml +0 -15
- package/dist/src/vocab/article.yaml +0 -46
- package/dist/src/vocab/audio.yaml +0 -11
- package/dist/src/vocab/block.yaml +0 -16
- package/dist/src/vocab/chatmessage.yaml +0 -50
- package/dist/src/vocab/collection.yaml +0 -154
- package/dist/src/vocab/collectionpage.yaml +0 -55
- package/dist/src/vocab/create.yaml +0 -28
- package/dist/src/vocab/dataintegrityproof.yaml +0 -56
- package/dist/src/vocab/delete.yaml +0 -27
- package/dist/src/vocab/didservice.yaml +0 -22
- package/dist/src/vocab/dislike.yaml +0 -14
- package/dist/src/vocab/document.yaml +0 -31
- package/dist/src/vocab/emoji.yaml +0 -12
- package/dist/src/vocab/emojireact.yaml +0 -17
- package/dist/src/vocab/endpoints.yaml +0 -85
- package/dist/src/vocab/event.yaml +0 -11
- package/dist/src/vocab/export.yaml +0 -9
- package/dist/src/vocab/flag.yaml +0 -15
- package/dist/src/vocab/follow.yaml +0 -19
- package/dist/src/vocab/group.yaml +0 -324
- package/dist/src/vocab/hashtag.yaml +0 -14
- package/dist/src/vocab/ignore.yaml +0 -14
- package/dist/src/vocab/image.yaml +0 -9
- package/dist/src/vocab/intransitiveactivity.yaml +0 -15
- package/dist/src/vocab/invite.yaml +0 -14
- package/dist/src/vocab/join.yaml +0 -14
- package/dist/src/vocab/key.yaml +0 -28
- package/dist/src/vocab/leave.yaml +0 -14
- package/dist/src/vocab/like.yaml +0 -16
- package/dist/src/vocab/link.yaml +0 -101
- package/dist/src/vocab/listen.yaml +0 -12
- package/dist/src/vocab/mention.yaml +0 -9
- package/dist/src/vocab/move.yaml +0 -15
- package/dist/src/vocab/multikey.yaml +0 -36
- package/dist/src/vocab/note.yaml +0 -48
- package/dist/src/vocab/object.yaml +0 -404
- package/dist/src/vocab/offer.yaml +0 -15
- package/dist/src/vocab/orderedcollection.yaml +0 -39
- package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
- package/dist/src/vocab/organization.yaml +0 -324
- package/dist/src/vocab/page.yaml +0 -11
- package/dist/src/vocab/person.yaml +0 -324
- package/dist/src/vocab/place.yaml +0 -75
- package/dist/src/vocab/profile.yaml +0 -26
- package/dist/src/vocab/propertyvalue.yaml +0 -32
- package/dist/src/vocab/question.yaml +0 -103
- package/dist/src/vocab/read.yaml +0 -13
- package/dist/src/vocab/reject.yaml +0 -14
- package/dist/src/vocab/relationship.yaml +0 -52
- package/dist/src/vocab/remove.yaml +0 -14
- package/dist/src/vocab/service.yaml +0 -324
- package/dist/src/vocab/source.yaml +0 -26
- package/dist/src/vocab/tentativeaccept.yaml +0 -14
- package/dist/src/vocab/tentativereject.yaml +0 -14
- package/dist/src/vocab/tombstone.yaml +0 -24
- package/dist/src/vocab/travel.yaml +0 -16
- package/dist/src/vocab/undo.yaml +0 -26
- package/dist/src/vocab/update.yaml +0 -58
- package/dist/src/vocab/video.yaml +0 -11
- package/dist/src/vocab/view.yaml +0 -13
- package/dist/testing/docloader.test.js +0 -22
- package/dist/vocab/actor.test.js +0 -5963
- package/dist/vocab/lookup.test.d.ts +0 -3
- package/dist/vocab/lookup.test.js +0 -476
- package/dist/vocab/type.test.d.ts +0 -3
- package/dist/vocab/type.test.js +0 -24
- package/dist/vocab/vocab.test.d.ts +0 -3
- package/dist/vocab/vocab.test.js +0 -9397
- package/dist/vocab-BCWe1Ih5.d.ts +0 -14905
- package/dist/vocab-ByUp-A2_.js +0 -260
- package/dist/vocab-CeDBzu-f.d.cts +0 -14903
- package/dist/vocab-X_X5T8D3.cjs +0 -296
- package/dist/webfinger/handler.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.js +0 -193
- package/dist/webfinger/mod.cjs +0 -8
- package/dist/webfinger/mod.d.cts +0 -2
- package/dist/webfinger/mod.d.ts +0 -4
- package/dist/webfinger/mod.js +0 -8
- package/dist/webfinger-C72Y8lrh.js +0 -4
- package/dist/webfinger-vAtLmxOF.cjs +0 -4
- /package/dist/{collection-BzWsN9pB.js → collection-CcnIw1qY.js} +0 -0
- /package/dist/{testing/docloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
- /package/dist/{mod-CVgZgliM.d.ts → mod-1E3W847c.d.ts} +0 -0
- /package/dist/{mod-B-hUPT2N.d.cts → mod-C81L6_lQ.d.cts} +0 -0
- /package/dist/{negotiation-C4nFufNk.js → negotiation-5NPJL6zp.js} +0 -0
- /package/dist/{nodeinfo-BnthBobC.js → nodeinfo-BlLsRSiT.js} +0 -0
- /package/dist/{nodeinfo-CdN0rEnZ.cjs → nodeinfo-DuMYTpbZ.cjs} +0 -0
- /package/dist/{vocab/actor.test.d.ts → otel/exporter.test.d.ts} +0 -0
- /package/dist/{retry-CfF8Gn4d.js → retry-D4GJ670a.js} +0 -0
- /package/dist/{sig-C34-oHBl.js → sig-CwuONEzF.js} +0 -0
- /package/dist/{sig-YYj5tCnr.cjs → sig-DeXX2xnj.cjs} +0 -0
- /package/dist/{utils-DyRU1gdZ.cjs → utils-Db0ZmjcD.cjs} +0 -0
- /package/dist/{utils-D-Va7aXC.js → utils-Wranxuoe.js} +0 -0
|
@@ -3,25 +3,28 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { getNodeInfo } from "./client-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
6
|
+
import { deno_default } from "./deno-DGx1JZHr.js";
|
|
7
|
+
import { getNodeInfo } from "./client-Dg7OfUDA.js";
|
|
8
|
+
import { RouterError } from "./router-D9eI0s4b.js";
|
|
9
|
+
import { nodeInfoToJson } from "./types-CPz01LGH.js";
|
|
10
|
+
import { exportJwk, importJwk, validateCryptoKey } from "./key-BCtt1Ugy.js";
|
|
11
|
+
import { verifyRequest } from "./http-LGtYlSfN.js";
|
|
12
|
+
import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-QlZPwGEH.js";
|
|
13
|
+
import { doesActorOwnKey, getKeyOwner } from "./owner-Cejm-F7S.js";
|
|
14
|
+
import { signObject, verifyObject } from "./proof-BOQBHd-i.js";
|
|
15
|
+
import { getAuthenticatedDocumentLoader } from "./docloader-D8UHsyqD.js";
|
|
16
|
+
import { kvCache } from "./kv-cache-B__dHl7g.js";
|
|
17
|
+
import { routeActivity } from "./inbox-DbtWQY2D.js";
|
|
18
|
+
import { FederationBuilderImpl } from "./builder-DTlQwmVF.js";
|
|
19
|
+
import { buildCollectionSynchronizationHeader } from "./collection-CcnIw1qY.js";
|
|
20
|
+
import { KvKeyCache } from "./keycache-DRxpZ5r9.js";
|
|
21
|
+
import { acceptsJsonLd } from "./negotiation-5NPJL6zp.js";
|
|
22
|
+
import { createExponentialBackoffPolicy } from "./retry-D4GJ670a.js";
|
|
23
|
+
import { SendActivityError, extractInboxes, sendActivity } from "./send-jFxXfsN8.js";
|
|
24
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";
|
|
25
28
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
26
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";
|
|
27
30
|
import { domainToASCII } from "node:url";
|
|
@@ -62,7 +65,7 @@ function autoIdAssigner(activity, context$1) {
|
|
|
62
65
|
* activity like this:
|
|
63
66
|
*
|
|
64
67
|
* ```typescript
|
|
65
|
-
* import { Follow, Person } from "@fedify/
|
|
68
|
+
* import { Follow, Person } from "@fedify/vocab";
|
|
66
69
|
* const input = new Follow({
|
|
67
70
|
* id: new URL("http://example.com/activities/1"),
|
|
68
71
|
* actor: new Person({
|
|
@@ -81,7 +84,7 @@ function autoIdAssigner(activity, context$1) {
|
|
|
81
84
|
* The result of applying this transformer would be:
|
|
82
85
|
*
|
|
83
86
|
* ```typescript
|
|
84
|
-
* import { Follow, Person } from "@fedify/
|
|
87
|
+
* import { Follow, Person } from "@fedify/vocab";
|
|
85
88
|
* const output = new Follow({
|
|
86
89
|
* id: new URL("http://example.com/activities/1"),
|
|
87
90
|
* actor: new URL("http://example.com/actors/1"),
|
|
@@ -154,151 +157,6 @@ function handleNodeInfoJrd(_request, context$1) {
|
|
|
154
157
|
return Promise.resolve(response);
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
//#endregion
|
|
158
|
-
//#region src/vocab/constants.ts
|
|
159
|
-
/**
|
|
160
|
-
* The special public collection for [public addressing]. *Do not mutate this
|
|
161
|
-
* object.*
|
|
162
|
-
*
|
|
163
|
-
* [public addressing]: https://www.w3.org/TR/activitypub/#public-addressing
|
|
164
|
-
*
|
|
165
|
-
* @since 0.7.0
|
|
166
|
-
*/
|
|
167
|
-
const PUBLIC_COLLECTION = new URL("https://www.w3.org/ns/activitystreams#Public");
|
|
168
|
-
|
|
169
|
-
//#endregion
|
|
170
|
-
//#region src/webfinger/handler.ts
|
|
171
|
-
const logger = getLogger([
|
|
172
|
-
"fedify",
|
|
173
|
-
"webfinger",
|
|
174
|
-
"server"
|
|
175
|
-
]);
|
|
176
|
-
/**
|
|
177
|
-
* Handles a WebFinger request. You would not typically call this function
|
|
178
|
-
* directly, but instead use {@link Federation.fetch} method.
|
|
179
|
-
* @param request The WebFinger request to handle.
|
|
180
|
-
* @param parameters The parameters for handling the request.
|
|
181
|
-
* @returns The response to the request.
|
|
182
|
-
*/
|
|
183
|
-
async function handleWebFinger(request, options) {
|
|
184
|
-
if (options.tracer == null) return await handleWebFingerInternal(request, options);
|
|
185
|
-
return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
186
|
-
try {
|
|
187
|
-
const response = await handleWebFingerInternal(request, options);
|
|
188
|
-
span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
189
|
-
return response;
|
|
190
|
-
} catch (error) {
|
|
191
|
-
span.setStatus({
|
|
192
|
-
code: SpanStatusCode.ERROR,
|
|
193
|
-
message: String(error)
|
|
194
|
-
});
|
|
195
|
-
throw error;
|
|
196
|
-
} finally {
|
|
197
|
-
span.end();
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
202
|
-
if (actorDispatcher == null) {
|
|
203
|
-
logger.error("Actor dispatcher is not set.");
|
|
204
|
-
return await onNotFound(request);
|
|
205
|
-
}
|
|
206
|
-
const resource = context$1.url.searchParams.get("resource");
|
|
207
|
-
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
208
|
-
span?.setAttribute("webfinger.resource", resource);
|
|
209
|
-
let resourceUrl;
|
|
210
|
-
try {
|
|
211
|
-
resourceUrl = new URL(resource);
|
|
212
|
-
} catch (e) {
|
|
213
|
-
if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
|
|
214
|
-
throw e;
|
|
215
|
-
}
|
|
216
|
-
span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
|
|
217
|
-
async function mapUsernameToIdentifier(username) {
|
|
218
|
-
if (actorHandleMapper == null) {
|
|
219
|
-
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
220
|
-
return username;
|
|
221
|
-
}
|
|
222
|
-
const identifier$1 = await actorHandleMapper(context$1, username);
|
|
223
|
-
if (identifier$1 == null) {
|
|
224
|
-
logger.error("Actor {username} not found.", { username });
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
return identifier$1;
|
|
228
|
-
}
|
|
229
|
-
let identifier = null;
|
|
230
|
-
const uriParsed = context$1.parseUri(resourceUrl);
|
|
231
|
-
if (uriParsed?.type != "actor") {
|
|
232
|
-
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
233
|
-
if (match == null) {
|
|
234
|
-
const result = await actorAliasMapper?.(context$1, resourceUrl);
|
|
235
|
-
if (result == null) return await onNotFound(request);
|
|
236
|
-
if ("identifier" in result) identifier = result.identifier;
|
|
237
|
-
else identifier = await mapUsernameToIdentifier(result.username);
|
|
238
|
-
} else {
|
|
239
|
-
const portMatch = /:\d+$/.exec(match[2]);
|
|
240
|
-
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
241
|
-
if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
|
|
242
|
-
else {
|
|
243
|
-
identifier = await mapUsernameToIdentifier(match[1]);
|
|
244
|
-
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
} else identifier = uriParsed.identifier;
|
|
248
|
-
if (identifier == null) return await onNotFound(request);
|
|
249
|
-
const actor = await actorDispatcher(context$1, identifier);
|
|
250
|
-
if (actor == null) {
|
|
251
|
-
logger.error("Actor {identifier} not found.", { identifier });
|
|
252
|
-
return await onNotFound(request);
|
|
253
|
-
}
|
|
254
|
-
const links = [{
|
|
255
|
-
rel: "self",
|
|
256
|
-
href: context$1.getActorUri(identifier).href,
|
|
257
|
-
type: "application/activity+json"
|
|
258
|
-
}];
|
|
259
|
-
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
260
|
-
rel: url.rel ?? "http://webfinger.net/rel/profile-page",
|
|
261
|
-
href: url.href.href,
|
|
262
|
-
type: url.mediaType == null ? void 0 : url.mediaType
|
|
263
|
-
});
|
|
264
|
-
else if (url instanceof URL) links.push({
|
|
265
|
-
rel: "http://webfinger.net/rel/profile-page",
|
|
266
|
-
href: url.href
|
|
267
|
-
});
|
|
268
|
-
for await (const image of actor.getIcons()) {
|
|
269
|
-
if (image.url?.href == null) continue;
|
|
270
|
-
const link = {
|
|
271
|
-
rel: "http://webfinger.net/rel/avatar",
|
|
272
|
-
href: image.url.href.toString()
|
|
273
|
-
};
|
|
274
|
-
if (image.mediaType != null) link.type = image.mediaType;
|
|
275
|
-
links.push(link);
|
|
276
|
-
}
|
|
277
|
-
if (webFingerLinksDispatcher != null) {
|
|
278
|
-
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
279
|
-
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
280
|
-
}
|
|
281
|
-
const aliases = [];
|
|
282
|
-
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
283
|
-
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
284
|
-
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
285
|
-
}
|
|
286
|
-
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
287
|
-
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
288
|
-
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
289
|
-
aliases.push(`acct:${username}@${host}`);
|
|
290
|
-
}
|
|
291
|
-
const jrd = {
|
|
292
|
-
subject: resourceUrl.href,
|
|
293
|
-
aliases,
|
|
294
|
-
links
|
|
295
|
-
};
|
|
296
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
297
|
-
"Content-Type": "application/jrd+json",
|
|
298
|
-
"Access-Control-Allow-Origin": "*"
|
|
299
|
-
} });
|
|
300
|
-
}
|
|
301
|
-
|
|
302
160
|
//#endregion
|
|
303
161
|
//#region src/federation/handler.ts
|
|
304
162
|
/**
|
|
@@ -1289,6 +1147,138 @@ async function respondWithObjectIfAcceptable(object, request, options) {
|
|
|
1289
1147
|
return response;
|
|
1290
1148
|
}
|
|
1291
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
|
+
links.push({
|
|
1252
|
+
rel: "http://webfinger.net/rel/avatar",
|
|
1253
|
+
href: image.url.href.toString(),
|
|
1254
|
+
...image.mediaType != null && { type: image.mediaType }
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
if (webFingerLinksDispatcher != null) {
|
|
1258
|
+
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
1259
|
+
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
1260
|
+
}
|
|
1261
|
+
const aliases = [];
|
|
1262
|
+
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
1263
|
+
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
1264
|
+
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
1265
|
+
}
|
|
1266
|
+
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
1267
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
1268
|
+
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
1269
|
+
aliases.push(`acct:${username}@${host}`);
|
|
1270
|
+
}
|
|
1271
|
+
const jrd = {
|
|
1272
|
+
subject: resourceUrl.href,
|
|
1273
|
+
aliases,
|
|
1274
|
+
links
|
|
1275
|
+
};
|
|
1276
|
+
return new Response(JSON.stringify(jrd), { headers: {
|
|
1277
|
+
"Content-Type": "application/jrd+json",
|
|
1278
|
+
"Access-Control-Allow-Origin": "*"
|
|
1279
|
+
} });
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1292
1282
|
//#endregion
|
|
1293
1283
|
//#region src/federation/middleware.ts
|
|
1294
1284
|
/**
|
|
@@ -1317,6 +1307,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1317
1307
|
allowPrivateAddress;
|
|
1318
1308
|
userAgent;
|
|
1319
1309
|
onOutboxError;
|
|
1310
|
+
permanentFailureStatusCodes;
|
|
1320
1311
|
signatureTimeWindow;
|
|
1321
1312
|
skipSignatureVerification;
|
|
1322
1313
|
outboxRetryPolicy;
|
|
@@ -1398,6 +1389,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1398
1389
|
}));
|
|
1399
1390
|
this.userAgent = userAgent;
|
|
1400
1391
|
this.onOutboxError = options.onOutboxError;
|
|
1392
|
+
this.permanentFailureStatusCodes = options.permanentFailureStatusCodes ?? [404, 410];
|
|
1401
1393
|
this.signatureTimeWindow = options.signatureTimeWindow ?? { hours: 1 };
|
|
1402
1394
|
this.skipSignatureVerification = options.skipSignatureVerification ?? false;
|
|
1403
1395
|
this.outboxRetryPolicy = options.outboxRetryPolicy ?? createExponentialBackoffPolicy();
|
|
@@ -1528,6 +1520,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1528
1520
|
}) });
|
|
1529
1521
|
await this.sendActivity(keys, message.inboxes, activity, {
|
|
1530
1522
|
collectionSync: message.collectionSync,
|
|
1523
|
+
orderingKey: message.orderingKey,
|
|
1531
1524
|
context: context$1
|
|
1532
1525
|
});
|
|
1533
1526
|
}
|
|
@@ -1579,13 +1572,44 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1579
1572
|
tracerProvider: this.tracerProvider
|
|
1580
1573
|
});
|
|
1581
1574
|
try {
|
|
1582
|
-
this.onOutboxError?.(error, activity);
|
|
1575
|
+
await this.onOutboxError?.(error, activity);
|
|
1583
1576
|
} catch (error$1) {
|
|
1584
1577
|
logger$2.error("An unexpected error occurred in onError handler:\n{error}", {
|
|
1585
1578
|
...logData,
|
|
1586
1579
|
error: error$1
|
|
1587
1580
|
});
|
|
1588
1581
|
}
|
|
1582
|
+
if (error instanceof SendActivityError && this.permanentFailureStatusCodes.includes(error.statusCode)) {
|
|
1583
|
+
logger$2.warn("Permanent delivery failure for activity {activityId} to {inbox} ({status}); not retrying.", {
|
|
1584
|
+
...logData,
|
|
1585
|
+
status: error.statusCode
|
|
1586
|
+
});
|
|
1587
|
+
if (this.outboxPermanentFailureHandler != null) {
|
|
1588
|
+
const ctx = this.#createContext(new URL(message.baseUrl), _, { documentLoader: this.documentLoaderFactory(loaderOptions) });
|
|
1589
|
+
try {
|
|
1590
|
+
await this.outboxPermanentFailureHandler(ctx, {
|
|
1591
|
+
inbox: new URL(message.inbox),
|
|
1592
|
+
activity,
|
|
1593
|
+
error,
|
|
1594
|
+
statusCode: error.statusCode,
|
|
1595
|
+
actorIds: (message.actorIds ?? []).flatMap((id) => {
|
|
1596
|
+
try {
|
|
1597
|
+
return [new URL(id)];
|
|
1598
|
+
} catch {
|
|
1599
|
+
logger$2.warn("Invalid actorId URL in OutboxMessage: {id}", { id });
|
|
1600
|
+
return [];
|
|
1601
|
+
}
|
|
1602
|
+
})
|
|
1603
|
+
});
|
|
1604
|
+
} catch (handlerError) {
|
|
1605
|
+
logger$2.error("An unexpected error occurred in outboxPermanentFailureHandler:\n{error}", {
|
|
1606
|
+
...logData,
|
|
1607
|
+
error: handlerError
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1589
1613
|
if (this.outboxQueue?.nativeRetrial) {
|
|
1590
1614
|
logger$2.error("Failed to send activity {activityId} to {inbox}; backend will handle retry:\n{error}", {
|
|
1591
1615
|
...logData,
|
|
@@ -1776,7 +1800,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1776
1800
|
"federation",
|
|
1777
1801
|
"outbox"
|
|
1778
1802
|
]);
|
|
1779
|
-
const { immediate, collectionSync, context: ctx } = options;
|
|
1803
|
+
const { immediate, collectionSync, orderingKey, context: ctx } = options;
|
|
1780
1804
|
if (activity.id == null) throw new TypeError("The activity to send must have an id.");
|
|
1781
1805
|
if (activity.actorId == null) throw new TypeError("The activity to send must have at least one actor property.");
|
|
1782
1806
|
else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
|
|
@@ -1864,6 +1888,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1864
1888
|
propagation.inject(context.active(), carrier);
|
|
1865
1889
|
const messages = [];
|
|
1866
1890
|
for (const inbox in inboxes) {
|
|
1891
|
+
const inboxOrigin = new URL(inbox).origin;
|
|
1892
|
+
const messageOrderingKey = orderingKey == null ? void 0 : `${orderingKey}\n${inboxOrigin}`;
|
|
1867
1893
|
const message = {
|
|
1868
1894
|
type: "outbox",
|
|
1869
1895
|
id: crypto.randomUUID(),
|
|
@@ -1874,16 +1900,33 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1874
1900
|
activityType: getTypeId(activity).href,
|
|
1875
1901
|
inbox,
|
|
1876
1902
|
sharedInbox: inboxes[inbox].sharedInbox,
|
|
1903
|
+
actorIds: [...inboxes[inbox].actorIds],
|
|
1877
1904
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1878
1905
|
attempt: 0,
|
|
1879
1906
|
headers: collectionSync == null ? {} : { "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox].actorIds) },
|
|
1907
|
+
orderingKey: messageOrderingKey,
|
|
1880
1908
|
traceContext: carrier
|
|
1881
1909
|
};
|
|
1882
|
-
messages.push(
|
|
1910
|
+
messages.push({
|
|
1911
|
+
message,
|
|
1912
|
+
orderingKey: messageOrderingKey
|
|
1913
|
+
});
|
|
1883
1914
|
}
|
|
1884
1915
|
const { outboxQueue } = this;
|
|
1885
1916
|
if (outboxQueue.enqueueMany == null) {
|
|
1886
|
-
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
1917
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
1918
|
+
const results = await Promise.allSettled(promises);
|
|
1919
|
+
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
1920
|
+
if (errors.length > 0) {
|
|
1921
|
+
logger$2.error("Failed to enqueue activity {activityId} to send later: {errors}", {
|
|
1922
|
+
activityId: activity.id.href,
|
|
1923
|
+
errors
|
|
1924
|
+
});
|
|
1925
|
+
if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
|
|
1926
|
+
throw errors[0];
|
|
1927
|
+
}
|
|
1928
|
+
} else if (orderingKey != null) {
|
|
1929
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
1887
1930
|
const results = await Promise.allSettled(promises);
|
|
1888
1931
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
1889
1932
|
if (errors.length > 0) {
|
|
@@ -1895,7 +1938,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
1895
1938
|
throw errors[0];
|
|
1896
1939
|
}
|
|
1897
1940
|
} else try {
|
|
1898
|
-
await outboxQueue.enqueueMany(messages);
|
|
1941
|
+
await outboxQueue.enqueueMany(messages.map((m) => m.message));
|
|
1899
1942
|
} catch (error) {
|
|
1900
1943
|
logger$2.error("Failed to enqueue activity {activityId} to send later: {error}", {
|
|
1901
1944
|
activityId: activity.id.href,
|
|
@@ -2611,20 +2654,25 @@ var ContextImpl = class ContextImpl {
|
|
|
2611
2654
|
} else keys = [sender];
|
|
2612
2655
|
if (keys.length < 1) throw new TypeError("The sender's keys must not be empty.");
|
|
2613
2656
|
for (const { privateKey } of keys) validateCryptoKey(privateKey, "private");
|
|
2614
|
-
const opts = { context: this };
|
|
2615
2657
|
let expandedRecipients;
|
|
2658
|
+
let collectionSync;
|
|
2616
2659
|
if (Array.isArray(recipients)) expandedRecipients = recipients;
|
|
2617
2660
|
else if (recipients === "followers") {
|
|
2618
2661
|
if (identifier == null) throw new Error("If recipients is \"followers\", sender must be an actor identifier or username.");
|
|
2619
2662
|
expandedRecipients = [];
|
|
2620
2663
|
for await (const recipient of this.getFollowers(identifier)) expandedRecipients.push(recipient);
|
|
2621
2664
|
if (options.syncCollection) try {
|
|
2622
|
-
|
|
2665
|
+
collectionSync = this.getFollowersUri(identifier).href;
|
|
2623
2666
|
} catch (error) {
|
|
2624
|
-
if (error instanceof RouterError)
|
|
2625
|
-
else throw error;
|
|
2667
|
+
if (!(error instanceof RouterError)) throw error;
|
|
2626
2668
|
}
|
|
2627
2669
|
} else expandedRecipients = [recipients];
|
|
2670
|
+
const opts = {
|
|
2671
|
+
context: this,
|
|
2672
|
+
orderingKey: options.orderingKey,
|
|
2673
|
+
collectionSync,
|
|
2674
|
+
immediate: options.immediate
|
|
2675
|
+
};
|
|
2628
2676
|
span.setAttribute("activitypub.inboxes", expandedRecipients.length);
|
|
2629
2677
|
for (const activityTransformer of this.federation.activityTransformers) activity = activityTransformer(activity, this);
|
|
2630
2678
|
span?.setAttribute("activitypub.activity.id", activity?.id?.href ?? "");
|
|
@@ -2671,10 +2719,11 @@ var ContextImpl = class ContextImpl {
|
|
|
2671
2719
|
activityId: activity.id?.href,
|
|
2672
2720
|
activityType: getTypeId(activity).href,
|
|
2673
2721
|
collectionSync: opts.collectionSync,
|
|
2722
|
+
orderingKey: options.orderingKey,
|
|
2674
2723
|
traceContext: carrier
|
|
2675
2724
|
};
|
|
2676
2725
|
if (!this.federation.manuallyStartQueue) this.federation._startQueueInternal(this.data);
|
|
2677
|
-
this.federation.fanoutQueue.enqueue(message);
|
|
2726
|
+
this.federation.fanoutQueue.enqueue(message, { orderingKey: options.orderingKey });
|
|
2678
2727
|
}
|
|
2679
2728
|
async *getFollowers(identifier) {
|
|
2680
2729
|
if (this.federation.followersCallbacks == null) throw new Error("No followers collection dispatcher registered.");
|
|
@@ -3026,8 +3075,10 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
3026
3075
|
}
|
|
3027
3076
|
const carrier = {};
|
|
3028
3077
|
propagation.inject(context.active(), carrier);
|
|
3078
|
+
const orderingKey = options?.orderingKey;
|
|
3029
3079
|
const messages = [];
|
|
3030
3080
|
for (const inbox in inboxes) {
|
|
3081
|
+
const inboxUrl = new URL(inbox);
|
|
3031
3082
|
const message = {
|
|
3032
3083
|
type: "outbox",
|
|
3033
3084
|
id: crypto.randomUUID(),
|
|
@@ -3041,13 +3092,29 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
3041
3092
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3042
3093
|
attempt: 0,
|
|
3043
3094
|
headers: {},
|
|
3095
|
+
orderingKey: orderingKey == null ? void 0 : `${orderingKey}\n${inboxUrl.origin}`,
|
|
3044
3096
|
traceContext: carrier
|
|
3045
3097
|
};
|
|
3046
|
-
messages.push(
|
|
3098
|
+
messages.push({
|
|
3099
|
+
message,
|
|
3100
|
+
orderingKey: message.orderingKey
|
|
3101
|
+
});
|
|
3047
3102
|
}
|
|
3048
3103
|
const { outboxQueue } = this.federation;
|
|
3049
3104
|
if (outboxQueue.enqueueMany == null) {
|
|
3050
|
-
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
3105
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
3106
|
+
const results = await Promise.allSettled(promises);
|
|
3107
|
+
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3108
|
+
if (errors.length > 0) {
|
|
3109
|
+
logger$2.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", {
|
|
3110
|
+
activityId: this.activityId,
|
|
3111
|
+
errors
|
|
3112
|
+
});
|
|
3113
|
+
if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${this.activityId} to forward later.`);
|
|
3114
|
+
throw errors[0];
|
|
3115
|
+
}
|
|
3116
|
+
} else if (orderingKey != null) {
|
|
3117
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
3051
3118
|
const results = await Promise.allSettled(promises);
|
|
3052
3119
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3053
3120
|
if (errors.length > 0) {
|
|
@@ -3059,7 +3126,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
3059
3126
|
throw errors[0];
|
|
3060
3127
|
}
|
|
3061
3128
|
} else try {
|
|
3062
|
-
await outboxQueue.enqueueMany(messages);
|
|
3129
|
+
await outboxQueue.enqueueMany(messages.map((m) => m.message));
|
|
3063
3130
|
} catch (error) {
|
|
3064
3131
|
logger$2.error("Failed to enqueue activity {activityId} to forward later:\n{error}", {
|
|
3065
3132
|
activityId: this.activityId,
|