@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
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
|
|
5
|
-
import { getDefaultActivityTransformers } from "./transformers-
|
|
6
|
-
import { deno_default,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { getNodeInfo, nodeInfoToJson } from "./types-BtUjyi5y.js";
|
|
11
|
-
import { getAuthenticatedDocumentLoader, kvCache } from "./kv-cache-HFnFIjSD.js";
|
|
12
|
-
import { lookupObject, traverseCollection } from "./vocab-ByUp-A2_.js";
|
|
5
|
+
import { getDefaultActivityTransformers } from "./transformers-N_ip_y4P.js";
|
|
6
|
+
import { deno_default, doubleKnock, exportJwk, importJwk, validateCryptoKey, verifyRequest } from "./http-CL3G0rnf.js";
|
|
7
|
+
import { detachSignature, doesActorOwnKey, getKeyOwner, hasSignature, signJsonLd, signObject, verifyJsonLd, verifyObject } from "./proof-CnaEQ_Ev.js";
|
|
8
|
+
import { getNodeInfo, nodeInfoToJson } from "./types-8l28uC8o.js";
|
|
9
|
+
import { getAuthenticatedDocumentLoader, kvCache } from "./kv-cache-0786BfqY.js";
|
|
13
10
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
11
|
+
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
14
12
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
15
|
-
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
16
13
|
import { cloneDeep } from "es-toolkit";
|
|
17
14
|
import { Router } from "uri-template-router";
|
|
18
15
|
import { parseTemplate } from "url-template";
|
|
19
16
|
import { encodeHex } from "byte-encodings/hex";
|
|
20
17
|
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";
|
|
18
|
+
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
19
|
+
import { lookupWebFinger } from "@fedify/webfinger";
|
|
21
20
|
import { domainToASCII } from "node:url";
|
|
22
21
|
|
|
23
22
|
//#region src/federation/inbox.ts
|
|
@@ -323,6 +322,7 @@ var FederationBuilderImpl = class {
|
|
|
323
322
|
inboxListeners;
|
|
324
323
|
inboxErrorHandler;
|
|
325
324
|
sharedInboxKeyDispatcher;
|
|
325
|
+
outboxPermanentFailureHandler;
|
|
326
326
|
idempotencyStrategy;
|
|
327
327
|
collectionTypeIds;
|
|
328
328
|
collectionCallbacks;
|
|
@@ -338,7 +338,7 @@ var FederationBuilderImpl = class {
|
|
|
338
338
|
this.collectionTypeIds = {};
|
|
339
339
|
}
|
|
340
340
|
async build(options) {
|
|
341
|
-
const { FederationImpl: FederationImpl$1 } = await import("./middleware-
|
|
341
|
+
const { FederationImpl: FederationImpl$1 } = await import("./middleware-B3jUPnDa.js");
|
|
342
342
|
const f = new FederationImpl$1(options);
|
|
343
343
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
344
344
|
f.router = this.router.clone();
|
|
@@ -360,6 +360,7 @@ var FederationBuilderImpl = class {
|
|
|
360
360
|
f.inboxListeners = this.inboxListeners?.clone();
|
|
361
361
|
f.inboxErrorHandler = this.inboxErrorHandler;
|
|
362
362
|
f.sharedInboxKeyDispatcher = this.sharedInboxKeyDispatcher;
|
|
363
|
+
f.outboxPermanentFailureHandler = this.outboxPermanentFailureHandler;
|
|
363
364
|
f.idempotencyStrategy = this.idempotencyStrategy;
|
|
364
365
|
return f;
|
|
365
366
|
}
|
|
@@ -841,6 +842,9 @@ var FederationBuilderImpl = class {
|
|
|
841
842
|
const path = this.router.build(`collection:${routeName}`, values) ?? this.router.build(`orderedCollection:${routeName}`, values);
|
|
842
843
|
return path;
|
|
843
844
|
}
|
|
845
|
+
setOutboxPermanentFailureHandler(handler) {
|
|
846
|
+
this.outboxPermanentFailureHandler = handler;
|
|
847
|
+
}
|
|
844
848
|
/**
|
|
845
849
|
* Converts a name (string or symbol) to a unique string identifier.
|
|
846
850
|
* For symbols, generates and caches a UUID if not already present.
|
|
@@ -2037,139 +2041,6 @@ function handleNodeInfoJrd(_request, context$1) {
|
|
|
2037
2041
|
return Promise.resolve(response);
|
|
2038
2042
|
}
|
|
2039
2043
|
|
|
2040
|
-
//#endregion
|
|
2041
|
-
//#region src/webfinger/handler.ts
|
|
2042
|
-
const logger = getLogger([
|
|
2043
|
-
"fedify",
|
|
2044
|
-
"webfinger",
|
|
2045
|
-
"server"
|
|
2046
|
-
]);
|
|
2047
|
-
/**
|
|
2048
|
-
* Handles a WebFinger request. You would not typically call this function
|
|
2049
|
-
* directly, but instead use {@link Federation.fetch} method.
|
|
2050
|
-
* @param request The WebFinger request to handle.
|
|
2051
|
-
* @param parameters The parameters for handling the request.
|
|
2052
|
-
* @returns The response to the request.
|
|
2053
|
-
*/
|
|
2054
|
-
async function handleWebFinger(request, options) {
|
|
2055
|
-
if (options.tracer == null) return await handleWebFingerInternal(request, options);
|
|
2056
|
-
return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
2057
|
-
try {
|
|
2058
|
-
const response = await handleWebFingerInternal(request, options);
|
|
2059
|
-
span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
2060
|
-
return response;
|
|
2061
|
-
} catch (error) {
|
|
2062
|
-
span.setStatus({
|
|
2063
|
-
code: SpanStatusCode.ERROR,
|
|
2064
|
-
message: String(error)
|
|
2065
|
-
});
|
|
2066
|
-
throw error;
|
|
2067
|
-
} finally {
|
|
2068
|
-
span.end();
|
|
2069
|
-
}
|
|
2070
|
-
});
|
|
2071
|
-
}
|
|
2072
|
-
async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2073
|
-
if (actorDispatcher == null) {
|
|
2074
|
-
logger.error("Actor dispatcher is not set.");
|
|
2075
|
-
return await onNotFound(request);
|
|
2076
|
-
}
|
|
2077
|
-
const resource = context$1.url.searchParams.get("resource");
|
|
2078
|
-
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
2079
|
-
span?.setAttribute("webfinger.resource", resource);
|
|
2080
|
-
let resourceUrl;
|
|
2081
|
-
try {
|
|
2082
|
-
resourceUrl = new URL(resource);
|
|
2083
|
-
} catch (e) {
|
|
2084
|
-
if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
|
|
2085
|
-
throw e;
|
|
2086
|
-
}
|
|
2087
|
-
span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
|
|
2088
|
-
async function mapUsernameToIdentifier(username) {
|
|
2089
|
-
if (actorHandleMapper == null) {
|
|
2090
|
-
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
2091
|
-
return username;
|
|
2092
|
-
}
|
|
2093
|
-
const identifier$1 = await actorHandleMapper(context$1, username);
|
|
2094
|
-
if (identifier$1 == null) {
|
|
2095
|
-
logger.error("Actor {username} not found.", { username });
|
|
2096
|
-
return null;
|
|
2097
|
-
}
|
|
2098
|
-
return identifier$1;
|
|
2099
|
-
}
|
|
2100
|
-
let identifier = null;
|
|
2101
|
-
const uriParsed = context$1.parseUri(resourceUrl);
|
|
2102
|
-
if (uriParsed?.type != "actor") {
|
|
2103
|
-
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
2104
|
-
if (match == null) {
|
|
2105
|
-
const result = await actorAliasMapper?.(context$1, resourceUrl);
|
|
2106
|
-
if (result == null) return await onNotFound(request);
|
|
2107
|
-
if ("identifier" in result) identifier = result.identifier;
|
|
2108
|
-
else identifier = await mapUsernameToIdentifier(result.username);
|
|
2109
|
-
} else {
|
|
2110
|
-
const portMatch = /:\d+$/.exec(match[2]);
|
|
2111
|
-
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2112
|
-
if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2113
|
-
else {
|
|
2114
|
-
identifier = await mapUsernameToIdentifier(match[1]);
|
|
2115
|
-
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
} else identifier = uriParsed.identifier;
|
|
2119
|
-
if (identifier == null) return await onNotFound(request);
|
|
2120
|
-
const actor = await actorDispatcher(context$1, identifier);
|
|
2121
|
-
if (actor == null) {
|
|
2122
|
-
logger.error("Actor {identifier} not found.", { identifier });
|
|
2123
|
-
return await onNotFound(request);
|
|
2124
|
-
}
|
|
2125
|
-
const links = [{
|
|
2126
|
-
rel: "self",
|
|
2127
|
-
href: context$1.getActorUri(identifier).href,
|
|
2128
|
-
type: "application/activity+json"
|
|
2129
|
-
}];
|
|
2130
|
-
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
2131
|
-
rel: url.rel ?? "http://webfinger.net/rel/profile-page",
|
|
2132
|
-
href: url.href.href,
|
|
2133
|
-
type: url.mediaType == null ? void 0 : url.mediaType
|
|
2134
|
-
});
|
|
2135
|
-
else if (url instanceof URL) links.push({
|
|
2136
|
-
rel: "http://webfinger.net/rel/profile-page",
|
|
2137
|
-
href: url.href
|
|
2138
|
-
});
|
|
2139
|
-
for await (const image of actor.getIcons()) {
|
|
2140
|
-
if (image.url?.href == null) continue;
|
|
2141
|
-
const link = {
|
|
2142
|
-
rel: "http://webfinger.net/rel/avatar",
|
|
2143
|
-
href: image.url.href.toString()
|
|
2144
|
-
};
|
|
2145
|
-
if (image.mediaType != null) link.type = image.mediaType;
|
|
2146
|
-
links.push(link);
|
|
2147
|
-
}
|
|
2148
|
-
if (webFingerLinksDispatcher != null) {
|
|
2149
|
-
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
2150
|
-
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2151
|
-
}
|
|
2152
|
-
const aliases = [];
|
|
2153
|
-
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
2154
|
-
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
2155
|
-
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
2156
|
-
}
|
|
2157
|
-
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
2158
|
-
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2159
|
-
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
2160
|
-
aliases.push(`acct:${username}@${host}`);
|
|
2161
|
-
}
|
|
2162
|
-
const jrd = {
|
|
2163
|
-
subject: resourceUrl.href,
|
|
2164
|
-
aliases,
|
|
2165
|
-
links
|
|
2166
|
-
};
|
|
2167
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
2168
|
-
"Content-Type": "application/jrd+json",
|
|
2169
|
-
"Access-Control-Allow-Origin": "*"
|
|
2170
|
-
} });
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
2044
|
//#endregion
|
|
2174
2045
|
//#region src/federation/retry.ts
|
|
2175
2046
|
/**
|
|
@@ -2196,8 +2067,8 @@ function createExponentialBackoffPolicy(options = {}) {
|
|
|
2196
2067
|
milliseconds *= 1 + Math.random();
|
|
2197
2068
|
milliseconds = Math.round(milliseconds);
|
|
2198
2069
|
}
|
|
2199
|
-
const delay
|
|
2200
|
-
return Temporal.Duration.compare(delay
|
|
2070
|
+
const delay = Temporal.Duration.from({ milliseconds });
|
|
2071
|
+
return Temporal.Duration.compare(delay, maxDelay) > 0 ? maxDelay : delay;
|
|
2201
2072
|
};
|
|
2202
2073
|
}
|
|
2203
2074
|
|
|
@@ -2314,7 +2185,7 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2314
2185
|
statusText: response.statusText,
|
|
2315
2186
|
error
|
|
2316
2187
|
});
|
|
2317
|
-
throw new
|
|
2188
|
+
throw new SendActivityError(inbox, response.status, `Failed to send activity ${activityId} to ${inbox.href} (${response.status} ${response.statusText}):\n${error}`, error);
|
|
2318
2189
|
}
|
|
2319
2190
|
span.addEvent("activitypub.activity.sent", {
|
|
2320
2191
|
"activitypub.activity.json": JSON.stringify(activity),
|
|
@@ -2322,6 +2193,172 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2322
2193
|
"activitypub.activity.id": activityId ?? ""
|
|
2323
2194
|
});
|
|
2324
2195
|
}
|
|
2196
|
+
/**
|
|
2197
|
+
* An error that is thrown when an activity fails to send to a remote inbox.
|
|
2198
|
+
* It contains structured information about the failure, including the HTTP
|
|
2199
|
+
* status code, the inbox URL, and the response body.
|
|
2200
|
+
* @since 2.0.0
|
|
2201
|
+
*/
|
|
2202
|
+
var SendActivityError = class extends Error {
|
|
2203
|
+
/**
|
|
2204
|
+
* The inbox URL that the activity was being sent to.
|
|
2205
|
+
*/
|
|
2206
|
+
inbox;
|
|
2207
|
+
/**
|
|
2208
|
+
* The HTTP status code returned by the inbox.
|
|
2209
|
+
*/
|
|
2210
|
+
statusCode;
|
|
2211
|
+
/**
|
|
2212
|
+
* The response body from the inbox, if any.
|
|
2213
|
+
*/
|
|
2214
|
+
responseBody;
|
|
2215
|
+
/**
|
|
2216
|
+
* Creates a new {@link SendActivityError}.
|
|
2217
|
+
* @param inbox The inbox URL.
|
|
2218
|
+
* @param statusCode The HTTP status code.
|
|
2219
|
+
* @param message The error message.
|
|
2220
|
+
* @param responseBody The response body.
|
|
2221
|
+
*/
|
|
2222
|
+
constructor(inbox, statusCode, message, responseBody) {
|
|
2223
|
+
super(message);
|
|
2224
|
+
this.name = "SendActivityError";
|
|
2225
|
+
this.inbox = inbox;
|
|
2226
|
+
this.statusCode = statusCode;
|
|
2227
|
+
this.responseBody = responseBody;
|
|
2228
|
+
}
|
|
2229
|
+
};
|
|
2230
|
+
|
|
2231
|
+
//#endregion
|
|
2232
|
+
//#region src/federation/webfinger.ts
|
|
2233
|
+
const logger = getLogger([
|
|
2234
|
+
"fedify",
|
|
2235
|
+
"webfinger",
|
|
2236
|
+
"server"
|
|
2237
|
+
]);
|
|
2238
|
+
/**
|
|
2239
|
+
* Handles a WebFinger request. You would not typically call this function
|
|
2240
|
+
* directly, but instead use {@link Federation.fetch} method.
|
|
2241
|
+
* @param request The WebFinger request to handle.
|
|
2242
|
+
* @param parameters The parameters for handling the request.
|
|
2243
|
+
* @returns The response to the request.
|
|
2244
|
+
*/
|
|
2245
|
+
async function handleWebFinger(request, options) {
|
|
2246
|
+
if (options.tracer == null) return await handleWebFingerInternal(request, options);
|
|
2247
|
+
return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
2248
|
+
try {
|
|
2249
|
+
const response = await handleWebFingerInternal(request, options);
|
|
2250
|
+
span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
2251
|
+
return response;
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
span.setStatus({
|
|
2254
|
+
code: SpanStatusCode.ERROR,
|
|
2255
|
+
message: String(error)
|
|
2256
|
+
});
|
|
2257
|
+
throw error;
|
|
2258
|
+
} finally {
|
|
2259
|
+
span.end();
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2264
|
+
if (actorDispatcher == null) {
|
|
2265
|
+
logger.error("Actor dispatcher is not set.");
|
|
2266
|
+
return await onNotFound(request);
|
|
2267
|
+
}
|
|
2268
|
+
const resource = context$1.url.searchParams.get("resource");
|
|
2269
|
+
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
2270
|
+
span?.setAttribute("webfinger.resource", resource);
|
|
2271
|
+
let resourceUrl;
|
|
2272
|
+
try {
|
|
2273
|
+
resourceUrl = new URL(resource);
|
|
2274
|
+
} catch (e) {
|
|
2275
|
+
if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
|
|
2276
|
+
throw e;
|
|
2277
|
+
}
|
|
2278
|
+
span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
|
|
2279
|
+
async function mapUsernameToIdentifier(username) {
|
|
2280
|
+
if (actorHandleMapper == null) {
|
|
2281
|
+
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
2282
|
+
return username;
|
|
2283
|
+
}
|
|
2284
|
+
const identifier$1 = await actorHandleMapper(context$1, username);
|
|
2285
|
+
if (identifier$1 == null) {
|
|
2286
|
+
logger.error("Actor {username} not found.", { username });
|
|
2287
|
+
return null;
|
|
2288
|
+
}
|
|
2289
|
+
return identifier$1;
|
|
2290
|
+
}
|
|
2291
|
+
let identifier = null;
|
|
2292
|
+
const uriParsed = context$1.parseUri(resourceUrl);
|
|
2293
|
+
if (uriParsed?.type != "actor") {
|
|
2294
|
+
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
2295
|
+
if (match == null) {
|
|
2296
|
+
const result = await actorAliasMapper?.(context$1, resourceUrl);
|
|
2297
|
+
if (result == null) return await onNotFound(request);
|
|
2298
|
+
if ("identifier" in result) identifier = result.identifier;
|
|
2299
|
+
else identifier = await mapUsernameToIdentifier(result.username);
|
|
2300
|
+
} else {
|
|
2301
|
+
const portMatch = /:\d+$/.exec(match[2]);
|
|
2302
|
+
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2303
|
+
if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2304
|
+
else {
|
|
2305
|
+
identifier = await mapUsernameToIdentifier(match[1]);
|
|
2306
|
+
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
} else identifier = uriParsed.identifier;
|
|
2310
|
+
if (identifier == null) return await onNotFound(request);
|
|
2311
|
+
const actor = await actorDispatcher(context$1, identifier);
|
|
2312
|
+
if (actor == null) {
|
|
2313
|
+
logger.error("Actor {identifier} not found.", { identifier });
|
|
2314
|
+
return await onNotFound(request);
|
|
2315
|
+
}
|
|
2316
|
+
const links = [{
|
|
2317
|
+
rel: "self",
|
|
2318
|
+
href: context$1.getActorUri(identifier).href,
|
|
2319
|
+
type: "application/activity+json"
|
|
2320
|
+
}];
|
|
2321
|
+
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
2322
|
+
rel: url.rel ?? "http://webfinger.net/rel/profile-page",
|
|
2323
|
+
href: url.href.href,
|
|
2324
|
+
type: url.mediaType == null ? void 0 : url.mediaType
|
|
2325
|
+
});
|
|
2326
|
+
else if (url instanceof URL) links.push({
|
|
2327
|
+
rel: "http://webfinger.net/rel/profile-page",
|
|
2328
|
+
href: url.href
|
|
2329
|
+
});
|
|
2330
|
+
for await (const image of actor.getIcons()) {
|
|
2331
|
+
if (image.url?.href == null) continue;
|
|
2332
|
+
links.push({
|
|
2333
|
+
rel: "http://webfinger.net/rel/avatar",
|
|
2334
|
+
href: image.url.href.toString(),
|
|
2335
|
+
...image.mediaType != null && { type: image.mediaType }
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
if (webFingerLinksDispatcher != null) {
|
|
2339
|
+
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
2340
|
+
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2341
|
+
}
|
|
2342
|
+
const aliases = [];
|
|
2343
|
+
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
2344
|
+
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
2345
|
+
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
2346
|
+
}
|
|
2347
|
+
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
2348
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2349
|
+
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
2350
|
+
aliases.push(`acct:${username}@${host}`);
|
|
2351
|
+
}
|
|
2352
|
+
const jrd = {
|
|
2353
|
+
subject: resourceUrl.href,
|
|
2354
|
+
aliases,
|
|
2355
|
+
links
|
|
2356
|
+
};
|
|
2357
|
+
return new Response(JSON.stringify(jrd), { headers: {
|
|
2358
|
+
"Content-Type": "application/jrd+json",
|
|
2359
|
+
"Access-Control-Allow-Origin": "*"
|
|
2360
|
+
} });
|
|
2361
|
+
}
|
|
2325
2362
|
|
|
2326
2363
|
//#endregion
|
|
2327
2364
|
//#region src/federation/middleware.ts
|
|
@@ -2351,6 +2388,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2351
2388
|
allowPrivateAddress;
|
|
2352
2389
|
userAgent;
|
|
2353
2390
|
onOutboxError;
|
|
2391
|
+
permanentFailureStatusCodes;
|
|
2354
2392
|
signatureTimeWindow;
|
|
2355
2393
|
skipSignatureVerification;
|
|
2356
2394
|
outboxRetryPolicy;
|
|
@@ -2432,6 +2470,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2432
2470
|
}));
|
|
2433
2471
|
this.userAgent = userAgent;
|
|
2434
2472
|
this.onOutboxError = options.onOutboxError;
|
|
2473
|
+
this.permanentFailureStatusCodes = options.permanentFailureStatusCodes ?? [404, 410];
|
|
2435
2474
|
this.signatureTimeWindow = options.signatureTimeWindow ?? { hours: 1 };
|
|
2436
2475
|
this.skipSignatureVerification = options.skipSignatureVerification ?? false;
|
|
2437
2476
|
this.outboxRetryPolicy = options.outboxRetryPolicy ?? createExponentialBackoffPolicy();
|
|
@@ -2562,6 +2601,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2562
2601
|
}) });
|
|
2563
2602
|
await this.sendActivity(keys, message.inboxes, activity, {
|
|
2564
2603
|
collectionSync: message.collectionSync,
|
|
2604
|
+
orderingKey: message.orderingKey,
|
|
2565
2605
|
context: context$1
|
|
2566
2606
|
});
|
|
2567
2607
|
}
|
|
@@ -2613,13 +2653,44 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2613
2653
|
tracerProvider: this.tracerProvider
|
|
2614
2654
|
});
|
|
2615
2655
|
try {
|
|
2616
|
-
this.onOutboxError?.(error, activity);
|
|
2656
|
+
await this.onOutboxError?.(error, activity);
|
|
2617
2657
|
} catch (error$1) {
|
|
2618
2658
|
logger$1.error("An unexpected error occurred in onError handler:\n{error}", {
|
|
2619
2659
|
...logData,
|
|
2620
2660
|
error: error$1
|
|
2621
2661
|
});
|
|
2622
2662
|
}
|
|
2663
|
+
if (error instanceof SendActivityError && this.permanentFailureStatusCodes.includes(error.statusCode)) {
|
|
2664
|
+
logger$1.warn("Permanent delivery failure for activity {activityId} to {inbox} ({status}); not retrying.", {
|
|
2665
|
+
...logData,
|
|
2666
|
+
status: error.statusCode
|
|
2667
|
+
});
|
|
2668
|
+
if (this.outboxPermanentFailureHandler != null) {
|
|
2669
|
+
const ctx = this.#createContext(new URL(message.baseUrl), _, { documentLoader: this.documentLoaderFactory(loaderOptions) });
|
|
2670
|
+
try {
|
|
2671
|
+
await this.outboxPermanentFailureHandler(ctx, {
|
|
2672
|
+
inbox: new URL(message.inbox),
|
|
2673
|
+
activity,
|
|
2674
|
+
error,
|
|
2675
|
+
statusCode: error.statusCode,
|
|
2676
|
+
actorIds: (message.actorIds ?? []).flatMap((id) => {
|
|
2677
|
+
try {
|
|
2678
|
+
return [new URL(id)];
|
|
2679
|
+
} catch {
|
|
2680
|
+
logger$1.warn("Invalid actorId URL in OutboxMessage: {id}", { id });
|
|
2681
|
+
return [];
|
|
2682
|
+
}
|
|
2683
|
+
})
|
|
2684
|
+
});
|
|
2685
|
+
} catch (handlerError) {
|
|
2686
|
+
logger$1.error("An unexpected error occurred in outboxPermanentFailureHandler:\n{error}", {
|
|
2687
|
+
...logData,
|
|
2688
|
+
error: handlerError
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
return;
|
|
2693
|
+
}
|
|
2623
2694
|
if (this.outboxQueue?.nativeRetrial) {
|
|
2624
2695
|
logger$1.error("Failed to send activity {activityId} to {inbox}; backend will handle retry:\n{error}", {
|
|
2625
2696
|
...logData,
|
|
@@ -2627,11 +2698,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2627
2698
|
});
|
|
2628
2699
|
throw error;
|
|
2629
2700
|
}
|
|
2630
|
-
const delay
|
|
2701
|
+
const delay = this.outboxRetryPolicy({
|
|
2631
2702
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2632
2703
|
attempts: message.attempt
|
|
2633
2704
|
});
|
|
2634
|
-
if (delay
|
|
2705
|
+
if (delay != null) {
|
|
2635
2706
|
logger$1.error("Failed to send activity {activityId} to {inbox} (attempt #{attempt}); retry...:\n{error}", {
|
|
2636
2707
|
...logData,
|
|
2637
2708
|
error
|
|
@@ -2639,7 +2710,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2639
2710
|
await this.outboxQueue?.enqueue({
|
|
2640
2711
|
...message,
|
|
2641
2712
|
attempt: message.attempt + 1
|
|
2642
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2713
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2643
2714
|
} else logger$1.error("Failed to send activity {activityId} to {inbox} after {attempt} attempts; giving up:\n{error}", {
|
|
2644
2715
|
...logData,
|
|
2645
2716
|
error
|
|
@@ -2726,11 +2797,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2726
2797
|
span$1.end();
|
|
2727
2798
|
throw error;
|
|
2728
2799
|
}
|
|
2729
|
-
const delay
|
|
2800
|
+
const delay = this.inboxRetryPolicy({
|
|
2730
2801
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2731
2802
|
attempts: message.attempt
|
|
2732
2803
|
});
|
|
2733
|
-
if (delay
|
|
2804
|
+
if (delay != null) {
|
|
2734
2805
|
logger$1.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2735
2806
|
error,
|
|
2736
2807
|
attempt: message.attempt,
|
|
@@ -2741,7 +2812,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2741
2812
|
await this.inboxQueue?.enqueue({
|
|
2742
2813
|
...message,
|
|
2743
2814
|
attempt: message.attempt + 1
|
|
2744
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2815
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2745
2816
|
} else logger$1.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2746
2817
|
error,
|
|
2747
2818
|
activityId: activity.id?.href,
|
|
@@ -2810,7 +2881,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2810
2881
|
"federation",
|
|
2811
2882
|
"outbox"
|
|
2812
2883
|
]);
|
|
2813
|
-
const { immediate, collectionSync, context: ctx } = options;
|
|
2884
|
+
const { immediate, collectionSync, orderingKey, context: ctx } = options;
|
|
2814
2885
|
if (activity.id == null) throw new TypeError("The activity to send must have an id.");
|
|
2815
2886
|
if (activity.actorId == null) throw new TypeError("The activity to send must have at least one actor property.");
|
|
2816
2887
|
else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
|
|
@@ -2898,6 +2969,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2898
2969
|
propagation.inject(context.active(), carrier);
|
|
2899
2970
|
const messages = [];
|
|
2900
2971
|
for (const inbox in inboxes) {
|
|
2972
|
+
const inboxOrigin = new URL(inbox).origin;
|
|
2973
|
+
const messageOrderingKey = orderingKey == null ? void 0 : `${orderingKey}\n${inboxOrigin}`;
|
|
2901
2974
|
const message = {
|
|
2902
2975
|
type: "outbox",
|
|
2903
2976
|
id: crypto.randomUUID(),
|
|
@@ -2908,16 +2981,33 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2908
2981
|
activityType: getTypeId(activity).href,
|
|
2909
2982
|
inbox,
|
|
2910
2983
|
sharedInbox: inboxes[inbox].sharedInbox,
|
|
2984
|
+
actorIds: [...inboxes[inbox].actorIds],
|
|
2911
2985
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2912
2986
|
attempt: 0,
|
|
2913
2987
|
headers: collectionSync == null ? {} : { "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox].actorIds) },
|
|
2988
|
+
orderingKey: messageOrderingKey,
|
|
2914
2989
|
traceContext: carrier
|
|
2915
2990
|
};
|
|
2916
|
-
messages.push(
|
|
2991
|
+
messages.push({
|
|
2992
|
+
message,
|
|
2993
|
+
orderingKey: messageOrderingKey
|
|
2994
|
+
});
|
|
2917
2995
|
}
|
|
2918
2996
|
const { outboxQueue } = this;
|
|
2919
2997
|
if (outboxQueue.enqueueMany == null) {
|
|
2920
|
-
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
2998
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
2999
|
+
const results = await Promise.allSettled(promises);
|
|
3000
|
+
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3001
|
+
if (errors.length > 0) {
|
|
3002
|
+
logger$1.error("Failed to enqueue activity {activityId} to send later: {errors}", {
|
|
3003
|
+
activityId: activity.id.href,
|
|
3004
|
+
errors
|
|
3005
|
+
});
|
|
3006
|
+
if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
|
|
3007
|
+
throw errors[0];
|
|
3008
|
+
}
|
|
3009
|
+
} else if (orderingKey != null) {
|
|
3010
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
2921
3011
|
const results = await Promise.allSettled(promises);
|
|
2922
3012
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
2923
3013
|
if (errors.length > 0) {
|
|
@@ -2929,7 +3019,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2929
3019
|
throw errors[0];
|
|
2930
3020
|
}
|
|
2931
3021
|
} else try {
|
|
2932
|
-
await outboxQueue.enqueueMany(messages);
|
|
3022
|
+
await outboxQueue.enqueueMany(messages.map((m) => m.message));
|
|
2933
3023
|
} catch (error) {
|
|
2934
3024
|
logger$1.error("Failed to enqueue activity {activityId} to send later: {error}", {
|
|
2935
3025
|
activityId: activity.id.href,
|
|
@@ -3645,20 +3735,25 @@ var ContextImpl = class ContextImpl {
|
|
|
3645
3735
|
} else keys = [sender];
|
|
3646
3736
|
if (keys.length < 1) throw new TypeError("The sender's keys must not be empty.");
|
|
3647
3737
|
for (const { privateKey } of keys) validateCryptoKey(privateKey, "private");
|
|
3648
|
-
const opts = { context: this };
|
|
3649
3738
|
let expandedRecipients;
|
|
3739
|
+
let collectionSync;
|
|
3650
3740
|
if (Array.isArray(recipients)) expandedRecipients = recipients;
|
|
3651
3741
|
else if (recipients === "followers") {
|
|
3652
3742
|
if (identifier == null) throw new Error("If recipients is \"followers\", sender must be an actor identifier or username.");
|
|
3653
3743
|
expandedRecipients = [];
|
|
3654
3744
|
for await (const recipient of this.getFollowers(identifier)) expandedRecipients.push(recipient);
|
|
3655
3745
|
if (options.syncCollection) try {
|
|
3656
|
-
|
|
3746
|
+
collectionSync = this.getFollowersUri(identifier).href;
|
|
3657
3747
|
} catch (error) {
|
|
3658
|
-
if (error instanceof RouterError)
|
|
3659
|
-
else throw error;
|
|
3748
|
+
if (!(error instanceof RouterError)) throw error;
|
|
3660
3749
|
}
|
|
3661
3750
|
} else expandedRecipients = [recipients];
|
|
3751
|
+
const opts = {
|
|
3752
|
+
context: this,
|
|
3753
|
+
orderingKey: options.orderingKey,
|
|
3754
|
+
collectionSync,
|
|
3755
|
+
immediate: options.immediate
|
|
3756
|
+
};
|
|
3662
3757
|
span.setAttribute("activitypub.inboxes", expandedRecipients.length);
|
|
3663
3758
|
for (const activityTransformer of this.federation.activityTransformers) activity = activityTransformer(activity, this);
|
|
3664
3759
|
span?.setAttribute("activitypub.activity.id", activity?.id?.href ?? "");
|
|
@@ -3705,10 +3800,11 @@ var ContextImpl = class ContextImpl {
|
|
|
3705
3800
|
activityId: activity.id?.href,
|
|
3706
3801
|
activityType: getTypeId(activity).href,
|
|
3707
3802
|
collectionSync: opts.collectionSync,
|
|
3803
|
+
orderingKey: options.orderingKey,
|
|
3708
3804
|
traceContext: carrier
|
|
3709
3805
|
};
|
|
3710
3806
|
if (!this.federation.manuallyStartQueue) this.federation._startQueueInternal(this.data);
|
|
3711
|
-
this.federation.fanoutQueue.enqueue(message);
|
|
3807
|
+
this.federation.fanoutQueue.enqueue(message, { orderingKey: options.orderingKey });
|
|
3712
3808
|
}
|
|
3713
3809
|
async *getFollowers(identifier) {
|
|
3714
3810
|
if (this.federation.followersCallbacks == null) throw new Error("No followers collection dispatcher registered.");
|
|
@@ -4060,8 +4156,10 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4060
4156
|
}
|
|
4061
4157
|
const carrier = {};
|
|
4062
4158
|
propagation.inject(context.active(), carrier);
|
|
4159
|
+
const orderingKey = options?.orderingKey;
|
|
4063
4160
|
const messages = [];
|
|
4064
4161
|
for (const inbox in inboxes) {
|
|
4162
|
+
const inboxUrl = new URL(inbox);
|
|
4065
4163
|
const message = {
|
|
4066
4164
|
type: "outbox",
|
|
4067
4165
|
id: crypto.randomUUID(),
|
|
@@ -4075,13 +4173,29 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4075
4173
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4076
4174
|
attempt: 0,
|
|
4077
4175
|
headers: {},
|
|
4176
|
+
orderingKey: orderingKey == null ? void 0 : `${orderingKey}\n${inboxUrl.origin}`,
|
|
4078
4177
|
traceContext: carrier
|
|
4079
4178
|
};
|
|
4080
|
-
messages.push(
|
|
4179
|
+
messages.push({
|
|
4180
|
+
message,
|
|
4181
|
+
orderingKey: message.orderingKey
|
|
4182
|
+
});
|
|
4081
4183
|
}
|
|
4082
4184
|
const { outboxQueue } = this.federation;
|
|
4083
4185
|
if (outboxQueue.enqueueMany == null) {
|
|
4084
|
-
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
4186
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
4187
|
+
const results = await Promise.allSettled(promises);
|
|
4188
|
+
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
4189
|
+
if (errors.length > 0) {
|
|
4190
|
+
logger$1.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", {
|
|
4191
|
+
activityId: this.activityId,
|
|
4192
|
+
errors
|
|
4193
|
+
});
|
|
4194
|
+
if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${this.activityId} to forward later.`);
|
|
4195
|
+
throw errors[0];
|
|
4196
|
+
}
|
|
4197
|
+
} else if (orderingKey != null) {
|
|
4198
|
+
const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
|
|
4085
4199
|
const results = await Promise.allSettled(promises);
|
|
4086
4200
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
4087
4201
|
if (errors.length > 0) {
|
|
@@ -4093,7 +4207,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4093
4207
|
throw errors[0];
|
|
4094
4208
|
}
|
|
4095
4209
|
} else try {
|
|
4096
|
-
await outboxQueue.enqueueMany(messages);
|
|
4210
|
+
await outboxQueue.enqueueMany(messages.map((m) => m.message));
|
|
4097
4211
|
} catch (error) {
|
|
4098
4212
|
logger$1.error("Failed to enqueue activity {activityId} to forward later:\n{error}", {
|
|
4099
4213
|
activityId: this.activityId,
|
|
@@ -4156,4 +4270,4 @@ function getRequestId(request) {
|
|
|
4156
4270
|
}
|
|
4157
4271
|
|
|
4158
4272
|
//#endregion
|
|
4159
|
-
export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, Router$1 as Router, RouterError, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, respondWithObject, respondWithObjectIfAcceptable };
|
|
4273
|
+
export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, Router$1 as Router, RouterError, SendActivityError, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };
|