@fedify/vocab-runtime 2.4.0-pr.934.40 → 2.4.0
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/deno.json +4 -2
- package/dist/{tests/docloader-Xi61Le8w.mjs → contexts-BK1CqBR5.cjs} +164 -269
- package/dist/{tests/docloader-BFedvemb.cjs → contexts-DPuJ4UYL.js} +160 -288
- package/dist/{docloader-DnUMWHaJ.d.cts → docloader-CYwqh5Df.d.cts} +68 -2
- package/dist/{docloader-xRGn1azD.d.ts → docloader-CYwqh5Df.d.ts} +68 -2
- package/dist/internal/jsonld-cache.cjs +70 -1
- package/dist/internal/jsonld-cache.d.cts +35 -2
- package/dist/internal/jsonld-cache.d.ts +35 -2
- package/dist/internal/jsonld-cache.js +67 -2
- package/dist/internal/portable-dereference.cjs +721 -0
- package/dist/internal/portable-dereference.d.cts +349 -0
- package/dist/internal/portable-dereference.d.ts +349 -0
- package/dist/internal/portable-dereference.js +702 -0
- package/dist/internal/signed-representation.cjs +378 -0
- package/dist/internal/signed-representation.d.cts +144 -0
- package/dist/internal/signed-representation.d.ts +144 -0
- package/dist/internal/signed-representation.js +371 -0
- package/dist/jsonld.cjs +2 -2
- package/dist/mod.cjs +715 -4523
- package/dist/mod.d.cts +406 -6
- package/dist/mod.d.ts +406 -7
- package/dist/mod.js +694 -4518
- package/dist/portable-DqtfLy_1.d.cts +160 -0
- package/dist/portable-DtWsu2yU.d.ts +160 -0
- package/dist/tests/body-CYiu9CO-.mjs +130 -0
- package/dist/tests/body-CkEwROsn.cjs +153 -0
- package/dist/tests/body.test.cjs +89 -0
- package/dist/tests/body.test.d.cts +1 -0
- package/dist/tests/body.test.d.mts +1 -0
- package/dist/tests/body.test.mjs +90 -0
- package/dist/tests/contexts-CIKsin4e.mjs +4512 -0
- package/dist/tests/contexts-DizzBjz4.cjs +4523 -0
- package/dist/tests/decimal.test.cjs +8 -7
- package/dist/tests/decimal.test.mjs +8 -6
- package/dist/tests/digest-3FeH2Y-Q.cjs +176 -0
- package/dist/tests/digest-COC7xDiQ.mjs +141 -0
- package/dist/tests/digest.test.cjs +102 -0
- package/dist/tests/digest.test.d.cts +1 -0
- package/dist/tests/digest.test.d.mts +1 -0
- package/dist/tests/digest.test.mjs +103 -0
- package/dist/tests/docloader-C3YFl6y4.cjs +396 -0
- package/dist/tests/docloader-CvmS4sVq.mjs +373 -0
- package/dist/tests/docloader.test.cjs +692 -39
- package/dist/tests/docloader.test.mjs +686 -34
- package/dist/tests/internal/multicodec.test.cjs +2 -3
- package/dist/tests/internal/multicodec.test.mjs +2 -2
- package/dist/tests/internal/portable-dereference.test.cjs +172 -0
- package/dist/tests/internal/portable-dereference.test.d.cts +1 -0
- package/dist/tests/internal/portable-dereference.test.d.mts +1 -0
- package/dist/tests/internal/portable-dereference.test.mjs +173 -0
- package/dist/tests/jsonld-cache-BPQmOZWD.mjs +342 -0
- package/dist/tests/jsonld-cache-C07AyNOY.cjs +397 -0
- package/dist/tests/jsonld-cache.test.cjs +101 -298
- package/dist/tests/jsonld-cache.test.mjs +94 -289
- package/dist/tests/{key-_wXwomh_.cjs → key-C-AYkdJJ.cjs} +11 -4
- package/dist/tests/{key-CDGDH_vC.mjs → key-C2Db_TAJ.mjs} +11 -3
- package/dist/tests/key.test.cjs +6 -5
- package/dist/tests/key.test.mjs +6 -4
- package/dist/tests/langstr.test.cjs +4 -4
- package/dist/tests/langstr.test.mjs +2 -2
- package/dist/tests/link.test.cjs +2 -3
- package/dist/tests/link.test.mjs +2 -2
- package/dist/tests/multibase/multibase.test.cjs +8 -9
- package/dist/tests/multibase/multibase.test.mjs +6 -6
- package/dist/tests/{multibase-Bz_UUDtL.cjs → multibase-B5Mea7Ip.cjs} +19 -2
- package/dist/tests/{multibase-B4bvakyA.mjs → multibase-BPnF_L4e.mjs} +12 -1
- package/dist/tests/portable-dereference-BNXtgg5U.cjs +278 -0
- package/dist/tests/portable-dereference-DRE5bz-l.mjs +249 -0
- package/dist/tests/portable-media-BLKllU56.cjs +153 -0
- package/dist/tests/portable-media-DRSGBORB.mjs +148 -0
- package/dist/tests/portable-media.test.cjs +222 -0
- package/dist/tests/portable-media.test.d.cts +1 -0
- package/dist/tests/portable-media.test.d.mts +1 -0
- package/dist/tests/portable-media.test.mjs +223 -0
- package/dist/tests/portable-workers.test.cjs +36 -0
- package/dist/tests/portable-workers.test.d.cts +2 -0
- package/dist/tests/portable-workers.test.d.mts +2 -0
- package/dist/tests/portable-workers.test.mjs +35 -0
- package/dist/tests/{request-cCPgOxYG.cjs → request-8vPWtV1-.cjs} +10 -4
- package/dist/tests/{request-BOS-hNaf.mjs → request-DRaOaTqD.mjs} +8 -2
- package/dist/tests/request.test.cjs +7 -4
- package/dist/tests/request.test.mjs +5 -2
- package/dist/tests/signed-representation.test.cjs +588 -0
- package/dist/tests/signed-representation.test.d.cts +1 -0
- package/dist/tests/signed-representation.test.d.mts +1 -0
- package/dist/tests/signed-representation.test.mjs +589 -0
- package/dist/tests/temporal.test.cjs +1 -2
- package/dist/tests/temporal.test.mjs +1 -1
- package/dist/tests/url-BNakuZ8k.cjs +998 -0
- package/dist/tests/url-DMxmp7ZG.mjs +859 -0
- package/dist/tests/url.test.cjs +503 -3
- package/dist/tests/url.test.mjs +503 -2
- package/dist/url-DrGTR8yv.cjs +993 -0
- package/dist/url-Dzyp-NsC.js +860 -0
- package/package.json +27 -4
- package/scripts/test-bun.mjs +17 -0
- package/src/body.test.ts +125 -0
- package/src/body.ts +152 -0
- package/src/contexts/cid-v1.json +114 -0
- package/src/contexts/fep-22cd.json +21 -0
- package/src/contexts/fep-ef61.json +10 -0
- package/src/contexts/miscellany.json +17 -0
- package/src/contexts/security-data-integrity-v1.json +0 -4
- package/src/contexts.ts +40 -0
- package/src/digest.test.ts +220 -0
- package/src/digest.ts +229 -0
- package/src/docloader.test.ts +918 -27
- package/src/docloader.ts +322 -105
- package/src/internal/jsonld-cache.ts +97 -1
- package/src/internal/portable-dereference.test.ts +254 -0
- package/src/internal/portable-dereference.ts +1000 -0
- package/src/internal/signed-representation.ts +565 -0
- package/src/jsonld-cache.test.ts +89 -0
- package/src/key.test.ts +9 -0
- package/src/key.ts +11 -1
- package/src/mod.ts +30 -0
- package/src/multibase/multibase.test.ts +5 -5
- package/src/portable-media.test.ts +293 -0
- package/src/portable-media.ts +264 -0
- package/src/portable-workers.test.ts +81 -0
- package/src/portable.ts +180 -0
- package/src/preprocessor.ts +7 -0
- package/src/request.test.ts +10 -1
- package/src/request.ts +9 -1
- package/src/signed-representation.test.ts +338 -0
- package/src/url.test.ts +844 -1
- package/src/url.ts +717 -17
- package/tsdown.config.ts +2 -0
- package/dist/tests/url-BvjYQdxL.cjs +0 -456
- package/dist/tests/url-a2D8NAgh.mjs +0 -378
- package/dist/url-Ck3dGEwH.cjs +0 -457
- package/dist/url-m1YxGNZ0.js +0 -379
- /package/dist/{chunk-M78iaK0I.cjs → rolldown-runtime-B7lfambq.cjs} +0 -0
- /package/dist/tests/{langstr-CbAxaeEZ.cjs → langstr-C4Fl80ae.cjs} +0 -0
- /package/dist/tests/{langstr-Di5AvKpB.mjs → langstr-CQ26J_L7.mjs} +0 -0
- /package/dist/tests/{link-NUUWCdnK.mjs → link-Cevmc87v.mjs} +0 -0
- /package/dist/tests/{link-FguCydMA.cjs → link-DlKm8bEr.cjs} +0 -0
- /package/dist/tests/{multicodec-CxGVGa91.cjs → multicodec-CLRPeW4N.cjs} +0 -0
- /package/dist/tests/{multicodec-CyFp54fI.mjs → multicodec-CRIj_05H.mjs} +0 -0
- /package/dist/tests/{chunk-C2EiDwsr.cjs → rolldown-runtime-emK7D4bc.cjs} +0 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
require("../
|
|
2
|
-
const require_multibase = require("../multibase-Bz_UUDtL.cjs");
|
|
1
|
+
const require_multibase = require("../multibase-B5Mea7Ip.cjs");
|
|
3
2
|
let node_assert = require("node:assert");
|
|
4
|
-
let
|
|
3
|
+
let _fedify_fixture = require("@fedify/fixture");
|
|
5
4
|
//#region src/multibase/multibase.test.ts
|
|
6
|
-
(0,
|
|
5
|
+
(0, _fedify_fixture.test)("multibase.encode and decode", async (t) => {
|
|
7
6
|
const testCases = [
|
|
8
7
|
[
|
|
9
8
|
"base16",
|
|
@@ -316,22 +315,22 @@ let node_test = require("node:test");
|
|
|
316
315
|
"Uw7fDr8O_8J-lsMO3w6_Dv_CfmI7wn6W28J-krw=="
|
|
317
316
|
]
|
|
318
317
|
];
|
|
319
|
-
for (const [name, input, expectedOutput] of testCases) await t.
|
|
318
|
+
for (const [name, input, expectedOutput] of testCases) await t.step(`Encoding/Decoding ${name} with ${input}`, () => {
|
|
320
319
|
(0, node_assert.deepStrictEqual)(require_multibase.decodeText(require_multibase.encodeMultibase(name, require_multibase.encodeText(input))), expectedOutput, `Encoding ${name} failed`);
|
|
321
320
|
(0, node_assert.deepStrictEqual)(require_multibase.decodeMultibase(expectedOutput), require_multibase.encodeText(input), `Decoding ${name} failed`);
|
|
322
321
|
(0, node_assert.deepStrictEqual)(require_multibase.decodeMultibase(require_multibase.encodeText(expectedOutput)), require_multibase.encodeText(input), `Decoding buffer of ${name} failed`);
|
|
323
322
|
});
|
|
324
|
-
await t.
|
|
323
|
+
await t.step("should allow base32pad full alphabet", () => {
|
|
325
324
|
const decoded = require_multibase.decodeMultibase("ctimaq4ygg2iegci7");
|
|
326
325
|
(0, node_assert.deepStrictEqual)(require_multibase.decodeMultibase(require_multibase.encodeMultibase("c", decoded)), decoded);
|
|
327
326
|
});
|
|
328
327
|
});
|
|
329
|
-
(0,
|
|
330
|
-
await t.
|
|
328
|
+
(0, _fedify_fixture.test)("constants", async (t) => {
|
|
329
|
+
await t.step("constants indexed by name", () => {
|
|
331
330
|
const names$1 = require_multibase.names;
|
|
332
331
|
(0, node_assert.deepStrictEqual)(Object.keys(names$1).length, 23);
|
|
333
332
|
});
|
|
334
|
-
await t.
|
|
333
|
+
await t.step("constants indexed by code", () => {
|
|
335
334
|
const codes$1 = require_multibase.codes;
|
|
336
335
|
(0, node_assert.deepStrictEqual)(Object.keys(codes$1).length, 23);
|
|
337
336
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as names, i as codes, n as encodeMultibase, o as decodeText, s as encodeText, t as decodeMultibase } from "../multibase-BPnF_L4e.mjs";
|
|
2
2
|
import { deepStrictEqual } from "node:assert";
|
|
3
|
-
import { test } from "
|
|
3
|
+
import { test } from "@fedify/fixture";
|
|
4
4
|
//#region src/multibase/multibase.test.ts
|
|
5
5
|
test("multibase.encode and decode", async (t) => {
|
|
6
6
|
const testCases = [
|
|
@@ -315,21 +315,21 @@ test("multibase.encode and decode", async (t) => {
|
|
|
315
315
|
"Uw7fDr8O_8J-lsMO3w6_Dv_CfmI7wn6W28J-krw=="
|
|
316
316
|
]
|
|
317
317
|
];
|
|
318
|
-
for (const [name, input, expectedOutput] of testCases) await t.
|
|
318
|
+
for (const [name, input, expectedOutput] of testCases) await t.step(`Encoding/Decoding ${name} with ${input}`, () => {
|
|
319
319
|
deepStrictEqual(decodeText(encodeMultibase(name, encodeText(input))), expectedOutput, `Encoding ${name} failed`);
|
|
320
320
|
deepStrictEqual(decodeMultibase(expectedOutput), encodeText(input), `Decoding ${name} failed`);
|
|
321
321
|
deepStrictEqual(decodeMultibase(encodeText(expectedOutput)), encodeText(input), `Decoding buffer of ${name} failed`);
|
|
322
322
|
});
|
|
323
|
-
await t.
|
|
323
|
+
await t.step("should allow base32pad full alphabet", () => {
|
|
324
324
|
const decoded = decodeMultibase("ctimaq4ygg2iegci7");
|
|
325
325
|
deepStrictEqual(decodeMultibase(encodeMultibase("c", decoded)), decoded);
|
|
326
326
|
});
|
|
327
327
|
});
|
|
328
328
|
test("constants", async (t) => {
|
|
329
|
-
await t.
|
|
329
|
+
await t.step("constants indexed by name", () => {
|
|
330
330
|
deepStrictEqual(Object.keys(names).length, 23);
|
|
331
331
|
});
|
|
332
|
-
await t.
|
|
332
|
+
await t.step("constants indexed by code", () => {
|
|
333
333
|
deepStrictEqual(Object.keys(codes).length, 23);
|
|
334
334
|
});
|
|
335
335
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
2
2
|
let _multiformats_base_x = require("@multiformats/base-x");
|
|
3
|
-
_multiformats_base_x =
|
|
3
|
+
_multiformats_base_x = require_rolldown_runtime.__toESM(_multiformats_base_x, 1);
|
|
4
4
|
//#region src/multibase/util.ts
|
|
5
5
|
const textDecoder = new TextDecoder();
|
|
6
6
|
const decodeText = (bytes) => textDecoder.decode(bytes);
|
|
@@ -305,6 +305,17 @@ function encoding(nameOrCode) {
|
|
|
305
305
|
else if (Object.prototype.hasOwnProperty.call(codes, nameOrCode)) return codes[nameOrCode];
|
|
306
306
|
else throw new Error(`Unsupported encoding: ${nameOrCode}`);
|
|
307
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Get encoding multibase from data
|
|
310
|
+
*
|
|
311
|
+
* @param {string|Uint8Array} data
|
|
312
|
+
* @returns {Base}
|
|
313
|
+
* @throws {Error} Will throw if the encoding is not supported
|
|
314
|
+
*/
|
|
315
|
+
function encodingFromBaseData(data) {
|
|
316
|
+
if (data instanceof Uint8Array) data = decodeText(data);
|
|
317
|
+
return encoding(data[0]);
|
|
318
|
+
}
|
|
308
319
|
//#endregion
|
|
309
320
|
Object.defineProperty(exports, "codes", {
|
|
310
321
|
enumerable: true,
|
|
@@ -336,6 +347,12 @@ Object.defineProperty(exports, "encodeText", {
|
|
|
336
347
|
return encodeText;
|
|
337
348
|
}
|
|
338
349
|
});
|
|
350
|
+
Object.defineProperty(exports, "encodingFromBaseData", {
|
|
351
|
+
enumerable: true,
|
|
352
|
+
get: function() {
|
|
353
|
+
return encodingFromBaseData;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
339
356
|
Object.defineProperty(exports, "names", {
|
|
340
357
|
enumerable: true,
|
|
341
358
|
get: function() {
|
|
@@ -303,5 +303,16 @@ function encoding(nameOrCode) {
|
|
|
303
303
|
else if (Object.prototype.hasOwnProperty.call(codes, nameOrCode)) return codes[nameOrCode];
|
|
304
304
|
else throw new Error(`Unsupported encoding: ${nameOrCode}`);
|
|
305
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Get encoding multibase from data
|
|
308
|
+
*
|
|
309
|
+
* @param {string|Uint8Array} data
|
|
310
|
+
* @returns {Base}
|
|
311
|
+
* @throws {Error} Will throw if the encoding is not supported
|
|
312
|
+
*/
|
|
313
|
+
function encodingFromBaseData(data) {
|
|
314
|
+
if (data instanceof Uint8Array) data = decodeText(data);
|
|
315
|
+
return encoding(data[0]);
|
|
316
|
+
}
|
|
306
317
|
//#endregion
|
|
307
|
-
export {
|
|
318
|
+
export { names as a, codes as i, encodeMultibase as n, decodeText as o, encodingFromBaseData as r, encodeText as s, decodeMultibase as t };
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
const require_contexts = require("./contexts-DizzBjz4.cjs");
|
|
2
|
+
const require_url = require("./url-BNakuZ8k.cjs");
|
|
3
|
+
const require_jsonld_cache = require("./jsonld-cache-C07AyNOY.cjs");
|
|
4
|
+
let _logtape_logtape = require("@logtape/logtape");
|
|
5
|
+
require("@opentelemetry/api");
|
|
6
|
+
//#region src/internal/portable-dereference.ts
|
|
7
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
8
|
+
"fedify",
|
|
9
|
+
"vocab",
|
|
10
|
+
"gateway"
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* The maximum number of `@gateway` location hints to try for one reference.
|
|
14
|
+
* Hints come from possibly untrusted documents, so they are bounded to keep
|
|
15
|
+
* a single accessor call from fanning out to many servers.
|
|
16
|
+
*/
|
|
17
|
+
const MAX_GATEWAY_HINTS = 5;
|
|
18
|
+
const BASELINE_CONTEXT_URLS = /* @__PURE__ */ new Set([
|
|
19
|
+
"https://w3id.org/identity/v1",
|
|
20
|
+
"https://www.w3.org/ns/activitystreams",
|
|
21
|
+
"https://w3id.org/security/v1",
|
|
22
|
+
"https://w3id.org/security/data-integrity/v1"
|
|
23
|
+
]);
|
|
24
|
+
const provenances = /* @__PURE__ */ new WeakMap();
|
|
25
|
+
function getObjectId(object) {
|
|
26
|
+
if (object == null || typeof object !== "object" || !("id" in object)) return null;
|
|
27
|
+
const id = object.id;
|
|
28
|
+
return id instanceof URL ? id : null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Checks whether a vocabulary object is part of a chain of portable objects,
|
|
32
|
+
* i.e., whether it has a portable ID, has an FEP-ef61 compatible identifier
|
|
33
|
+
* as its ID (even a malformed one, so that it fails closed), or was obtained
|
|
34
|
+
* from a portable object. Accessors of such objects dereference references
|
|
35
|
+
* as portable objects.
|
|
36
|
+
*
|
|
37
|
+
* Being part of a chain does not mean that the object itself is verified:
|
|
38
|
+
* an object parsed from arbitrary JSON-LD is in a chain just because of its
|
|
39
|
+
* ID. Only {@link dereferencePortableIri} records that an object was
|
|
40
|
+
* accepted by a verifier.
|
|
41
|
+
*
|
|
42
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
43
|
+
* part of the public API contract. This is not considered public API for
|
|
44
|
+
* Semantic Versioning decisions.
|
|
45
|
+
*/
|
|
46
|
+
function isInPortableChain(object) {
|
|
47
|
+
if (provenances.has(object)) return true;
|
|
48
|
+
const id = getObjectId(object);
|
|
49
|
+
return id != null && (isPortableIri(id) || isCompatibleEf61Iri(id));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks whether a URL is an FEP-ef61 compatible identifier, i.e., an HTTP(S)
|
|
53
|
+
* URL under a gateway's `/.well-known/apgateway/` path that stands for
|
|
54
|
+
* a portable object. Malformed compatible identifiers count as compatible
|
|
55
|
+
* identifiers too.
|
|
56
|
+
*
|
|
57
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
58
|
+
* part of the public API contract. This is not considered public API for
|
|
59
|
+
* Semantic Versioning decisions.
|
|
60
|
+
*/
|
|
61
|
+
function isCompatibleEf61Iri(url) {
|
|
62
|
+
try {
|
|
63
|
+
return require_url.fromCompatibleEf61Id(url) != null;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (error instanceof TypeError) return true;
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Records that a vocabulary object returned by a property accessor was
|
|
71
|
+
* obtained through the given property of a portable object, so that later
|
|
72
|
+
* dereferences from it can tell where it came from. Nothing is recorded if
|
|
73
|
+
* the parent is not in a portable chain, or if the child already has its
|
|
74
|
+
* provenance.
|
|
75
|
+
*
|
|
76
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
77
|
+
* part of the public API contract. This is not considered public API for
|
|
78
|
+
* Semantic Versioning decisions.
|
|
79
|
+
*/
|
|
80
|
+
function recordPortableReferrer(parent, child, property) {
|
|
81
|
+
if (child == null || typeof child !== "object") return;
|
|
82
|
+
if (provenances.has(child) || !isInPortableChain(parent)) return;
|
|
83
|
+
provenances.set(child, { referrer: {
|
|
84
|
+
object: parent,
|
|
85
|
+
property
|
|
86
|
+
} });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Checks whether a URL is an FEP-ef61 portable ActivityPub IRI.
|
|
90
|
+
*
|
|
91
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
92
|
+
* part of the public API contract. This is not considered public API for
|
|
93
|
+
* Semantic Versioning decisions.
|
|
94
|
+
*/
|
|
95
|
+
function isPortableIri(url) {
|
|
96
|
+
return url.protocol === "ap+ef61:" || url.protocol === "ap:";
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Picks the ordered list of FEP-ef61 gateways to fetch a portable IRI from.
|
|
100
|
+
*
|
|
101
|
+
* If `gateways` is given, it is used as is (even when empty), and `@gateway`
|
|
102
|
+
* location hints in the IRI are ignored. Otherwise, up to
|
|
103
|
+
* {@link MAX_GATEWAY_HINTS} valid `@gateway` hints are used. Duplicate
|
|
104
|
+
* gateways are dropped in both cases.
|
|
105
|
+
*
|
|
106
|
+
* @throws {TypeError} If an explicit gateway is not an HTTP(S) origin.
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
function getPortableGatewayCandidates(url, gateways) {
|
|
110
|
+
const candidates = [];
|
|
111
|
+
const seen = /* @__PURE__ */ new Set();
|
|
112
|
+
const add = (gateway) => {
|
|
113
|
+
if (seen.has(gateway.href)) return;
|
|
114
|
+
seen.add(gateway.href);
|
|
115
|
+
candidates.push(gateway);
|
|
116
|
+
};
|
|
117
|
+
if (gateways != null) {
|
|
118
|
+
for (const gateway of gateways) {
|
|
119
|
+
const parsed = require_url.parseGatewayOrigin(gateway);
|
|
120
|
+
if (parsed == null) throw new TypeError("FEP-ef61 gateways must be HTTP(S) origins with no credentials, path, query, or fragment: " + String(gateway));
|
|
121
|
+
add(parsed);
|
|
122
|
+
}
|
|
123
|
+
return candidates;
|
|
124
|
+
}
|
|
125
|
+
for (const hint of new URLSearchParams(url.search).getAll(require_url.GATEWAY_HINT_PARAMETER)) {
|
|
126
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
127
|
+
const parsed = require_url.parseGatewayOrigin(hint);
|
|
128
|
+
if (parsed == null) {
|
|
129
|
+
logger.debug("Ignoring an invalid FEP-ef61 gateway hint {hint} in {url}.", {
|
|
130
|
+
hint,
|
|
131
|
+
url: require_url.formatIri(url)
|
|
132
|
+
});
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
add(parsed);
|
|
136
|
+
}
|
|
137
|
+
return candidates;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Gets the gateways through which a portable reference without location hints
|
|
141
|
+
* can be dereferenced, from the portable actor that the reference belongs to.
|
|
142
|
+
*
|
|
143
|
+
* The references in a portable actor's own document, such as its `outbox`,
|
|
144
|
+
* usually have no `@gateway` hints, as they are not needed there, since
|
|
145
|
+
* the actor's `gateways` already tells where to retrieve them. So this walks
|
|
146
|
+
* from the object whose property is being dereferenced up through the objects
|
|
147
|
+
* it was obtained from, e.g., from a collection page to the collection and
|
|
148
|
+
* then to the actor, and returns the `gateways` of the first object that has
|
|
149
|
+
* any, but only if that object has the same DID as the reference. The
|
|
150
|
+
* gateways only tell where to look; whatever they serve is still verified.
|
|
151
|
+
*
|
|
152
|
+
* @param object The object whose property is being dereferenced.
|
|
153
|
+
* @param url The portable IRI to dereference.
|
|
154
|
+
* @returns Up to {@link MAX_GATEWAY_HINTS} valid gateways, or `undefined` if
|
|
155
|
+
* the IRI has valid `@gateway` hints or no such object is found.
|
|
156
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
157
|
+
* part of the public API contract. This is not considered public API for
|
|
158
|
+
* Semantic Versioning decisions.
|
|
159
|
+
*/
|
|
160
|
+
function getReferrerGateways(object, url) {
|
|
161
|
+
if (getPortableGatewayCandidates(url).length > 0) return void 0;
|
|
162
|
+
const visited = /* @__PURE__ */ new Set();
|
|
163
|
+
let current = object;
|
|
164
|
+
while (current != null && !visited.has(current)) {
|
|
165
|
+
visited.add(current);
|
|
166
|
+
const gateways = "gateways" in current ? current.gateways : void 0;
|
|
167
|
+
if (Array.isArray(gateways) && gateways.length > 0) {
|
|
168
|
+
const id = getObjectId(current);
|
|
169
|
+
const portableId = id == null ? null : isPortableIri(id) ? id : getCompatibleEf61Target(id);
|
|
170
|
+
if (portableId == null || !require_url.haveSameFe34Origin(portableId, url)) return;
|
|
171
|
+
const candidates = [];
|
|
172
|
+
for (const gateway of gateways) {
|
|
173
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
174
|
+
if (typeof gateway !== "string" && !(gateway instanceof URL)) continue;
|
|
175
|
+
const parsed = require_url.parseGatewayOrigin(gateway);
|
|
176
|
+
if (parsed == null) continue;
|
|
177
|
+
if (candidates.some((c) => c.href === parsed.href)) continue;
|
|
178
|
+
candidates.push(parsed);
|
|
179
|
+
}
|
|
180
|
+
return candidates.length > 0 ? candidates : void 0;
|
|
181
|
+
}
|
|
182
|
+
current = provenances.get(current)?.referrer?.object;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function getCompatibleEf61Target(id) {
|
|
186
|
+
try {
|
|
187
|
+
return require_url.fromCompatibleEf61Id(id);
|
|
188
|
+
} catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Creates a context loader that returns the same context documents for the
|
|
194
|
+
* whole dereference operation, so that the identity check, the proof
|
|
195
|
+
* verifier, and the parser interpret the fetched document identically even
|
|
196
|
+
* if the underlying loader is nondeterministic. Failed loads are not
|
|
197
|
+
* remembered, so a transient failure does not affect the next gateway.
|
|
198
|
+
*
|
|
199
|
+
* The parsed object keeps the loader for its own later dereferences, so
|
|
200
|
+
* `release()` turns it into a plain pass-through to the underlying loader
|
|
201
|
+
* once the operation is over.
|
|
202
|
+
*
|
|
203
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
204
|
+
* part of the public API contract. This is not considered public API for
|
|
205
|
+
* Semantic Versioning decisions.
|
|
206
|
+
*/
|
|
207
|
+
function createSnapshotContextLoader(contextLoader, suppressError) {
|
|
208
|
+
contextLoader = require_jsonld_cache.unwrapReleasedDocumentLoader(contextLoader);
|
|
209
|
+
const cache = /* @__PURE__ */ new Map();
|
|
210
|
+
let released = false;
|
|
211
|
+
const release = () => {
|
|
212
|
+
released = true;
|
|
213
|
+
state.released = true;
|
|
214
|
+
cache.clear();
|
|
215
|
+
};
|
|
216
|
+
const loader = async (url, options) => {
|
|
217
|
+
if (released) return await contextLoader(url, options);
|
|
218
|
+
const key = URL.canParse(url) ? new URL(url).href : url;
|
|
219
|
+
if (BASELINE_CONTEXT_URLS.has(key)) return {
|
|
220
|
+
contextUrl: null,
|
|
221
|
+
document: structuredClone(require_contexts.preloadedContexts[key]),
|
|
222
|
+
documentUrl: key
|
|
223
|
+
};
|
|
224
|
+
let promise = cache.get(key);
|
|
225
|
+
if (promise == null) {
|
|
226
|
+
const loading = contextLoader(url, suppressError ? {
|
|
227
|
+
...options,
|
|
228
|
+
suppressError: true
|
|
229
|
+
} : options).then((document) => structuredClone(document));
|
|
230
|
+
promise = loading;
|
|
231
|
+
cache.set(key, loading);
|
|
232
|
+
loading.catch(() => {
|
|
233
|
+
if (cache.get(key) === loading) cache.delete(key);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return structuredClone(await promise);
|
|
237
|
+
};
|
|
238
|
+
const state = {
|
|
239
|
+
base: contextLoader,
|
|
240
|
+
released: false
|
|
241
|
+
};
|
|
242
|
+
require_jsonld_cache.registerDocumentLoaderWrapper(loader, state);
|
|
243
|
+
return {
|
|
244
|
+
loader,
|
|
245
|
+
release
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
Object.defineProperty(exports, "createSnapshotContextLoader", {
|
|
250
|
+
enumerable: true,
|
|
251
|
+
get: function() {
|
|
252
|
+
return createSnapshotContextLoader;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
Object.defineProperty(exports, "getPortableGatewayCandidates", {
|
|
256
|
+
enumerable: true,
|
|
257
|
+
get: function() {
|
|
258
|
+
return getPortableGatewayCandidates;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
Object.defineProperty(exports, "getReferrerGateways", {
|
|
262
|
+
enumerable: true,
|
|
263
|
+
get: function() {
|
|
264
|
+
return getReferrerGateways;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
Object.defineProperty(exports, "isPortableIri", {
|
|
268
|
+
enumerable: true,
|
|
269
|
+
get: function() {
|
|
270
|
+
return isPortableIri;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
Object.defineProperty(exports, "recordPortableReferrer", {
|
|
274
|
+
enumerable: true,
|
|
275
|
+
get: function() {
|
|
276
|
+
return recordPortableReferrer;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { t as preloadedContexts } from "./contexts-CIKsin4e.mjs";
|
|
2
|
+
import { h as parseGatewayOrigin, o as formatIri, s as fromCompatibleEf61Id, t as GATEWAY_HINT_PARAMETER, u as haveSameFe34Origin } from "./url-DMxmp7ZG.mjs";
|
|
3
|
+
import { c as unwrapReleasedDocumentLoader, s as registerDocumentLoaderWrapper } from "./jsonld-cache-BPQmOZWD.mjs";
|
|
4
|
+
import { getLogger } from "@logtape/logtape";
|
|
5
|
+
import "@opentelemetry/api";
|
|
6
|
+
//#region src/internal/portable-dereference.ts
|
|
7
|
+
const logger = getLogger([
|
|
8
|
+
"fedify",
|
|
9
|
+
"vocab",
|
|
10
|
+
"gateway"
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* The maximum number of `@gateway` location hints to try for one reference.
|
|
14
|
+
* Hints come from possibly untrusted documents, so they are bounded to keep
|
|
15
|
+
* a single accessor call from fanning out to many servers.
|
|
16
|
+
*/
|
|
17
|
+
const MAX_GATEWAY_HINTS = 5;
|
|
18
|
+
const BASELINE_CONTEXT_URLS = /* @__PURE__ */ new Set([
|
|
19
|
+
"https://w3id.org/identity/v1",
|
|
20
|
+
"https://www.w3.org/ns/activitystreams",
|
|
21
|
+
"https://w3id.org/security/v1",
|
|
22
|
+
"https://w3id.org/security/data-integrity/v1"
|
|
23
|
+
]);
|
|
24
|
+
const provenances = /* @__PURE__ */ new WeakMap();
|
|
25
|
+
function getObjectId(object) {
|
|
26
|
+
if (object == null || typeof object !== "object" || !("id" in object)) return null;
|
|
27
|
+
const id = object.id;
|
|
28
|
+
return id instanceof URL ? id : null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Checks whether a vocabulary object is part of a chain of portable objects,
|
|
32
|
+
* i.e., whether it has a portable ID, has an FEP-ef61 compatible identifier
|
|
33
|
+
* as its ID (even a malformed one, so that it fails closed), or was obtained
|
|
34
|
+
* from a portable object. Accessors of such objects dereference references
|
|
35
|
+
* as portable objects.
|
|
36
|
+
*
|
|
37
|
+
* Being part of a chain does not mean that the object itself is verified:
|
|
38
|
+
* an object parsed from arbitrary JSON-LD is in a chain just because of its
|
|
39
|
+
* ID. Only {@link dereferencePortableIri} records that an object was
|
|
40
|
+
* accepted by a verifier.
|
|
41
|
+
*
|
|
42
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
43
|
+
* part of the public API contract. This is not considered public API for
|
|
44
|
+
* Semantic Versioning decisions.
|
|
45
|
+
*/
|
|
46
|
+
function isInPortableChain(object) {
|
|
47
|
+
if (provenances.has(object)) return true;
|
|
48
|
+
const id = getObjectId(object);
|
|
49
|
+
return id != null && (isPortableIri(id) || isCompatibleEf61Iri(id));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks whether a URL is an FEP-ef61 compatible identifier, i.e., an HTTP(S)
|
|
53
|
+
* URL under a gateway's `/.well-known/apgateway/` path that stands for
|
|
54
|
+
* a portable object. Malformed compatible identifiers count as compatible
|
|
55
|
+
* identifiers too.
|
|
56
|
+
*
|
|
57
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
58
|
+
* part of the public API contract. This is not considered public API for
|
|
59
|
+
* Semantic Versioning decisions.
|
|
60
|
+
*/
|
|
61
|
+
function isCompatibleEf61Iri(url) {
|
|
62
|
+
try {
|
|
63
|
+
return fromCompatibleEf61Id(url) != null;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (error instanceof TypeError) return true;
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Records that a vocabulary object returned by a property accessor was
|
|
71
|
+
* obtained through the given property of a portable object, so that later
|
|
72
|
+
* dereferences from it can tell where it came from. Nothing is recorded if
|
|
73
|
+
* the parent is not in a portable chain, or if the child already has its
|
|
74
|
+
* provenance.
|
|
75
|
+
*
|
|
76
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
77
|
+
* part of the public API contract. This is not considered public API for
|
|
78
|
+
* Semantic Versioning decisions.
|
|
79
|
+
*/
|
|
80
|
+
function recordPortableReferrer(parent, child, property) {
|
|
81
|
+
if (child == null || typeof child !== "object") return;
|
|
82
|
+
if (provenances.has(child) || !isInPortableChain(parent)) return;
|
|
83
|
+
provenances.set(child, { referrer: {
|
|
84
|
+
object: parent,
|
|
85
|
+
property
|
|
86
|
+
} });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Checks whether a URL is an FEP-ef61 portable ActivityPub IRI.
|
|
90
|
+
*
|
|
91
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
92
|
+
* part of the public API contract. This is not considered public API for
|
|
93
|
+
* Semantic Versioning decisions.
|
|
94
|
+
*/
|
|
95
|
+
function isPortableIri(url) {
|
|
96
|
+
return url.protocol === "ap+ef61:" || url.protocol === "ap:";
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Picks the ordered list of FEP-ef61 gateways to fetch a portable IRI from.
|
|
100
|
+
*
|
|
101
|
+
* If `gateways` is given, it is used as is (even when empty), and `@gateway`
|
|
102
|
+
* location hints in the IRI are ignored. Otherwise, up to
|
|
103
|
+
* {@link MAX_GATEWAY_HINTS} valid `@gateway` hints are used. Duplicate
|
|
104
|
+
* gateways are dropped in both cases.
|
|
105
|
+
*
|
|
106
|
+
* @throws {TypeError} If an explicit gateway is not an HTTP(S) origin.
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
function getPortableGatewayCandidates(url, gateways) {
|
|
110
|
+
const candidates = [];
|
|
111
|
+
const seen = /* @__PURE__ */ new Set();
|
|
112
|
+
const add = (gateway) => {
|
|
113
|
+
if (seen.has(gateway.href)) return;
|
|
114
|
+
seen.add(gateway.href);
|
|
115
|
+
candidates.push(gateway);
|
|
116
|
+
};
|
|
117
|
+
if (gateways != null) {
|
|
118
|
+
for (const gateway of gateways) {
|
|
119
|
+
const parsed = parseGatewayOrigin(gateway);
|
|
120
|
+
if (parsed == null) throw new TypeError("FEP-ef61 gateways must be HTTP(S) origins with no credentials, path, query, or fragment: " + String(gateway));
|
|
121
|
+
add(parsed);
|
|
122
|
+
}
|
|
123
|
+
return candidates;
|
|
124
|
+
}
|
|
125
|
+
for (const hint of new URLSearchParams(url.search).getAll(GATEWAY_HINT_PARAMETER)) {
|
|
126
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
127
|
+
const parsed = parseGatewayOrigin(hint);
|
|
128
|
+
if (parsed == null) {
|
|
129
|
+
logger.debug("Ignoring an invalid FEP-ef61 gateway hint {hint} in {url}.", {
|
|
130
|
+
hint,
|
|
131
|
+
url: formatIri(url)
|
|
132
|
+
});
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
add(parsed);
|
|
136
|
+
}
|
|
137
|
+
return candidates;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Gets the gateways through which a portable reference without location hints
|
|
141
|
+
* can be dereferenced, from the portable actor that the reference belongs to.
|
|
142
|
+
*
|
|
143
|
+
* The references in a portable actor's own document, such as its `outbox`,
|
|
144
|
+
* usually have no `@gateway` hints, as they are not needed there, since
|
|
145
|
+
* the actor's `gateways` already tells where to retrieve them. So this walks
|
|
146
|
+
* from the object whose property is being dereferenced up through the objects
|
|
147
|
+
* it was obtained from, e.g., from a collection page to the collection and
|
|
148
|
+
* then to the actor, and returns the `gateways` of the first object that has
|
|
149
|
+
* any, but only if that object has the same DID as the reference. The
|
|
150
|
+
* gateways only tell where to look; whatever they serve is still verified.
|
|
151
|
+
*
|
|
152
|
+
* @param object The object whose property is being dereferenced.
|
|
153
|
+
* @param url The portable IRI to dereference.
|
|
154
|
+
* @returns Up to {@link MAX_GATEWAY_HINTS} valid gateways, or `undefined` if
|
|
155
|
+
* the IRI has valid `@gateway` hints or no such object is found.
|
|
156
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
157
|
+
* part of the public API contract. This is not considered public API for
|
|
158
|
+
* Semantic Versioning decisions.
|
|
159
|
+
*/
|
|
160
|
+
function getReferrerGateways(object, url) {
|
|
161
|
+
if (getPortableGatewayCandidates(url).length > 0) return void 0;
|
|
162
|
+
const visited = /* @__PURE__ */ new Set();
|
|
163
|
+
let current = object;
|
|
164
|
+
while (current != null && !visited.has(current)) {
|
|
165
|
+
visited.add(current);
|
|
166
|
+
const gateways = "gateways" in current ? current.gateways : void 0;
|
|
167
|
+
if (Array.isArray(gateways) && gateways.length > 0) {
|
|
168
|
+
const id = getObjectId(current);
|
|
169
|
+
const portableId = id == null ? null : isPortableIri(id) ? id : getCompatibleEf61Target(id);
|
|
170
|
+
if (portableId == null || !haveSameFe34Origin(portableId, url)) return;
|
|
171
|
+
const candidates = [];
|
|
172
|
+
for (const gateway of gateways) {
|
|
173
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
174
|
+
if (typeof gateway !== "string" && !(gateway instanceof URL)) continue;
|
|
175
|
+
const parsed = parseGatewayOrigin(gateway);
|
|
176
|
+
if (parsed == null) continue;
|
|
177
|
+
if (candidates.some((c) => c.href === parsed.href)) continue;
|
|
178
|
+
candidates.push(parsed);
|
|
179
|
+
}
|
|
180
|
+
return candidates.length > 0 ? candidates : void 0;
|
|
181
|
+
}
|
|
182
|
+
current = provenances.get(current)?.referrer?.object;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function getCompatibleEf61Target(id) {
|
|
186
|
+
try {
|
|
187
|
+
return fromCompatibleEf61Id(id);
|
|
188
|
+
} catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Creates a context loader that returns the same context documents for the
|
|
194
|
+
* whole dereference operation, so that the identity check, the proof
|
|
195
|
+
* verifier, and the parser interpret the fetched document identically even
|
|
196
|
+
* if the underlying loader is nondeterministic. Failed loads are not
|
|
197
|
+
* remembered, so a transient failure does not affect the next gateway.
|
|
198
|
+
*
|
|
199
|
+
* The parsed object keeps the loader for its own later dereferences, so
|
|
200
|
+
* `release()` turns it into a plain pass-through to the underlying loader
|
|
201
|
+
* once the operation is over.
|
|
202
|
+
*
|
|
203
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
204
|
+
* part of the public API contract. This is not considered public API for
|
|
205
|
+
* Semantic Versioning decisions.
|
|
206
|
+
*/
|
|
207
|
+
function createSnapshotContextLoader(contextLoader, suppressError) {
|
|
208
|
+
contextLoader = unwrapReleasedDocumentLoader(contextLoader);
|
|
209
|
+
const cache = /* @__PURE__ */ new Map();
|
|
210
|
+
let released = false;
|
|
211
|
+
const release = () => {
|
|
212
|
+
released = true;
|
|
213
|
+
state.released = true;
|
|
214
|
+
cache.clear();
|
|
215
|
+
};
|
|
216
|
+
const loader = async (url, options) => {
|
|
217
|
+
if (released) return await contextLoader(url, options);
|
|
218
|
+
const key = URL.canParse(url) ? new URL(url).href : url;
|
|
219
|
+
if (BASELINE_CONTEXT_URLS.has(key)) return {
|
|
220
|
+
contextUrl: null,
|
|
221
|
+
document: structuredClone(preloadedContexts[key]),
|
|
222
|
+
documentUrl: key
|
|
223
|
+
};
|
|
224
|
+
let promise = cache.get(key);
|
|
225
|
+
if (promise == null) {
|
|
226
|
+
const loading = contextLoader(url, suppressError ? {
|
|
227
|
+
...options,
|
|
228
|
+
suppressError: true
|
|
229
|
+
} : options).then((document) => structuredClone(document));
|
|
230
|
+
promise = loading;
|
|
231
|
+
cache.set(key, loading);
|
|
232
|
+
loading.catch(() => {
|
|
233
|
+
if (cache.get(key) === loading) cache.delete(key);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return structuredClone(await promise);
|
|
237
|
+
};
|
|
238
|
+
const state = {
|
|
239
|
+
base: contextLoader,
|
|
240
|
+
released: false
|
|
241
|
+
};
|
|
242
|
+
registerDocumentLoaderWrapper(loader, state);
|
|
243
|
+
return {
|
|
244
|
+
loader,
|
|
245
|
+
release
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
export { recordPortableReferrer as a, isPortableIri as i, getPortableGatewayCandidates as n, getReferrerGateways as r, createSnapshotContextLoader as t };
|