@fedify/fedify 2.4.0-pr.936.41 → 2.5.0-dev.2271
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/README.md +50 -39
- package/dist/{assert-CJ1KXcvv.mjs → assert-D1Eafmd_.mjs} +1 -1
- package/dist/{assert_equals-BV7oLMxm.mjs → assert_equals-Z6IcEbWU.mjs} +2 -28
- package/dist/assert_exists-cffSpJ7X.mjs +28 -0
- package/dist/assert_false-CPdRnc3E.mjs +23 -0
- package/dist/assert_greater_or_equal-BlafOF4-.mjs +31 -0
- package/dist/{assert_instance_of-Q9KTBnrf.mjs → assert_instance_of-mrXWWNY-.mjs} +1 -1
- package/dist/{assert_not_equals-EPJPoxuf.mjs → assert_not_equals-CpPK2t89.mjs} +2 -1
- package/dist/assert_rejects-CTptdYck.mjs +39 -0
- package/dist/{assert_strict_equals-Ec20AUwa.mjs → assert_strict_equals-CYvBmkpC.mjs} +2 -1
- package/dist/{assert_throws-NiFfqbnH.mjs → assert_throws-BYITOvPO.mjs} +2 -1
- package/dist/assertion_error-B-cx0fFA.mjs +31 -0
- package/dist/audience-CHQ-FlLD.mjs +95 -0
- package/dist/{builder-DonuxRl_.mjs → builder-Bda6LK7A.mjs} +169 -14
- package/dist/{circuit-breaker-CBGyz5F7.mjs → circuit-breaker-XJ53md4S.mjs} +224 -17
- package/dist/circuit-breaker-test-utils-DW6YC_Pe.mjs +14 -0
- package/dist/{client-CjF5IYQS.mjs → client-CEnNz8O7.mjs} +144 -8
- package/dist/{codec-BBga-FWI.mjs → codec-C6rTrpIp.mjs} +26 -3
- package/dist/{collection-BIhlldqK.mjs → collection-CnnP1UAv.mjs} +1 -1
- package/dist/compat/mod.cjs +1 -1
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/mod.js +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +71 -3
- package/dist/compat/public-audience.test.mjs +14 -5
- package/dist/compat/secured-document.test.d.mts +2 -0
- package/dist/compat/secured-document.test.mjs +58 -0
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/compound-proof-B-9mXxFW.mjs +989 -0
- package/dist/{context-Zii1f5xS.d.ts → context-7NyiqIcg.d.ts} +1600 -25
- package/dist/{context-BJXxPElm.mjs → context-8Tu9kea0.mjs} +21 -63
- package/dist/{context-lxX6I7as.d.cts → context-tsYPJ2Ew.d.cts} +1600 -25
- package/dist/{deno-BHzKn9Ig.mjs → deno-oR5aJKpU.mjs} +1 -1
- package/dist/dist-DJQM4u7i.mjs +189 -0
- package/dist/docloader-DBoYbvYW.mjs +87 -0
- package/dist/{esm-yYQfPhIY.mjs → esm-BHXXx4Wx.mjs} +13 -6
- package/dist/federation/audience.test.d.mts +2 -0
- package/dist/federation/audience.test.mjs +130 -0
- package/dist/federation/builder.test.mjs +54 -5
- package/dist/federation/circuit-breaker.test.mjs +838 -7
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/compound-fanout.test.d.mts +2 -0
- package/dist/federation/compound-fanout.test.mjs +228 -0
- package/dist/federation/handler-compound-proof.test.d.mts +2 -0
- package/dist/federation/handler-compound-proof.test.mjs +384 -0
- package/dist/federation/handler.test.mjs +385 -15
- package/dist/federation/hashlink-media.test.d.mts +2 -0
- package/dist/federation/hashlink-media.test.mjs +422 -0
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox-report.test.d.mts +2 -0
- package/dist/federation/inbox-report.test.mjs +475 -0
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +215 -14
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +5 -5
- package/dist/federation/middleware.test.mjs +967 -35
- package/dist/federation/mod.cjs +18 -261
- package/dist/federation/mod.d.cts +5 -5
- package/dist/federation/mod.d.ts +5 -5
- package/dist/federation/mod.js +279 -1
- package/dist/federation/mq.test.mjs +123 -47
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/outgoing-proof.test.d.mts +2 -0
- package/dist/federation/outgoing-proof.test.mjs +931 -0
- package/dist/federation/portable-actor.test.d.mts +2 -0
- package/dist/federation/portable-actor.test.mjs +496 -0
- package/dist/federation/portable-chain.test.d.mts +2 -0
- package/dist/federation/portable-chain.test.mjs +370 -0
- package/dist/federation/portable-collection.test.d.mts +2 -0
- package/dist/federation/portable-collection.test.mjs +832 -0
- package/dist/federation/portable-delivery.test.d.mts +2 -0
- package/dist/federation/portable-delivery.test.mjs +746 -0
- package/dist/federation/portable-gateway-keys.test.d.mts +2 -0
- package/dist/federation/portable-gateway-keys.test.mjs +686 -0
- package/dist/federation/portable-inbox.test.d.mts +2 -0
- package/dist/federation/portable-inbox.test.mjs +1535 -0
- package/dist/federation/portable-parse-uri.test.d.mts +2 -0
- package/dist/federation/portable-parse-uri.test.mjs +348 -0
- package/dist/federation/portable-route-activity.test.d.mts +2 -0
- package/dist/federation/portable-route-activity.test.mjs +259 -0
- package/dist/federation/portable.test.d.mts +2 -0
- package/dist/federation/portable.test.mjs +1072 -0
- package/dist/federation/retry.test.mjs +4 -3
- package/dist/federation/router.test.mjs +9 -159
- package/dist/federation/send.test.mjs +245 -27
- package/dist/federation/tasks/codec.test.mjs +4 -4
- package/dist/federation/tasks/enqueue.test.mjs +42 -4
- package/dist/federation/tasks/tasks.test.mjs +7 -6
- package/dist/federation/temporal.test.mjs +4 -4
- package/dist/federation/webfinger.test.mjs +275 -12
- package/dist/{middleware-FrSMAYEx.cjs → federation-CkZiAcWY.cjs} +8640 -3722
- package/dist/http-B5JT115n.cjs +10630 -0
- package/dist/http-DydWCB7R.js +6527 -0
- package/dist/{http-CPVMUgsW.mjs → http-siciWkmx.mjs} +397 -168
- package/dist/key-BspPiXqn.mjs +951 -0
- package/dist/key-C1nv7_jD.d.ts +1125 -0
- package/dist/key-DYxuyd-s.d.cts +1125 -0
- package/dist/key-owner-evidence-APB6NpSk.mjs +108 -0
- package/dist/keycache-Da8A8mZa.mjs +200 -0
- package/dist/{kv-D6hNiMTK.d.ts → kv-B2mzK5tl.d.cts} +3 -2
- package/dist/{kv-gJ8LYbxX.d.cts → kv-B2mzK5tl.d.ts} +3 -2
- package/dist/kv-DBRWVx3Q.mjs +104 -0
- package/dist/{kv-cache-KyGqJqSp.mjs → kv-cache-BF1hnW65.mjs} +1 -1
- package/dist/{kv-cache-5bnX3-Jq.js → kv-cache-CTQr1tbn.js} +54 -16
- package/dist/{kv-cache-DQ29C4XL.cjs → kv-cache-DCac1nEU.cjs} +55 -19
- package/dist/{ld-Cj9F_5AP.mjs → ld-CzaP-hJl.mjs} +44 -12
- package/dist/map-local-context-conflict-DOYEEJ3u.mjs +204 -0
- package/dist/map-local-create-note-B0SeXJms.mjs +214 -0
- package/dist/{metrics-DMk-nTxI.mjs → metrics-CYg9yxBL.mjs} +3 -2
- package/dist/metrics-DVKYY6K1.d.cts +36 -0
- package/dist/metrics-DoRtI0qU.d.ts +36 -0
- package/dist/{middleware-Y-kpsp6S.js → middleware-CsDDXKuL.js} +5493 -1103
- package/dist/{middleware-CvwTUgnP.mjs → middleware-D7_LO-Vs.mjs} +3157 -272
- package/dist/{middleware-CEctxBN6.mjs → middleware-DWjrfpcz.mjs} +1 -1
- package/dist/{mod-gOlPDuT8.d.cts → mod-BojP2Bw3.d.cts} +1 -1
- package/dist/mod-CavhAgLw.d.cts +320 -0
- package/dist/mod-CtpF2BU5.d.ts +320 -0
- package/dist/{mod-BtEaIEcD.d.cts → mod-DEZXwV6J.d.ts} +10 -4
- package/dist/{mod-UMmveiO0.d.ts → mod-Dw-nPxQh.d.cts} +10 -4
- package/dist/{mod-DLc2Ot6f.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
- package/dist/mod.cjs +40 -39
- package/dist/mod.d.cts +10 -11
- package/dist/mod.d.ts +10 -11
- package/dist/mod.js +9 -9
- package/dist/{mq-llHKivST.mjs → mq-Dm1Wmtm-.mjs} +6 -0
- package/dist/nodeinfo/client.test.mjs +139 -4
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.d.cts +1 -1
- package/dist/nodeinfo/mod.d.ts +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/otel/mod.cjs +0 -1
- package/dist/otel/mod.d.cts +1 -1
- package/dist/otel/mod.d.ts +1 -1
- package/dist/{outgoing-jsonld-URuqsICz.mjs → outgoing-jsonld-4IJqPYos.mjs} +12 -10
- package/dist/{owner-DEvZuyOE.d.cts → owner-BF0L9cMt.d.cts} +11 -0
- package/dist/{owner-CnngXDNJ.d.ts → owner-BSzr5-I8.d.ts} +11 -0
- package/dist/owner-DYgfTFHy.mjs +267 -0
- package/dist/portable-collection-BpsVsRov.js +670 -0
- package/dist/portable-collection-C74P1vtC.mjs +418 -0
- package/dist/portable-collection-DZd2bm7M.cjs +686 -0
- package/dist/portable-key-BIMLrAP4.mjs +549 -0
- package/dist/portable-key-id-Ca30-hOa.mjs +248 -0
- package/dist/proof-Dxy6ByqI.mjs +1299 -0
- package/dist/{public-audience-Cr5MsnMq.mjs → public-audience--klBIOk1.mjs} +15 -10
- package/dist/router-u5O5KCQr.mjs +156 -0
- package/dist/runtime/mod.cjs +1 -1
- package/dist/runtime/mod.js +1 -1
- package/dist/secured-document-CxzZZ9nL.mjs +35 -0
- package/dist/send-C4dDpAxm.mjs +495 -0
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/compound-proof-discovery.test.d.mts +2 -0
- package/dist/sig/compound-proof-discovery.test.mjs +331 -0
- package/dist/sig/compound-proof-producer.test.d.mts +2 -0
- package/dist/sig/compound-proof-producer.test.mjs +107 -0
- package/dist/sig/compound-proof-verification.test.d.mts +2 -0
- package/dist/sig/compound-proof-verification.test.mjs +833 -0
- package/dist/sig/compound-proof.test.d.mts +2 -0
- package/dist/sig/compound-proof.test.mjs +411 -0
- package/dist/sig/http.test.mjs +702 -31
- package/dist/sig/key-owner-evidence.test.d.mts +2 -0
- package/dist/sig/key-owner-evidence.test.mjs +100 -0
- package/dist/sig/key.test.mjs +220 -8
- package/dist/sig/ld.test.mjs +65 -7
- package/dist/sig/mitra-receive-interop.test.d.mts +2 -0
- package/dist/sig/mitra-receive-interop.test.mjs +260 -0
- package/dist/sig/mitra-send-interop.test.d.mts +2 -0
- package/dist/sig/mitra-send-interop.test.mjs +461 -0
- package/dist/sig/mod.cjs +18 -16
- package/dist/sig/mod.d.cts +4 -4
- package/dist/sig/mod.d.ts +4 -4
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +108 -9
- package/dist/sig/portable-collection.test.d.mts +2 -0
- package/dist/sig/portable-collection.test.mjs +697 -0
- package/dist/sig/portable-interop.test.d.mts +2 -0
- package/dist/sig/portable-interop.test.mjs +156 -0
- package/dist/sig/portable-key-id.test.d.mts +2 -0
- package/dist/sig/portable-key-id.test.mjs +67 -0
- package/dist/sig/portable-key.test.d.mts +2 -0
- package/dist/sig/portable-key.test.mjs +1439 -0
- package/dist/sig/proof.test.mjs +1753 -16
- package/dist/sig/tootik-request-interop.test.d.mts +2 -0
- package/dist/sig/tootik-request-interop.test.mjs +190 -0
- package/dist/sig/tootik-send-interop.test.d.mts +2 -0
- package/dist/sig/tootik-send-interop.test.mjs +331 -0
- package/dist/sig/verification.test.d.mts +2 -0
- package/dist/sig/verification.test.mjs +310 -0
- package/dist/std__assert-DvMDRPes.mjs +8 -0
- package/dist/{testing-CO7ftO8A.mjs → tasks-IG3pHfvZ.mjs} +2 -2
- package/dist/{temporal-fsXO5IvD.mjs → temporal-D0KJI4NF.mjs} +3 -3
- package/dist/testing/context.test.d.mts +2 -0
- package/dist/testing/context.test.mjs +19 -0
- package/dist/testing/kv.test.d.mts +2 -0
- package/dist/testing/kv.test.mjs +101 -0
- package/dist/testing/mod.d.mts +1617 -48
- package/dist/testing/mod.mjs +6 -3
- package/dist/testing-t8xDeJZ5.mjs +8 -0
- package/dist/{transformers-DGwl-hD1.cjs → transformers-BalCrSsr.cjs} +0 -1
- package/dist/{types-DC1pNgJA.js → types-_S2_MeLF.js} +144 -8
- package/dist/{types-CPym83zc.cjs → types-poIao40f.cjs} +160 -7
- package/dist/utils/docloader.test.mjs +530 -8
- package/dist/utils/kv-cache.test.mjs +2 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/dist/verification-C3954hQh.mjs +5 -0
- package/dist/verification-Dpfcw8ml.mjs +105 -0
- package/dist/vocab/cjs.test.mjs +1 -1
- package/package.json +8 -8
- package/dist/assert_rejects-EgstcQy5.mjs +0 -82
- package/dist/docloader-e1khNUKy.mjs +0 -49
- package/dist/http-CsmQ-BQ4.js +0 -2483
- package/dist/http-VyDTd4G3.d.cts +0 -553
- package/dist/http-hlIjmewS.cjs +0 -2694
- package/dist/http-lf8Hsd91.d.ts +0 -553
- package/dist/key-DfPsX8hv.mjs +0 -453
- package/dist/keycache-_DHqz5z_.mjs +0 -97
- package/dist/metrics-CoUJLQhZ.d.cts +0 -276
- package/dist/metrics-Dc4jR-IC.d.ts +0 -276
- package/dist/mod-B0hW12_O.d.cts +0 -307
- package/dist/mod-COIAjwRS.d.ts +0 -307
- package/dist/owner-Br9YYzn_.mjs +0 -120
- package/dist/proof-B4ngoaNQ.mjs +0 -316
- package/dist/proof-B6E0XUXJ.js +0 -1415
- package/dist/proof-NN4xCQGL.cjs +0 -1562
- package/dist/send-CxHKUNzv.mjs +0 -239
- package/dist/std__assert-B2NnY9bq.mjs +0 -79
- package/dist/temporal-polyfill-BCdTHexd.cjs +0 -3565
- /package/dist/{accept-8PiolDP7.mjs → accept-CPVqki78.mjs} +0 -0
- /package/dist/{activity-listener-BtTSxZWA.mjs → activity-listener-C-BSbKI7.mjs} +0 -0
- /package/dist/{client-CAM_bQXx.d.cts → client-D-XP_Ccb.d.cts} +0 -0
- /package/dist/{client-CSddvgWN.d.ts → client-D-XP_Ccb.d.ts} +0 -0
- /package/dist/{keys-Dbyd7bhl.mjs → keys-DIJNHW-Y.mjs} +0 -0
- /package/dist/{kv-CXBAok3k.mjs → kv-DCHkaJ9-.mjs} +0 -0
- /package/dist/{negotiation-RuwrPFqi.mjs → negotiation-CCocWT_N.mjs} +0 -0
- /package/dist/{retry-DgFqeS5k.mjs → retry-zX5xw5e0.mjs} +0 -0
- /package/dist/{chunk-D5IdezsZ.js → rolldown-runtime-BC-Eo5Mj.js} +0 -0
- /package/dist/{chunk-Czpeue4M.cjs → rolldown-runtime-Dmm3t92W.cjs} +0 -0
- /package/dist/{transformers-DXze6FUB.js → transformers-DAtXl_Kc.js} +0 -0
- /package/dist/{types-CrtdVuDP.mjs → types-DE_LV1JB.mjs} +0 -0
package/dist/key-DfPsX8hv.mjs
DELETED
|
@@ -1,453 +0,0 @@
|
|
|
1
|
-
import "temporal-polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-BHzKn9Ig.mjs";
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-DMk-nTxI.mjs";
|
|
6
|
-
import { getLogger } from "@logtape/logtape";
|
|
7
|
-
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
|
-
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
|
-
import { FetchError, getDocumentLoader, parseDidKeyVerificationMethod } from "@fedify/vocab-runtime";
|
|
10
|
-
//#region src/sig/key.ts
|
|
11
|
-
/**
|
|
12
|
-
* Checks if the given key is valid and supported. No-op if the key is valid,
|
|
13
|
-
* otherwise throws an error.
|
|
14
|
-
* @param key The key to check.
|
|
15
|
-
* @param type Which type of key to check. If not specified, the key can be
|
|
16
|
-
* either public or private.
|
|
17
|
-
* @throws {TypeError} If the key is invalid or unsupported.
|
|
18
|
-
*/
|
|
19
|
-
function validateCryptoKey(key, type) {
|
|
20
|
-
if (type != null && key.type !== type) throw new TypeError(`The key is not a ${type} key.`);
|
|
21
|
-
if (!key.extractable) throw new TypeError("The key is not extractable.");
|
|
22
|
-
if (key.algorithm.name !== "RSASSA-PKCS1-v1_5" && key.algorithm.name !== "Ed25519") throw new TypeError("Currently only RSASSA-PKCS1-v1_5 and Ed25519 keys are supported. More algorithms will be added in the future!");
|
|
23
|
-
if (key.algorithm.name === "RSASSA-PKCS1-v1_5") {
|
|
24
|
-
if (key.algorithm.hash.name !== "SHA-256") throw new TypeError("For compatibility with the existing Fediverse software (e.g., Mastodon), hash algorithm for RSASSA-PKCS1-v1_5 keys must be SHA-256.");
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Generates a key pair which is appropriate for Fedify.
|
|
29
|
-
* @param algorithm The algorithm to use. Currently only RSASSA-PKCS1-v1_5 and
|
|
30
|
-
* Ed25519 are supported.
|
|
31
|
-
* @returns The generated key pair.
|
|
32
|
-
* @throws {TypeError} If the algorithm is unsupported.
|
|
33
|
-
*/
|
|
34
|
-
function generateCryptoKeyPair(algorithm) {
|
|
35
|
-
if (algorithm == null) getLogger([
|
|
36
|
-
"fedify",
|
|
37
|
-
"sig",
|
|
38
|
-
"key"
|
|
39
|
-
]).warn("No algorithm specified. Using RSASSA-PKCS1-v1_5 by default, but it is recommended to specify the algorithm explicitly as the parameter will be required in the future.");
|
|
40
|
-
if (algorithm == null || algorithm === "RSASSA-PKCS1-v1_5") return crypto.subtle.generateKey({
|
|
41
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
42
|
-
modulusLength: 4096,
|
|
43
|
-
publicExponent: new Uint8Array([
|
|
44
|
-
1,
|
|
45
|
-
0,
|
|
46
|
-
1
|
|
47
|
-
]),
|
|
48
|
-
hash: "SHA-256"
|
|
49
|
-
}, true, ["sign", "verify"]);
|
|
50
|
-
else if (algorithm === "Ed25519") return crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]);
|
|
51
|
-
throw new TypeError("Unsupported algorithm: " + algorithm);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Exports a key in JWK format.
|
|
55
|
-
* @param key The key to export. Either public or private key.
|
|
56
|
-
* @returns The exported key in JWK format. The key is suitable for
|
|
57
|
-
* serialization and storage.
|
|
58
|
-
* @throws {TypeError} If the key is invalid or unsupported.
|
|
59
|
-
*/
|
|
60
|
-
async function exportJwk(key) {
|
|
61
|
-
validateCryptoKey(key);
|
|
62
|
-
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
63
|
-
if (jwk.crv === "Ed25519") jwk.alg = "Ed25519";
|
|
64
|
-
return jwk;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Imports a key from JWK format.
|
|
68
|
-
* @param jwk The key in JWK format.
|
|
69
|
-
* @param type Which type of key to import, either `"public"` or `"private"`.
|
|
70
|
-
* @returns The imported key.
|
|
71
|
-
* @throws {TypeError} If the key is invalid or unsupported.
|
|
72
|
-
*/
|
|
73
|
-
async function importJwk(jwk, type) {
|
|
74
|
-
let key;
|
|
75
|
-
if (jwk.kty === "RSA" && jwk.alg === "RS256") key = await crypto.subtle.importKey("jwk", jwk, {
|
|
76
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
77
|
-
hash: "SHA-256"
|
|
78
|
-
}, true, type === "public" ? ["verify"] : ["sign"]);
|
|
79
|
-
else if (jwk.kty === "OKP" && jwk.crv === "Ed25519") {
|
|
80
|
-
if (navigator?.userAgent === "Cloudflare-Workers") {
|
|
81
|
-
jwk = { ...jwk };
|
|
82
|
-
delete jwk.alg;
|
|
83
|
-
}
|
|
84
|
-
key = await crypto.subtle.importKey("jwk", jwk, "Ed25519", true, type === "public" ? ["verify"] : ["sign"]);
|
|
85
|
-
} else throw new TypeError("Unsupported JWK format.");
|
|
86
|
-
validateCryptoKey(key, type);
|
|
87
|
-
return key;
|
|
88
|
-
}
|
|
89
|
-
async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
90
|
-
tracerProvider ??= trace.getTracerProvider();
|
|
91
|
-
return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.fetch_key", {
|
|
92
|
-
kind: SpanKind.CLIENT,
|
|
93
|
-
attributes: {
|
|
94
|
-
"http.method": "GET",
|
|
95
|
-
"url.full": keyId.href,
|
|
96
|
-
"url.scheme": keyId.protocol.replace(/:$/, ""),
|
|
97
|
-
"url.domain": keyId.hostname,
|
|
98
|
-
"url.path": keyId.pathname,
|
|
99
|
-
"url.query": keyId.search.replace(/^\?/, ""),
|
|
100
|
-
"url.fragment": keyId.hash.replace(/^#/, "")
|
|
101
|
-
}
|
|
102
|
-
}, async (span) => {
|
|
103
|
-
try {
|
|
104
|
-
const result = await fetcher();
|
|
105
|
-
span.setAttribute("activitypub.actor.key.cached", result.cached);
|
|
106
|
-
return result;
|
|
107
|
-
} catch (e) {
|
|
108
|
-
span.setStatus({
|
|
109
|
-
code: SpanStatusCode.ERROR,
|
|
110
|
-
message: String(e)
|
|
111
|
-
});
|
|
112
|
-
throw e;
|
|
113
|
-
} finally {
|
|
114
|
-
span.end();
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Fetches a {@link CryptographicKey} or {@link Multikey} from the given URL.
|
|
120
|
-
* If the given URL contains an {@link Actor} object, it tries to find
|
|
121
|
-
* the corresponding key in the `publicKey` or `assertionMethod` property.
|
|
122
|
-
* @template T The type of the key to fetch. Either {@link CryptographicKey}
|
|
123
|
-
* or {@link Multikey}.
|
|
124
|
-
* @param keyId The URL of the key.
|
|
125
|
-
* @param cls The class of the key to fetch. Either {@link CryptographicKey}
|
|
126
|
-
* or {@link Multikey}.
|
|
127
|
-
* @param options Options for fetching the key. See {@link FetchKeyOptions}.
|
|
128
|
-
* @returns The fetched key or `null` if the key is not found.
|
|
129
|
-
* @since 1.3.0
|
|
130
|
-
*/
|
|
131
|
-
function fetchKey(keyId, cls, options = {}) {
|
|
132
|
-
keyId = typeof keyId === "string" ? new URL(keyId) : keyId;
|
|
133
|
-
return withFetchKeySpan(keyId, options.tracerProvider, () => fetchKeyInternal(keyId, cls, options));
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Fetches a {@link CryptographicKey} or {@link Multikey} from the given URL,
|
|
137
|
-
* preserving transport-level fetch failures for callers that need to inspect
|
|
138
|
-
* why the key could not be loaded.
|
|
139
|
-
*
|
|
140
|
-
* @template T The type of the key to fetch. Either {@link CryptographicKey}
|
|
141
|
-
* or {@link Multikey}.
|
|
142
|
-
* @param keyId The URL of the key.
|
|
143
|
-
* @param cls The class of the key to fetch. Either {@link CryptographicKey}
|
|
144
|
-
* or {@link Multikey}.
|
|
145
|
-
* @param options Options for fetching the key.
|
|
146
|
-
* @returns The fetched key, or detailed fetch failure information.
|
|
147
|
-
* @since 2.1.0
|
|
148
|
-
*/
|
|
149
|
-
async function fetchKeyDetailed(keyId, cls, options = {}) {
|
|
150
|
-
const cacheKey = typeof keyId === "string" ? new URL(keyId) : keyId;
|
|
151
|
-
return await withFetchKeySpan(cacheKey, options.tracerProvider, async () => {
|
|
152
|
-
return await fetchKeyWithResult(cacheKey, cls, options, async (cacheKey, keyId, keyCache, logger) => {
|
|
153
|
-
const fetchError = await keyCache?.getFetchError?.(cacheKey);
|
|
154
|
-
if (fetchError != null) {
|
|
155
|
-
logger.debug("Entry {keyId} found in cache with preserved fetch failure details.", { keyId });
|
|
156
|
-
return {
|
|
157
|
-
key: null,
|
|
158
|
-
cached: true,
|
|
159
|
-
fetchError
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
logger.debug("Entry {keyId} found in cache, but no fetch failure details are available.", { keyId });
|
|
163
|
-
return {
|
|
164
|
-
key: null,
|
|
165
|
-
cached: true
|
|
166
|
-
};
|
|
167
|
-
}, async (error, cacheKey, keyId, keyCache, logger) => {
|
|
168
|
-
logger.debug("Failed to fetch key {keyId}.", {
|
|
169
|
-
keyId,
|
|
170
|
-
error
|
|
171
|
-
});
|
|
172
|
-
await keyCache?.set(cacheKey, null);
|
|
173
|
-
if (error instanceof FetchError && error.response != null) {
|
|
174
|
-
const fetchError = {
|
|
175
|
-
status: error.response.status,
|
|
176
|
-
response: error.response.clone()
|
|
177
|
-
};
|
|
178
|
-
await keyCache?.setFetchError?.(cacheKey, fetchError);
|
|
179
|
-
return {
|
|
180
|
-
key: null,
|
|
181
|
-
cached: false,
|
|
182
|
-
fetchError
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
const fetchError = { error: error instanceof Error ? error : new Error(String(error)) };
|
|
186
|
-
await keyCache?.setFetchError?.(cacheKey, fetchError);
|
|
187
|
-
return {
|
|
188
|
-
key: null,
|
|
189
|
-
cached: false,
|
|
190
|
-
fetchError
|
|
191
|
-
};
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
async function getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger) {
|
|
196
|
-
if (keyCache == null) return null;
|
|
197
|
-
const cachedKey = await keyCache.get(cacheKey);
|
|
198
|
-
const hit = checkCachedKeyHit(cachedKey, keyId, cls, logger);
|
|
199
|
-
if (hit != null) return hit;
|
|
200
|
-
if (cachedKey === null) {
|
|
201
|
-
logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
|
|
202
|
-
return {
|
|
203
|
-
key: null,
|
|
204
|
-
cached: true
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
function checkCachedKeyHit(cachedKey, keyId, cls, logger) {
|
|
210
|
-
if (cachedKey instanceof cls && cachedKey.publicKey != null) {
|
|
211
|
-
logger.debug("Key {keyId} found in cache.", { keyId });
|
|
212
|
-
return {
|
|
213
|
-
key: cachedKey,
|
|
214
|
-
cached: true
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
async function clearFetchErrorMetadata(keyId, keyCache) {
|
|
220
|
-
await keyCache?.setFetchError?.(keyId, null);
|
|
221
|
-
}
|
|
222
|
-
function isDidKeyUrl(keyId) {
|
|
223
|
-
return keyId.protocol === "did:" && keyId.pathname.startsWith("key:");
|
|
224
|
-
}
|
|
225
|
-
async function doRawKeysMatch(left, right) {
|
|
226
|
-
const [leftRaw, rightRaw] = await Promise.all([crypto.subtle.exportKey("raw", left), crypto.subtle.exportKey("raw", right)]);
|
|
227
|
-
if (leftRaw.byteLength !== rightRaw.byteLength) return false;
|
|
228
|
-
const leftBytes = new Uint8Array(leftRaw);
|
|
229
|
-
const rightBytes = new Uint8Array(rightRaw);
|
|
230
|
-
return leftBytes.every((byte, index) => byte === rightBytes[index]);
|
|
231
|
-
}
|
|
232
|
-
async function isCachedDidKeyValid(key, verificationMethod) {
|
|
233
|
-
try {
|
|
234
|
-
return key.id?.href === verificationMethod.id.href && key.controllerId?.href === verificationMethod.controller.href && await doRawKeysMatch(key.publicKey, verificationMethod.publicKey);
|
|
235
|
-
} catch {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async function resolveDidKey(cacheKey, cls, keyCache, logger) {
|
|
240
|
-
if (!isDidKeyUrl(cacheKey)) return null;
|
|
241
|
-
const keyId = cacheKey.href;
|
|
242
|
-
if (!(cls === Multikey)) {
|
|
243
|
-
logger.debug("Failed to resolve did:key {keyId}; did:key verification methods are only supported as Multikey values.", { keyId });
|
|
244
|
-
return {
|
|
245
|
-
key: null,
|
|
246
|
-
cached: false
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
let verificationMethod;
|
|
250
|
-
try {
|
|
251
|
-
verificationMethod = await parseDidKeyVerificationMethod(cacheKey);
|
|
252
|
-
} catch (error) {
|
|
253
|
-
logger.debug("Failed to resolve did:key verification method {keyId}: {error}", {
|
|
254
|
-
keyId,
|
|
255
|
-
error
|
|
256
|
-
});
|
|
257
|
-
return {
|
|
258
|
-
key: null,
|
|
259
|
-
cached: false
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
const hit = checkCachedKeyHit(await keyCache?.get(cacheKey), keyId, cls, logger);
|
|
263
|
-
if (hit?.key instanceof Multikey && await isCachedDidKeyValid(hit.key, verificationMethod)) return hit;
|
|
264
|
-
const key = new Multikey({
|
|
265
|
-
id: verificationMethod.id,
|
|
266
|
-
controller: verificationMethod.controller,
|
|
267
|
-
publicKey: verificationMethod.publicKey
|
|
268
|
-
});
|
|
269
|
-
await keyCache?.set(cacheKey, key);
|
|
270
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
271
|
-
logger.debug("Resolved did:key verification method {keyId}.", { keyId });
|
|
272
|
-
return {
|
|
273
|
-
key,
|
|
274
|
-
cached: false
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider }, logger) {
|
|
278
|
-
let object;
|
|
279
|
-
try {
|
|
280
|
-
object = await Object$1.fromJsonLd(document, {
|
|
281
|
-
documentLoader,
|
|
282
|
-
contextLoader,
|
|
283
|
-
tracerProvider
|
|
284
|
-
});
|
|
285
|
-
} catch (e) {
|
|
286
|
-
if (!(e instanceof TypeError)) throw e;
|
|
287
|
-
try {
|
|
288
|
-
object = await cls.fromJsonLd(document, {
|
|
289
|
-
documentLoader,
|
|
290
|
-
contextLoader,
|
|
291
|
-
tracerProvider
|
|
292
|
-
});
|
|
293
|
-
} catch (e) {
|
|
294
|
-
if (e instanceof TypeError) {
|
|
295
|
-
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
|
296
|
-
await keyCache?.set(cacheKey, null);
|
|
297
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
298
|
-
return {
|
|
299
|
-
key: null,
|
|
300
|
-
cached: false
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
throw e;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
let key = null;
|
|
307
|
-
if (object instanceof cls) key = object;
|
|
308
|
-
else if (isActor(object)) {
|
|
309
|
-
const keys = cls === CryptographicKey ? object.getPublicKeys({
|
|
310
|
-
documentLoader,
|
|
311
|
-
contextLoader,
|
|
312
|
-
suppressError: true,
|
|
313
|
-
tracerProvider
|
|
314
|
-
}) : object.getAssertionMethods({
|
|
315
|
-
documentLoader,
|
|
316
|
-
contextLoader,
|
|
317
|
-
suppressError: true,
|
|
318
|
-
tracerProvider
|
|
319
|
-
});
|
|
320
|
-
let length = 0;
|
|
321
|
-
let lastKey = null;
|
|
322
|
-
try {
|
|
323
|
-
for await (const k of keys) {
|
|
324
|
-
length++;
|
|
325
|
-
lastKey = k;
|
|
326
|
-
if (k.id?.href === keyId) {
|
|
327
|
-
key = k;
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
} catch (e) {
|
|
332
|
-
if (!(e instanceof TypeError)) throw e;
|
|
333
|
-
logger.debug("Failed to verify; a malformed key was encountered while iterating the keys of {keyId}; treating it as a missing key: {error}", {
|
|
334
|
-
keyId,
|
|
335
|
-
error: e
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
const keyIdUrl = new URL(keyId);
|
|
339
|
-
if (key == null && keyIdUrl.hash === "" && length === 1) key = lastKey;
|
|
340
|
-
if (key == null) {
|
|
341
|
-
logger.debug("Failed to verify; object {keyId} returned an {actorType}, but has no key matching {keyId}.", {
|
|
342
|
-
keyId,
|
|
343
|
-
actorType: object.constructor.name
|
|
344
|
-
});
|
|
345
|
-
await keyCache?.set(cacheKey, null);
|
|
346
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
347
|
-
return {
|
|
348
|
-
key: null,
|
|
349
|
-
cached: false
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
} else {
|
|
353
|
-
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
|
354
|
-
await keyCache?.set(cacheKey, null);
|
|
355
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
356
|
-
return {
|
|
357
|
-
key: null,
|
|
358
|
-
cached: false
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
if (key.publicKey == null) {
|
|
362
|
-
logger.debug("Failed to verify; key {keyId} has no publicKeyPem field.", { keyId });
|
|
363
|
-
await keyCache?.set(cacheKey, null);
|
|
364
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
365
|
-
return {
|
|
366
|
-
key: null,
|
|
367
|
-
cached: false
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
if (keyCache != null) {
|
|
371
|
-
await keyCache.set(cacheKey, key);
|
|
372
|
-
logger.debug("Key {keyId} cached.", { keyId });
|
|
373
|
-
}
|
|
374
|
-
await clearFetchErrorMetadata(cacheKey, keyCache);
|
|
375
|
-
return {
|
|
376
|
-
key,
|
|
377
|
-
cached: false
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, onFetchError) {
|
|
381
|
-
const start = performance.now();
|
|
382
|
-
let outcome = { result: "error" };
|
|
383
|
-
try {
|
|
384
|
-
const logger = getLogger([
|
|
385
|
-
"fedify",
|
|
386
|
-
"sig",
|
|
387
|
-
"key"
|
|
388
|
-
]);
|
|
389
|
-
const keyId = cacheKey.href;
|
|
390
|
-
const keyCache = options.keyCache;
|
|
391
|
-
const didKey = await resolveDidKey(cacheKey, cls, keyCache, logger);
|
|
392
|
-
if (didKey != null) {
|
|
393
|
-
outcome = { result: didKey.key == null ? "invalid" : didKey.cached ? "hit" : "fetched" };
|
|
394
|
-
return didKey;
|
|
395
|
-
}
|
|
396
|
-
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
397
|
-
if (cached?.key === null && cached.cached) {
|
|
398
|
-
const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
399
|
-
outcome = { result: "hit" };
|
|
400
|
-
return cachedUnavailable;
|
|
401
|
-
}
|
|
402
|
-
if (cached != null) {
|
|
403
|
-
outcome = { result: "hit" };
|
|
404
|
-
return cached;
|
|
405
|
-
}
|
|
406
|
-
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
407
|
-
let document;
|
|
408
|
-
try {
|
|
409
|
-
document = (await (options.documentLoader ?? getDocumentLoader())(keyId)).document;
|
|
410
|
-
} catch (error) {
|
|
411
|
-
const classified = classifyFetchError(error);
|
|
412
|
-
const errored = await onFetchError(error, cacheKey, keyId, keyCache, logger);
|
|
413
|
-
outcome = classified;
|
|
414
|
-
return errored;
|
|
415
|
-
}
|
|
416
|
-
const resolved = await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
417
|
-
outcome = { result: resolved.key != null ? "fetched" : "invalid" };
|
|
418
|
-
return resolved;
|
|
419
|
-
} finally {
|
|
420
|
-
recordKeyLookup(options.meterProvider, {
|
|
421
|
-
durationMs: getDurationMs(start),
|
|
422
|
-
result: outcome.result,
|
|
423
|
-
remoteUrl: cacheKey,
|
|
424
|
-
cacheEnabled: options.keyCache != null,
|
|
425
|
-
statusCode: outcome.statusCode
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
430
|
-
return await fetchKeyWithResult(typeof keyId === "string" ? new URL(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
431
|
-
return {
|
|
432
|
-
key: null,
|
|
433
|
-
cached: true
|
|
434
|
-
};
|
|
435
|
-
}, async (error, cacheKey, keyId, keyCache, logger) => {
|
|
436
|
-
logger.debug("Failed to fetch key {keyId}.", {
|
|
437
|
-
keyId,
|
|
438
|
-
error
|
|
439
|
-
});
|
|
440
|
-
await keyCache?.set(cacheKey, null);
|
|
441
|
-
if (error instanceof FetchError && error.response != null) await keyCache?.setFetchError?.(cacheKey, {
|
|
442
|
-
status: error.response.status,
|
|
443
|
-
response: error.response.clone()
|
|
444
|
-
});
|
|
445
|
-
else await keyCache?.setFetchError?.(cacheKey, { error: error instanceof Error ? error : new Error(String(error)) });
|
|
446
|
-
return {
|
|
447
|
-
key: null,
|
|
448
|
-
cached: false
|
|
449
|
-
};
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
//#endregion
|
|
453
|
-
export { importJwk as a, generateCryptoKeyPair as i, fetchKey as n, validateCryptoKey as o, fetchKeyDetailed as r, exportJwk as t };
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { Temporal } from "temporal-polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
globalThis.addEventListener = () => {};
|
|
4
|
-
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
5
|
-
//#region src/federation/keycache.ts
|
|
6
|
-
var KvKeyCache = class {
|
|
7
|
-
kv;
|
|
8
|
-
prefix;
|
|
9
|
-
options;
|
|
10
|
-
unavailableKeyTtl;
|
|
11
|
-
nullKeys;
|
|
12
|
-
constructor(kv, prefix, options = {}) {
|
|
13
|
-
this.kv = kv;
|
|
14
|
-
this.prefix = prefix;
|
|
15
|
-
this.options = options;
|
|
16
|
-
this.unavailableKeyTtl = options.unavailableKeyTtl ?? Temporal.Duration.from({ minutes: 10 });
|
|
17
|
-
this.nullKeys = /* @__PURE__ */ new Map();
|
|
18
|
-
}
|
|
19
|
-
#getFetchErrorKey(keyId) {
|
|
20
|
-
return [
|
|
21
|
-
...this.prefix,
|
|
22
|
-
"__fetchError",
|
|
23
|
-
keyId.href
|
|
24
|
-
];
|
|
25
|
-
}
|
|
26
|
-
async get(keyId) {
|
|
27
|
-
const negativeExpiration = this.nullKeys.get(keyId.href);
|
|
28
|
-
if (negativeExpiration != null) {
|
|
29
|
-
if (Temporal.Now.instant().until(negativeExpiration).sign >= 0) return null;
|
|
30
|
-
this.nullKeys.delete(keyId.href);
|
|
31
|
-
}
|
|
32
|
-
const serialized = await this.kv.get([...this.prefix, keyId.href]);
|
|
33
|
-
if (serialized === void 0) return void 0;
|
|
34
|
-
if (serialized === null) {
|
|
35
|
-
this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
return await CryptographicKey.fromJsonLd(serialized, this.options);
|
|
40
|
-
} catch {
|
|
41
|
-
try {
|
|
42
|
-
return await Multikey.fromJsonLd(serialized, this.options);
|
|
43
|
-
} catch {
|
|
44
|
-
await this.kv.delete([...this.prefix, keyId.href]);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async set(keyId, key) {
|
|
50
|
-
if (key == null) {
|
|
51
|
-
this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
|
|
52
|
-
await this.kv.set([...this.prefix, keyId.href], null, { ttl: this.unavailableKeyTtl });
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
this.nullKeys.delete(keyId.href);
|
|
56
|
-
const serialized = await key.toJsonLd(this.options);
|
|
57
|
-
await this.kv.set([...this.prefix, keyId.href], serialized);
|
|
58
|
-
}
|
|
59
|
-
async getFetchError(keyId) {
|
|
60
|
-
const cached = await this.kv.get(this.#getFetchErrorKey(keyId));
|
|
61
|
-
if (cached == null || typeof cached !== "object") return void 0;
|
|
62
|
-
if ("status" in cached && typeof cached.status === "number" && "statusText" in cached && typeof cached.statusText === "string" && "headers" in cached && Array.isArray(cached.headers) && "body" in cached && typeof cached.body === "string") return {
|
|
63
|
-
status: cached.status,
|
|
64
|
-
response: new Response(cached.body, {
|
|
65
|
-
status: cached.status,
|
|
66
|
-
statusText: cached.statusText,
|
|
67
|
-
headers: cached.headers
|
|
68
|
-
})
|
|
69
|
-
};
|
|
70
|
-
else if ("errorName" in cached && typeof cached.errorName === "string" && "errorMessage" in cached && typeof cached.errorMessage === "string") {
|
|
71
|
-
const error = new Error(cached.errorMessage);
|
|
72
|
-
error.name = cached.errorName;
|
|
73
|
-
return { error };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async setFetchError(keyId, error) {
|
|
77
|
-
if (error == null) {
|
|
78
|
-
await this.kv.delete(this.#getFetchErrorKey(keyId));
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if ("status" in error) {
|
|
82
|
-
await this.kv.set(this.#getFetchErrorKey(keyId), {
|
|
83
|
-
status: error.status,
|
|
84
|
-
statusText: error.response.statusText,
|
|
85
|
-
headers: Array.from(error.response.headers.entries()),
|
|
86
|
-
body: await error.response.clone().text()
|
|
87
|
-
}, { ttl: this.unavailableKeyTtl });
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
await this.kv.set(this.#getFetchErrorKey(keyId), {
|
|
91
|
-
errorName: error.error.name,
|
|
92
|
-
errorMessage: error.error.message
|
|
93
|
-
}, { ttl: this.unavailableKeyTtl });
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
//#endregion
|
|
97
|
-
export { KvKeyCache as t };
|