@fedify/fedify 2.4.0-dev.1417 → 2.4.0-dev.1422
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/dist/{assert-OguE97r2.mjs → assert-DikXweDx.mjs} +1 -1
- package/dist/{assert_instance_of-DBC5X09g.mjs → assert_instance_of-C4Ri6VuN.mjs} +1 -1
- package/dist/{assert_not_equals-DkVK8oqV.mjs → assert_not_equals--wG9hV7u.mjs} +1 -1
- package/dist/{assert_rejects-DN60FHPX.mjs → assert_rejects-DQP-q39h.mjs} +2 -2
- package/dist/{assert_strict_equals-XEgZAlrj.mjs → assert_strict_equals-Dmjbg-bA.mjs} +1 -1
- package/dist/{assert_throws-BOkhLGYc.mjs → assert_throws-4NwKEy2q.mjs} +1 -1
- package/dist/{builder-CU98OOiD.mjs → builder-Gef_ZeDE.mjs} +23 -3
- package/dist/codec-Bf-rTqks.mjs +94 -0
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +3 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-DVoTs_wM.mjs → context-BrIOaBSs.mjs} +7 -1
- package/dist/{context-BBVLF7lx.d.cts → context-BuGH_Vft.d.cts} +286 -70
- package/dist/{context-BU6jSQdo.d.ts → context-CLtZxCu6.d.ts} +285 -70
- package/dist/{deno-Dhn909W6.mjs → deno-BmD7XRaO.mjs} +1 -1
- package/dist/{docloader-CX8Auxrr.mjs → docloader-B8AJowCx.mjs} +2 -2
- package/dist/federation/builder.test.mjs +5 -5
- package/dist/federation/circuit-breaker.test.mjs +5 -5
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +13 -13
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +4 -4
- package/dist/federation/middleware.test.mjs +200 -19
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +5 -260
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +5 -5
- package/dist/federation/send.test.mjs +10 -10
- package/dist/federation/tasks/codec.test.d.mts +2 -0
- package/dist/federation/tasks/codec.test.mjs +292 -0
- package/dist/federation/tasks/tasks.test.d.mts +2 -0
- package/dist/federation/tasks/tasks.test.mjs +651 -0
- package/dist/federation/temporal.test.mjs +4 -4
- package/dist/federation/webfinger.test.mjs +6 -6
- package/dist/{http-CsSSDB5j.cjs → http-BCSQJ_gv.cjs} +1 -1
- package/dist/{http-DndWw3Rs.js → http-CJ0WNyqA.js} +1 -1
- package/dist/{http-iapcKTk-.mjs → http-GQoPA_YT.mjs} +4 -4
- package/dist/{key-b17Uu8wX.mjs → key-BLy_TeTg.mjs} +2 -2
- package/dist/{kv-cache-CLo3nRjl.js → kv-cache-CjEcb9qH.js} +1 -1
- package/dist/{kv-cache-BIngyLxt.cjs → kv-cache-DXwu7BtY.cjs} +1 -1
- package/dist/{kv-cache-DcsWACki.mjs → kv-cache-pw-kBdVz.mjs} +1 -1
- package/dist/{ld-B1503hdI.mjs → ld-CWgxPlZq.mjs} +3 -3
- package/dist/{metrics-DSV9HQUk.mjs → metrics-DUKoLd_E.mjs} +1 -1
- package/dist/{middleware-DT5sfJam.js → middleware-2Us0G3Iy.js} +277 -10
- package/dist/{middleware-DA8JjaXv.cjs → middleware-BiCk4wGY.cjs} +277 -10
- package/dist/{middleware-Bb9gR5Ro.mjs → middleware-Dq-HhJHd.mjs} +1 -1
- package/dist/{middleware-Dh1xDMbI.mjs → middleware-PZaroDUk.mjs} +182 -23
- package/dist/{mod-C0F6kvgS.d.cts → mod-DRokcHeU.d.cts} +1 -1
- package/dist/{mod-vPYVoa5n.d.ts → mod-r-1xOW_C.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +4 -4
- package/dist/mq-CvJAzRz5.mjs +260 -0
- package/dist/nodeinfo/client.test.mjs +3 -3
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/{outgoing-jsonld-L_DbOaFe.mjs → outgoing-jsonld-BgFLCJQ_.mjs} +1 -1
- package/dist/{owner-PCw-OkL0.mjs → owner-U0Z8Ex6i.mjs} +2 -2
- package/dist/{proof-CJCLdaV3.cjs → proof-DA3hLGSO.cjs} +1 -1
- package/dist/{proof-BhbSD4bP.js → proof-f7K32nz7.js} +1 -1
- package/dist/{proof-Dacxh41h.mjs → proof-nb5tfciW.mjs} +5 -5
- package/dist/{send-Cdsbc_Vj.mjs → send-CLfW5Fdf.mjs} +3 -3
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +8 -8
- package/dist/sig/key.test.mjs +6 -6
- package/dist/sig/ld.test.mjs +7 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +8 -8
- package/dist/{std__assert-BBjXFNOb.mjs → std__assert-BTEgfoJo.mjs} +4 -4
- package/dist/{temporal-BMMqjhOp.mjs → temporal-2ry_jdCK.mjs} +1 -1
- package/dist/testing/mod.d.mts +378 -7
- package/dist/testing/mod.mjs +3 -2
- package/dist/testing-CjYPStvE.mjs +55 -0
- package/dist/utils/docloader.test.mjs +6 -6
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +9 -7
- /package/dist/{accept-CPkZzmGN.mjs → accept-CceiKpCy.mjs} +0 -0
- /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-BeTGV3wc.mjs} +0 -0
- /package/dist/{assert_equals-C-ZRDbaf.mjs → assert_equals-Ew3jOFa3.mjs} +0 -0
- /package/dist/{circuit-breaker-CSWsyoef.mjs → circuit-breaker-hJBB6jwA.mjs} +0 -0
- /package/dist/{client-ByXmQhYD.mjs → client-B_A6mfn3.mjs} +0 -0
- /package/dist/{collection-Cc3DVAhE.mjs → collection-Dp5ky45w.mjs} +0 -0
- /package/dist/{keycache-BeU0LCII.mjs → keycache-CaOR6NYg.mjs} +0 -0
- /package/dist/{keys-DGu1NFwu.mjs → keys-C3kae-6B.mjs} +0 -0
- /package/dist/{kv-rV3vodCc.mjs → kv-x2IvBUyq.mjs} +0 -0
- /package/dist/{negotiation-DDstyBvc.mjs → negotiation-m_L2nyS3.mjs} +0 -0
- /package/dist/{public-audience-Cvbr2Gzt.mjs → public-audience-N3pyOx2p.mjs} +0 -0
- /package/dist/{retry-CXg_MBI-.mjs → retry-DI4O-zYl.mjs} +0 -0
- /package/dist/{types-J53Kw7so.mjs → types-BFowWFTT.mjs} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-
|
|
7
|
-
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-BmD7XRaO.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-DUKoLd_E.mjs";
|
|
6
|
+
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CceiKpCy.mjs";
|
|
7
|
+
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-BLy_TeTg.mjs";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { CryptographicKey } from "@fedify/vocab";
|
|
10
10
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-BmD7XRaO.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-DUKoLd_E.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-
|
|
3
|
+
import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-CJ0WNyqA.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { curry } from "es-toolkit";
|
|
6
6
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
require("./chunk-DDcVe30Y.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-BCSQJ_gv.cjs");
|
|
5
5
|
let _logtape_logtape = require("@logtape/logtape");
|
|
6
6
|
let es_toolkit = require("es-toolkit");
|
|
7
7
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-DUKoLd_E.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { n as fetchKey, o as validateCryptoKey } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-BmD7XRaO.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-DUKoLd_E.mjs";
|
|
6
|
+
import { n as fetchKey, o as validateCryptoKey } from "./key-BLy_TeTg.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-BmD7XRaO.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
-
import { A as formatAcceptSignature, D as recordOutboxEnqueue, E as recordOutboxActivity, F as version, O as recordWebFingerHandle, P as name, S as recordCollectionTotalItems, T as recordInboxActivity, a as verifyRequestDetailed, b as recordCollectionPageItems, d as validateCryptoKey, f as getDurationMs, g as isAbortError, h as instrumentDocumentLoader, i as verifyRequest, k as registerQueueDepthGauge, m as getRemoteHost, n as parseRfc9421SignatureInput, o as exportJwk, p as getFederationMetrics, t as doubleKnock, u as importJwk, v as recordCircuitBreakerStateChange, w as recordFanoutRecipients, x as recordCollectionRequest, y as recordCollectionDispatchDuration } from "./http-
|
|
6
|
-
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-
|
|
5
|
+
import { A as formatAcceptSignature, D as recordOutboxEnqueue, E as recordOutboxActivity, F as version, O as recordWebFingerHandle, P as name, S as recordCollectionTotalItems, T as recordInboxActivity, a as verifyRequestDetailed, b as recordCollectionPageItems, d as validateCryptoKey, f as getDurationMs, g as isAbortError, h as instrumentDocumentLoader, i as verifyRequest, k as registerQueueDepthGauge, m as getRemoteHost, n as parseRfc9421SignatureInput, o as exportJwk, p as getFederationMetrics, t as doubleKnock, u as importJwk, v as recordCircuitBreakerStateChange, w as recordFanoutRecipients, x as recordCollectionRequest, y as recordCollectionDispatchDuration } from "./http-CJ0WNyqA.js";
|
|
6
|
+
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-f7K32nz7.js";
|
|
7
7
|
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-CjEcb9qH.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
11
11
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
@@ -17,6 +17,7 @@ import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_
|
|
|
17
17
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
18
18
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
19
19
|
import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
20
|
+
import { parse, stringifyAsync } from "devalue";
|
|
20
21
|
import { domainToASCII } from "node:url";
|
|
21
22
|
//#region src/federation/activity-listener.ts
|
|
22
23
|
var ActivityListenerSet = class {
|
|
@@ -107,6 +108,7 @@ var FederationBuilderImpl = class {
|
|
|
107
108
|
idempotencyStrategy;
|
|
108
109
|
collectionTypeIds;
|
|
109
110
|
collectionCallbacks;
|
|
111
|
+
taskDefinitions;
|
|
110
112
|
/**
|
|
111
113
|
* Symbol registry for unique identification of unnamed symbols.
|
|
112
114
|
*/
|
|
@@ -117,6 +119,7 @@ var FederationBuilderImpl = class {
|
|
|
117
119
|
this.objectTypeIds = {};
|
|
118
120
|
this.collectionCallbacks = {};
|
|
119
121
|
this.collectionTypeIds = {};
|
|
122
|
+
this.taskDefinitions = /* @__PURE__ */ new Map();
|
|
120
123
|
}
|
|
121
124
|
/**
|
|
122
125
|
* Builds the federation object.
|
|
@@ -155,6 +158,7 @@ var FederationBuilderImpl = class {
|
|
|
155
158
|
f.unverifiedActivityHandler = this.unverifiedActivityHandler;
|
|
156
159
|
f.outboxPermanentFailureHandler = this.outboxPermanentFailureHandler;
|
|
157
160
|
f.idempotencyStrategy = this.idempotencyStrategy;
|
|
161
|
+
f.taskDefinitions = new Map(this.taskDefinitions);
|
|
158
162
|
return f;
|
|
159
163
|
}
|
|
160
164
|
_getTracer() {
|
|
@@ -287,6 +291,23 @@ var FederationBuilderImpl = class {
|
|
|
287
291
|
setWebFingerLinksDispatcher(dispatcher) {
|
|
288
292
|
this.webFingerLinksDispatcher = dispatcher;
|
|
289
293
|
}
|
|
294
|
+
defineTask(name, options) {
|
|
295
|
+
if (this.taskDefinitions.has(name)) throw new TypeError(`Task ${JSON.stringify(name)} is already defined.`);
|
|
296
|
+
const handle = {
|
|
297
|
+
name,
|
|
298
|
+
schema: options.schema
|
|
299
|
+
};
|
|
300
|
+
this.taskDefinitions.set(name, {
|
|
301
|
+
name,
|
|
302
|
+
schema: options.schema,
|
|
303
|
+
handle,
|
|
304
|
+
handler: options.handler,
|
|
305
|
+
onError: options.onError,
|
|
306
|
+
retryPolicy: options.retryPolicy,
|
|
307
|
+
queue: options.queue
|
|
308
|
+
});
|
|
309
|
+
return handle;
|
|
310
|
+
}
|
|
290
311
|
/**
|
|
291
312
|
* The RFC 6570 template-literal `path` overloads were removed for
|
|
292
313
|
* type-checking efficiency, so the URI variable types can no longer be
|
|
@@ -1392,7 +1413,7 @@ function acceptsJsonLd(request) {
|
|
|
1392
1413
|
}
|
|
1393
1414
|
//#endregion
|
|
1394
1415
|
//#region src/federation/temporal.ts
|
|
1395
|
-
function isPlainObject(value) {
|
|
1416
|
+
function isPlainObject$1(value) {
|
|
1396
1417
|
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1397
1418
|
}
|
|
1398
1419
|
function normalizeDateTimeLiteral(value) {
|
|
@@ -1430,11 +1451,11 @@ const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
|
1430
1451
|
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1431
1452
|
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1432
1453
|
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1433
|
-
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1454
|
+
return isPlainObject$1(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1434
1455
|
}
|
|
1435
1456
|
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1436
1457
|
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1437
|
-
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1458
|
+
if (!isPlainObject$1(value) || !("@value" in value)) return false;
|
|
1438
1459
|
const literal = value["@value"];
|
|
1439
1460
|
if (typeof literal === "boolean") return false;
|
|
1440
1461
|
if (typeof literal !== "string") return false;
|
|
@@ -1444,11 +1465,11 @@ function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
|
1444
1465
|
}
|
|
1445
1466
|
function hasMalformedExpandedDurationLiteral(value) {
|
|
1446
1467
|
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1447
|
-
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1468
|
+
return isPlainObject$1(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1448
1469
|
}
|
|
1449
1470
|
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1450
1471
|
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1451
|
-
if (!isPlainObject(value)) return false;
|
|
1472
|
+
if (!isPlainObject$1(value)) return false;
|
|
1452
1473
|
if (visited.has(value)) return false;
|
|
1453
1474
|
visited.add(value);
|
|
1454
1475
|
if ("@value" in value) return false;
|
|
@@ -3552,6 +3573,94 @@ function createExponentialBackoffPolicy(options = {}) {
|
|
|
3552
3573
|
};
|
|
3553
3574
|
}
|
|
3554
3575
|
//#endregion
|
|
3576
|
+
//#region src/federation/tasks/codec.ts
|
|
3577
|
+
var TaskCodec = class TaskCodec {
|
|
3578
|
+
options;
|
|
3579
|
+
constructor(options) {
|
|
3580
|
+
this.options = options;
|
|
3581
|
+
}
|
|
3582
|
+
serialize = (data) => stringifyAsync(data, { Vocab: this.#stringifyVocab });
|
|
3583
|
+
deserialize = (raw) => this.#revive(/* @__PURE__ */ new Map())(parse(raw, { Vocab: VocabHolder.from }));
|
|
3584
|
+
/** Validates `data` against `schema`, then serializes it. */
|
|
3585
|
+
encode = async (schema, data) => this.serialize(await TaskCodec.validate(schema, data));
|
|
3586
|
+
/** Deserializes `raw`, then validates the result against `schema`. */
|
|
3587
|
+
decode = async (schema, raw) => TaskCodec.validate(schema, await this.deserialize(raw));
|
|
3588
|
+
static validate = async (schema, data) => getValueIfSchema(await schema["~standard"].validate(data));
|
|
3589
|
+
#stringifyVocab = (value) => isVocab(value) && this.#toWire(value);
|
|
3590
|
+
#toWire = async (value) => ({
|
|
3591
|
+
kind: value instanceof Link ? "link" : "object",
|
|
3592
|
+
jsonLd: await value.toJsonLd({
|
|
3593
|
+
format: "expand",
|
|
3594
|
+
...this.options
|
|
3595
|
+
})
|
|
3596
|
+
});
|
|
3597
|
+
#revive = (seen) => {
|
|
3598
|
+
const inner = async (node) => {
|
|
3599
|
+
if (node === null || typeof node !== "object") return node;
|
|
3600
|
+
if (seen.has(node)) return seen.get(node);
|
|
3601
|
+
for (const reviver of this.#classRevivers) {
|
|
3602
|
+
const out = reviver(seen, inner, node);
|
|
3603
|
+
if (out !== void 0) return await out;
|
|
3604
|
+
}
|
|
3605
|
+
return node;
|
|
3606
|
+
};
|
|
3607
|
+
return inner;
|
|
3608
|
+
};
|
|
3609
|
+
#classRevivers = [
|
|
3610
|
+
classReviver(isInstanceOf(VocabHolder), ({ kind, jsonLd }) => kind === "link" ? Link.fromJsonLd(jsonLd, this.options) : Object$1.fromJsonLd(jsonLd, this.options), () => {}),
|
|
3611
|
+
classReviver(isInstanceOf(Array), () => [], async (revive, node, arr) => {
|
|
3612
|
+
for (const item of await Array.fromAsync(node, revive)) arr.push(item);
|
|
3613
|
+
}),
|
|
3614
|
+
classReviver(isInstanceOf(Map), () => /* @__PURE__ */ new Map(), async (revive, node, map) => {
|
|
3615
|
+
for (const [k, v] of node) map.set(await revive(k), await revive(v));
|
|
3616
|
+
}),
|
|
3617
|
+
classReviver(isInstanceOf(Set), () => /* @__PURE__ */ new Set(), async (revive, node, set) => {
|
|
3618
|
+
for (const v of await Array.fromAsync(node, revive)) set.add(v);
|
|
3619
|
+
}),
|
|
3620
|
+
classReviver(isPlainObject, () => ({}), async (revive, node, obj) => {
|
|
3621
|
+
for (const [k, v] of globalThis.Object.entries(node)) obj[k] = await revive(v);
|
|
3622
|
+
})
|
|
3623
|
+
];
|
|
3624
|
+
};
|
|
3625
|
+
const isVocab = (value) => value instanceof Object$1 || value instanceof Link;
|
|
3626
|
+
const isPlainObject = (value) => value === null || typeof value !== "object" ? false : isObjectPrototype(globalThis.Object.getPrototypeOf(value));
|
|
3627
|
+
const isObjectPrototype = (proto) => proto === null || proto === globalThis.Object.prototype;
|
|
3628
|
+
const isInstanceOf = (cls) => (v) => v instanceof cls;
|
|
3629
|
+
function getValueIfSchema(result) {
|
|
3630
|
+
assertSchema(result);
|
|
3631
|
+
return result.value;
|
|
3632
|
+
}
|
|
3633
|
+
function assertSchema(result) {
|
|
3634
|
+
if (result.issues && result.issues.length > 0) throw new TypeError(`Task data failed schema validation: ${JSON.stringify(result.issues)}`);
|
|
3635
|
+
}
|
|
3636
|
+
/**
|
|
3637
|
+
* A vocabulary object parked by the synchronous decode reviver, held until
|
|
3638
|
+
* the async revive pass can `fromJsonLd()` it back into an instance.
|
|
3639
|
+
*/
|
|
3640
|
+
var VocabHolder = class VocabHolder {
|
|
3641
|
+
kind;
|
|
3642
|
+
jsonLd;
|
|
3643
|
+
constructor(kind, jsonLd) {
|
|
3644
|
+
this.kind = kind;
|
|
3645
|
+
this.jsonLd = jsonLd;
|
|
3646
|
+
}
|
|
3647
|
+
static from = ({ kind, jsonLd }) => new VocabHolder(kind, jsonLd);
|
|
3648
|
+
};
|
|
3649
|
+
/**
|
|
3650
|
+
* Ties a container filter to its empty-shell `init` and child-filling `set`
|
|
3651
|
+
* through one type parameter—a correlation the heterogeneous reviver list
|
|
3652
|
+
* cannot carry, which previously forced `@ts-ignore` at the dispatch site.
|
|
3653
|
+
*/
|
|
3654
|
+
const classReviver = (filter, init, set) => (seen, revive, node) => {
|
|
3655
|
+
if (!filter(node)) return void 0;
|
|
3656
|
+
return (async () => {
|
|
3657
|
+
const out = await init(node);
|
|
3658
|
+
seen.set(node, out);
|
|
3659
|
+
await set(revive, node, out);
|
|
3660
|
+
return out;
|
|
3661
|
+
})();
|
|
3662
|
+
};
|
|
3663
|
+
//#endregion
|
|
3555
3664
|
//#region src/federation/webfinger.ts
|
|
3556
3665
|
const logger = getLogger([
|
|
3557
3666
|
"fedify",
|
|
@@ -3876,9 +3985,12 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3876
3985
|
inboxQueue;
|
|
3877
3986
|
outboxQueue;
|
|
3878
3987
|
fanoutQueue;
|
|
3988
|
+
taskQueue;
|
|
3879
3989
|
inboxQueueStarted;
|
|
3880
3990
|
outboxQueueStarted;
|
|
3881
3991
|
fanoutQueueStarted;
|
|
3992
|
+
taskQueueStarted;
|
|
3993
|
+
startedTaskQueues;
|
|
3882
3994
|
manuallyStartQueue;
|
|
3883
3995
|
origin;
|
|
3884
3996
|
documentLoaderFactory;
|
|
@@ -3892,6 +4004,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3892
4004
|
skipSignatureVerification;
|
|
3893
4005
|
outboxRetryPolicy;
|
|
3894
4006
|
inboxRetryPolicy;
|
|
4007
|
+
taskRetryPolicy;
|
|
4008
|
+
taskQueueResolution;
|
|
3895
4009
|
circuitBreaker;
|
|
3896
4010
|
activityTransformers;
|
|
3897
4011
|
_tracerProvider;
|
|
@@ -3937,14 +4051,17 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3937
4051
|
this.inboxQueue = void 0;
|
|
3938
4052
|
this.outboxQueue = void 0;
|
|
3939
4053
|
this.fanoutQueue = void 0;
|
|
4054
|
+
this.taskQueue = void 0;
|
|
3940
4055
|
} else if ("enqueue" in options.queue && "listen" in options.queue) {
|
|
3941
4056
|
this.inboxQueue = options.queue;
|
|
3942
4057
|
this.outboxQueue = options.queue;
|
|
3943
4058
|
this.fanoutQueue = options.queue;
|
|
4059
|
+
this.taskQueue = void 0;
|
|
3944
4060
|
} else {
|
|
3945
4061
|
this.inboxQueue = options.queue.inbox;
|
|
3946
4062
|
this.outboxQueue = options.queue.outbox;
|
|
3947
4063
|
this.fanoutQueue = options.queue.fanout;
|
|
4064
|
+
this.taskQueue = options.queue.task;
|
|
3948
4065
|
}
|
|
3949
4066
|
if (options.circuitBreaker !== false && this.outboxQueue != null) {
|
|
3950
4067
|
this.circuitBreaker = new CircuitBreaker({
|
|
@@ -3968,6 +4085,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3968
4085
|
this.inboxQueueStarted = false;
|
|
3969
4086
|
this.outboxQueueStarted = false;
|
|
3970
4087
|
this.fanoutQueueStarted = false;
|
|
4088
|
+
this.taskQueueStarted = false;
|
|
4089
|
+
this.startedTaskQueues = /* @__PURE__ */ new Set();
|
|
3971
4090
|
this.manuallyStartQueue = options.manuallyStartQueue ?? false;
|
|
3972
4091
|
if (options.origin != null) if (typeof options.origin === "string") {
|
|
3973
4092
|
if (!URL.canParse(options.origin) || !options.origin.match(/^https?:\/\//)) throw new TypeError(`Invalid origin: ${JSON.stringify(options.origin)}`);
|
|
@@ -4049,6 +4168,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4049
4168
|
this.inboxChallengePolicy = options.inboxChallengePolicy;
|
|
4050
4169
|
this.outboxRetryPolicy = options.outboxRetryPolicy ?? createExponentialBackoffPolicy();
|
|
4051
4170
|
this.inboxRetryPolicy = options.inboxRetryPolicy ?? createExponentialBackoffPolicy();
|
|
4171
|
+
this.taskRetryPolicy = options.taskRetryPolicy ?? createExponentialBackoffPolicy();
|
|
4172
|
+
this.taskQueueResolution = options.taskQueueResolution ?? "fallback";
|
|
4052
4173
|
this.activityTransformers = options.activityTransformers ?? getDefaultActivityTransformers();
|
|
4053
4174
|
this._tracerProvider = options.tracerProvider;
|
|
4054
4175
|
if (benchmarkMode) {
|
|
@@ -4097,8 +4218,14 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4097
4218
|
_getTracer() {
|
|
4098
4219
|
return this.tracerProvider.getTracer(name, version);
|
|
4099
4220
|
}
|
|
4221
|
+
resolveTaskQueue(taskName) {
|
|
4222
|
+
const resolved = this.taskDefinitions.get(taskName)?.queue ?? this.taskQueue;
|
|
4223
|
+
if (resolved != null) return resolved;
|
|
4224
|
+
return this.taskQueueResolution === "strict" ? void 0 : this.outboxQueue;
|
|
4225
|
+
}
|
|
4100
4226
|
async _startQueueInternal(ctxData, signal, queue) {
|
|
4101
|
-
|
|
4227
|
+
const hasDedicatedTaskQueue = [...this.taskDefinitions.values()].some((def) => def.queue != null);
|
|
4228
|
+
if (this.inboxQueue == null && this.outboxQueue == null && this.fanoutQueue == null && this.taskQueue == null && !hasDedicatedTaskQueue) return;
|
|
4102
4229
|
const logger = getLogger([
|
|
4103
4230
|
"fedify",
|
|
4104
4231
|
"federation",
|
|
@@ -4120,6 +4247,26 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4120
4247
|
this.fanoutQueueStarted = true;
|
|
4121
4248
|
promises.push(this.fanoutQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
4122
4249
|
}
|
|
4250
|
+
if (this.taskQueue != null && this.taskQueue !== this.inboxQueue && this.taskQueue !== this.outboxQueue && this.taskQueue !== this.fanoutQueue && (queue == null || queue === "task") && !this.taskQueueStarted) {
|
|
4251
|
+
logger.debug("Starting a task worker.");
|
|
4252
|
+
this.taskQueueStarted = true;
|
|
4253
|
+
promises.push(this.taskQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
4254
|
+
}
|
|
4255
|
+
if (queue == null || queue === "task") {
|
|
4256
|
+
const standardQueues = new Set([
|
|
4257
|
+
this.inboxQueue,
|
|
4258
|
+
this.outboxQueue,
|
|
4259
|
+
this.fanoutQueue,
|
|
4260
|
+
this.taskQueue
|
|
4261
|
+
].filter((q) => q != null));
|
|
4262
|
+
for (const def of this.taskDefinitions.values()) {
|
|
4263
|
+
const taskQueue = def.queue;
|
|
4264
|
+
if (taskQueue == null || standardQueues.has(taskQueue) || this.startedTaskQueues.has(taskQueue)) continue;
|
|
4265
|
+
logger.debug("Starting a worker for a dedicated per-task queue.");
|
|
4266
|
+
this.startedTaskQueues.add(taskQueue);
|
|
4267
|
+
promises.push(taskQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4123
4270
|
await Promise.all(promises);
|
|
4124
4271
|
}
|
|
4125
4272
|
processQueuedTask(contextData, message) {
|
|
@@ -4241,7 +4388,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4241
4388
|
}
|
|
4242
4389
|
});
|
|
4243
4390
|
});
|
|
4244
|
-
}
|
|
4391
|
+
} else if (message.type === "task") await this.#listenTaskMessage(contextData, message);
|
|
4245
4392
|
});
|
|
4246
4393
|
}
|
|
4247
4394
|
async #listenFanoutMessage(data, message) {
|
|
@@ -4805,6 +4952,77 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4805
4952
|
listenerSpan.end();
|
|
4806
4953
|
});
|
|
4807
4954
|
}
|
|
4955
|
+
async #listenTaskMessage(contextData, message) {
|
|
4956
|
+
const logger = getLogger([
|
|
4957
|
+
"fedify",
|
|
4958
|
+
"federation",
|
|
4959
|
+
"task"
|
|
4960
|
+
]);
|
|
4961
|
+
const def = this.taskDefinitions.get(message.taskName);
|
|
4962
|
+
if (def == null) {
|
|
4963
|
+
logger.warn("Received a custom task {taskName} with no registered handler; dropping.", { taskName: message.taskName });
|
|
4964
|
+
return;
|
|
4965
|
+
}
|
|
4966
|
+
const context = this.#createContext(new URL(message.baseUrl), contextData);
|
|
4967
|
+
let data;
|
|
4968
|
+
try {
|
|
4969
|
+
data = await context.codec.decode(def.schema, message.data);
|
|
4970
|
+
} catch (error) {
|
|
4971
|
+
logger.error("Custom task {taskName} payload could not be decoded or validated; dropping:\n{error}", {
|
|
4972
|
+
taskName: message.taskName,
|
|
4973
|
+
error
|
|
4974
|
+
});
|
|
4975
|
+
return;
|
|
4976
|
+
}
|
|
4977
|
+
try {
|
|
4978
|
+
await def.handler(context, data);
|
|
4979
|
+
} catch (error) {
|
|
4980
|
+
if (def.onError != null) try {
|
|
4981
|
+
await def.onError(context, error, data);
|
|
4982
|
+
} catch (onErrorError) {
|
|
4983
|
+
logger.error("onError for custom task {taskName} threw:\n{error}", {
|
|
4984
|
+
taskName: message.taskName,
|
|
4985
|
+
error: onErrorError
|
|
4986
|
+
});
|
|
4987
|
+
}
|
|
4988
|
+
const queue = this.resolveTaskQueue(def.name);
|
|
4989
|
+
if (queue?.nativeRetrial) throw error;
|
|
4990
|
+
const retryPolicy = def.retryPolicy ?? this.taskRetryPolicy;
|
|
4991
|
+
let elapsedTime = Temporal.Duration.from({ seconds: 0 });
|
|
4992
|
+
try {
|
|
4993
|
+
elapsedTime = Temporal.Instant.from(message.started).until(Temporal.Now.instant());
|
|
4994
|
+
} catch (parseError) {
|
|
4995
|
+
logger.error("Custom task {taskName} has an unparsable started time {started}; treating elapsedTime as zero:\n{error}", {
|
|
4996
|
+
taskName: message.taskName,
|
|
4997
|
+
started: message.started,
|
|
4998
|
+
error: parseError
|
|
4999
|
+
});
|
|
5000
|
+
}
|
|
5001
|
+
const delay = retryPolicy({
|
|
5002
|
+
elapsedTime,
|
|
5003
|
+
attempts: message.attempt
|
|
5004
|
+
});
|
|
5005
|
+
if (delay != null && queue != null) {
|
|
5006
|
+
logger.error("Custom task {taskName} failed (attempt #{attempt}); retry...:\n{error}", {
|
|
5007
|
+
taskName: message.taskName,
|
|
5008
|
+
attempt: message.attempt,
|
|
5009
|
+
error
|
|
5010
|
+
});
|
|
5011
|
+
const retryMessage = {
|
|
5012
|
+
...message,
|
|
5013
|
+
attempt: message.attempt + 1
|
|
5014
|
+
};
|
|
5015
|
+
await queue.enqueue(retryMessage, {
|
|
5016
|
+
delay: clampNegativeDelay(delay),
|
|
5017
|
+
orderingKey: message.orderingKey
|
|
5018
|
+
});
|
|
5019
|
+
} else logger.error("Custom task {taskName} failed after {attempt} attempts; giving up:\n{error}", {
|
|
5020
|
+
taskName: message.taskName,
|
|
5021
|
+
attempt: message.attempt,
|
|
5022
|
+
error
|
|
5023
|
+
});
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
4808
5026
|
startQueue(contextData, options = {}) {
|
|
4809
5027
|
return this._startQueueInternal(contextData, options.signal, options.queue);
|
|
4810
5028
|
}
|
|
@@ -5381,6 +5599,7 @@ var ContextImpl = class ContextImpl {
|
|
|
5381
5599
|
documentLoader;
|
|
5382
5600
|
contextLoader;
|
|
5383
5601
|
invokedFromActorKeyPairsDispatcher;
|
|
5602
|
+
#codec;
|
|
5384
5603
|
constructor({ url, federation, data, documentLoader, contextLoader, invokedFromActorKeyPairsDispatcher }) {
|
|
5385
5604
|
this.url = url;
|
|
5386
5605
|
this.federation = federation;
|
|
@@ -5389,6 +5608,15 @@ var ContextImpl = class ContextImpl {
|
|
|
5389
5608
|
this.contextLoader = contextLoader;
|
|
5390
5609
|
this.invokedFromActorKeyPairsDispatcher = invokedFromActorKeyPairsDispatcher;
|
|
5391
5610
|
}
|
|
5611
|
+
/**
|
|
5612
|
+
* A {@link TaskCodec} bound to this context's loaders, used to encode
|
|
5613
|
+
* and decode custom task payloads. Lazily created and cached so a context
|
|
5614
|
+
* that never enqueues or dispatches a task pays nothing.
|
|
5615
|
+
* @internal
|
|
5616
|
+
*/
|
|
5617
|
+
get codec() {
|
|
5618
|
+
return this.#codec ??= new TaskCodec(this);
|
|
5619
|
+
}
|
|
5392
5620
|
clone(data) {
|
|
5393
5621
|
return new ContextImpl({
|
|
5394
5622
|
url: this.url,
|
|
@@ -5707,6 +5935,45 @@ var ContextImpl = class ContextImpl {
|
|
|
5707
5935
|
allowPrivateAddress: this.federation.allowPrivateAddress
|
|
5708
5936
|
});
|
|
5709
5937
|
}
|
|
5938
|
+
async enqueueTask(task, data, options = {}) {
|
|
5939
|
+
await this.#enqueueTasks(task, [data], options);
|
|
5940
|
+
}
|
|
5941
|
+
async enqueueTaskMany(task, payloads, options = {}) {
|
|
5942
|
+
await this.#enqueueTasks(task, payloads, options);
|
|
5943
|
+
}
|
|
5944
|
+
async #enqueueTasks(task, items, options) {
|
|
5945
|
+
const def = this.federation.taskDefinitions.get(task.name);
|
|
5946
|
+
if (def == null || def.handle !== task) throw new TypeError(`Task ${JSON.stringify(task.name)} is not defined on this federation; pass a handle returned by its defineTask().`);
|
|
5947
|
+
const queue = this.federation.resolveTaskQueue(task.name);
|
|
5948
|
+
if (queue == null) throw new TypeError("No message queue is configured for tasks; pass `queue` to createFederation() or to defineTask().");
|
|
5949
|
+
if (items.length < 1) return;
|
|
5950
|
+
const delay = options.delay == null ? void 0 : Temporal.Duration.from(options.delay);
|
|
5951
|
+
const messages = await Promise.all(items.map(this.#encodeTaskMessage(task, options)));
|
|
5952
|
+
if (!this.federation.manuallyStartQueue) this.federation._startQueueInternal(this.data);
|
|
5953
|
+
const enqueueOptions = {
|
|
5954
|
+
delay,
|
|
5955
|
+
orderingKey: options.orderingKey
|
|
5956
|
+
};
|
|
5957
|
+
if (messages.length === 1) await queue.enqueue(messages[0], enqueueOptions);
|
|
5958
|
+
else if (queue.enqueueMany != null) await queue.enqueueMany(messages, enqueueOptions);
|
|
5959
|
+
else await Promise.all(messages.map((m) => queue.enqueue(m, enqueueOptions)));
|
|
5960
|
+
}
|
|
5961
|
+
#encodeTaskMessage = (task, options) => async (data) => {
|
|
5962
|
+
const encoded = await this.codec.encode(task.schema, data);
|
|
5963
|
+
const carrier = {};
|
|
5964
|
+
propagation.inject(context.active(), carrier);
|
|
5965
|
+
return {
|
|
5966
|
+
type: "task",
|
|
5967
|
+
id: crypto.randomUUID(),
|
|
5968
|
+
baseUrl: this.origin,
|
|
5969
|
+
taskName: task.name,
|
|
5970
|
+
data: encoded,
|
|
5971
|
+
started: Temporal.Now.instant().toString(),
|
|
5972
|
+
attempt: 0,
|
|
5973
|
+
orderingKey: options.orderingKey,
|
|
5974
|
+
traceContext: carrier
|
|
5975
|
+
};
|
|
5976
|
+
};
|
|
5710
5977
|
sendActivity(sender, recipients, activity, options = {}) {
|
|
5711
5978
|
return this.tracerProvider.getTracer(name, version).startActiveSpan(this.federation.outboxQueue == null || options.immediate ? "activitypub.outbox" : "activitypub.fanout", {
|
|
5712
5979
|
kind: this.federation.outboxQueue == null || options.immediate ? SpanKind.CLIENT : SpanKind.PRODUCER,
|