@fedify/vocab-runtime 2.4.0-dev.2030 → 2.4.0-dev.2047
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 +2 -1
- package/dist/internal/jsonld-cache.cjs +1 -1
- package/dist/internal/jsonld-cache.js +1 -1
- package/dist/internal/portable-dereference.cjs +315 -0
- package/dist/internal/portable-dereference.d.cts +87 -0
- package/dist/internal/portable-dereference.d.ts +87 -0
- package/dist/internal/portable-dereference.js +311 -0
- package/dist/mod.cjs +11 -3
- package/dist/mod.d.cts +75 -1
- package/dist/mod.d.ts +75 -1
- package/dist/mod.js +10 -4
- package/dist/portable-CduElToy.d.ts +52 -0
- package/dist/portable-DxF2Ut-Z.d.cts +52 -0
- package/dist/tests/{body-B9qsaRLZ.cjs → body-BgDeabVX.cjs} +1 -1
- package/dist/tests/{body-BhoBj6zg.mjs → body-D7iDYZxi.mjs} +1 -1
- package/dist/tests/body.test.cjs +1 -1
- package/dist/tests/body.test.mjs +1 -1
- package/dist/tests/decimal.test.cjs +2 -2
- package/dist/tests/decimal.test.mjs +2 -2
- package/dist/tests/{docloader--w8_lTnA.cjs → docloader-0r0eohuK.cjs} +3 -3
- package/dist/tests/{docloader-DKk8OANv.mjs → docloader-DzfRRzKc.mjs} +3 -3
- package/dist/tests/docloader.test.cjs +3 -3
- package/dist/tests/docloader.test.mjs +3 -3
- package/dist/tests/internal/portable-dereference.test.cjs +123 -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 +124 -0
- package/dist/tests/jsonld-CmDhHNTx.cjs +12 -0
- package/dist/tests/jsonld-DweIJ07b.mjs +5 -0
- package/dist/tests/jsonld-cache.test.cjs +18 -23
- package/dist/tests/jsonld-cache.test.mjs +2 -5
- package/dist/tests/{request-Dm_aAoKt.mjs → request-DOyNI0N1.mjs} +8 -2
- package/dist/tests/{request-D3Z--Onp.cjs → request-DdT5TslC.cjs} +8 -2
- package/dist/tests/request.test.cjs +4 -1
- package/dist/tests/request.test.mjs +4 -1
- package/dist/{url-i33c0US6.cjs → tests/url-BqlldzT8.cjs} +164 -1
- package/dist/tests/{url-Basm1L_c.mjs → url-DgJM9WJn.mjs} +147 -1
- package/dist/tests/url.test.cjs +220 -1
- package/dist/tests/url.test.mjs +220 -1
- package/dist/{url-BHAShw9J.js → url-CEhi4hb4.js} +147 -1
- package/dist/{tests/url-CPfMatUL.cjs → url-Cke4irYD.cjs} +155 -2
- package/package.json +12 -2
- package/src/internal/portable-dereference.test.ts +74 -0
- package/src/internal/portable-dereference.ts +426 -0
- package/src/mod.ts +6 -0
- package/src/portable.ts +52 -0
- package/src/request.test.ts +10 -1
- package/src/request.ts +9 -1
- package/src/url.test.ts +361 -0
- package/src/url.ts +235 -0
- package/tsdown.config.ts +1 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
import { n as DocumentLoader } from "./docloader-Dr8wEkif.cjs";
|
|
3
|
+
import { TracerProvider } from "@opentelemetry/api";
|
|
4
|
+
|
|
5
|
+
//#region src/portable.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Options passed to a {@link PortableObjectVerifier}.
|
|
8
|
+
* @since 2.4.0
|
|
9
|
+
*/
|
|
10
|
+
interface PortableObjectVerifierOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The document loader for fetching remote documents, such as verification
|
|
13
|
+
* methods that are not `did:key` URLs.
|
|
14
|
+
*/
|
|
15
|
+
readonly documentLoader?: DocumentLoader;
|
|
16
|
+
/**
|
|
17
|
+
* The document loader for fetching remote JSON-LD contexts. During
|
|
18
|
+
* gateway dereferencing, this loader returns the same context documents
|
|
19
|
+
* that the vocabulary parser sees.
|
|
20
|
+
*/
|
|
21
|
+
readonly contextLoader?: DocumentLoader;
|
|
22
|
+
/**
|
|
23
|
+
* The OpenTelemetry tracer provider.
|
|
24
|
+
*/
|
|
25
|
+
readonly tracerProvider?: TracerProvider;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A function that applies the [FEP-ef61] proof policy to a portable object
|
|
29
|
+
* fetched through a gateway.
|
|
30
|
+
*
|
|
31
|
+
* It receives the fetched JSON-LD document as is, and resolves to an object
|
|
32
|
+
* whose `verified` property tells whether the document carries a valid
|
|
33
|
+
* [FEP-8b32] Object Integrity Proof made by the DID in its portable ID.
|
|
34
|
+
* `verifyPortableObjectProof()` from `@fedify/fedify` satisfies this type, so
|
|
35
|
+
* it can be passed as the `verifyPortableObject` option of generated
|
|
36
|
+
* vocabulary accessors such as `Activity.getObject()`.
|
|
37
|
+
*
|
|
38
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
39
|
+
* [FEP-8b32]: https://w3id.org/fep/8b32
|
|
40
|
+
*
|
|
41
|
+
* @param document The fetched JSON-LD document.
|
|
42
|
+
* @param options Loaders and tracing options for verification.
|
|
43
|
+
* @returns An object whose `verified` property is `true` if and only if the
|
|
44
|
+
* document satisfies the proof policy. Other properties, such as
|
|
45
|
+
* a failure reason, are logged when verification fails.
|
|
46
|
+
* @since 2.4.0
|
|
47
|
+
*/
|
|
48
|
+
type PortableObjectVerifier = (document: unknown, options: PortableObjectVerifierOptions) => Promise<{
|
|
49
|
+
readonly verified: boolean;
|
|
50
|
+
}>;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { PortableObjectVerifierOptions as n, PortableObjectVerifier as t };
|
package/dist/tests/body.test.cjs
CHANGED
package/dist/tests/body.test.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as readBoundedText, t as BodyTooLargeError } from "./body-
|
|
1
|
+
import { r as readBoundedText, t as BodyTooLargeError } from "./body-D7iDYZxi.mjs";
|
|
2
2
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const require_request = require("./request-
|
|
2
|
-
const require_body = require("./body-
|
|
1
|
+
const require_request = require("./request-DdT5TslC.cjs");
|
|
2
|
+
const require_body = require("./body-BgDeabVX.cjs");
|
|
3
3
|
const require_contexts = require("./contexts-Ch3v2Cgu.cjs");
|
|
4
4
|
const require_link = require("./link-DlKm8bEr.cjs");
|
|
5
|
-
const require_url = require("./url-
|
|
5
|
+
const require_url = require("./url-BqlldzT8.cjs");
|
|
6
6
|
let _logtape_logtape = require("@logtape/logtape");
|
|
7
7
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
8
|
//#region src/docloader.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-
|
|
2
|
-
import { n as MAX_BODY_SIZE, r as readBoundedText, t as BodyTooLargeError } from "./body-
|
|
1
|
+
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-DOyNI0N1.mjs";
|
|
2
|
+
import { n as MAX_BODY_SIZE, r as readBoundedText, t as BodyTooLargeError } from "./body-D7iDYZxi.mjs";
|
|
3
3
|
import { t as preloadedContexts } from "./contexts-BBX_qhBL.mjs";
|
|
4
4
|
import { t as HttpHeaderLink } from "./link-Cevmc87v.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { t as UrlError, v as validatePublicUrl } from "./url-DgJM9WJn.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
8
8
|
//#region src/docloader.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-DdT5TslC.cjs");
|
|
3
3
|
const require_contexts = require("./contexts-Ch3v2Cgu.cjs");
|
|
4
|
-
const require_url = require("./url-
|
|
5
|
-
const require_docloader = require("./docloader
|
|
4
|
+
const require_url = require("./url-BqlldzT8.cjs");
|
|
5
|
+
const require_docloader = require("./docloader-0r0eohuK.cjs");
|
|
6
6
|
let node_test = require("node:test");
|
|
7
7
|
let node_zlib = require("node:zlib");
|
|
8
8
|
let node_assert = require("node:assert");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as FetchError } from "./request-
|
|
1
|
+
import { t as FetchError } from "./request-DOyNI0N1.mjs";
|
|
2
2
|
import { n as cid_v1_default, t as preloadedContexts } from "./contexts-BBX_qhBL.mjs";
|
|
3
|
-
import { t as UrlError } from "./url-
|
|
4
|
-
import { n as getRemoteDocument, t as getDocumentLoader } from "./docloader-
|
|
3
|
+
import { t as UrlError } from "./url-DgJM9WJn.mjs";
|
|
4
|
+
import { n as getRemoteDocument, t as getDocumentLoader } from "./docloader-DzfRRzKc.mjs";
|
|
5
5
|
import { test } from "node:test";
|
|
6
6
|
import { gzipSync } from "node:zlib";
|
|
7
7
|
import { deepStrictEqual, ok, rejects } from "node:assert";
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const require_url = require("../url-BqlldzT8.cjs");
|
|
2
|
+
require("../jsonld-CmDhHNTx.cjs");
|
|
3
|
+
let node_assert_strict = require("node:assert/strict");
|
|
4
|
+
let node_test = require("node:test");
|
|
5
|
+
let _logtape_logtape = require("@logtape/logtape");
|
|
6
|
+
require("@opentelemetry/api");
|
|
7
|
+
//#region src/internal/portable-dereference.ts
|
|
8
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
9
|
+
"fedify",
|
|
10
|
+
"vocab",
|
|
11
|
+
"gateway"
|
|
12
|
+
]);
|
|
13
|
+
/**
|
|
14
|
+
* The maximum number of `@gateway` location hints to try for one reference.
|
|
15
|
+
* Hints come from possibly untrusted documents, so they are bounded to keep
|
|
16
|
+
* a single accessor call from fanning out to many servers.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_GATEWAY_HINTS = 5;
|
|
19
|
+
const LOCATION_HINT_PARAMETER = "@gateway";
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether a URL is an FEP-ef61 portable ActivityPub IRI.
|
|
22
|
+
*
|
|
23
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
24
|
+
* part of the public API contract. This is not considered public API for
|
|
25
|
+
* Semantic Versioning decisions.
|
|
26
|
+
*/
|
|
27
|
+
function isPortableIri(url) {
|
|
28
|
+
return url.protocol === "ap+ef61:" || url.protocol === "ap:";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Picks the ordered list of FEP-ef61 gateways to fetch a portable IRI from.
|
|
32
|
+
*
|
|
33
|
+
* If `gateways` is given, it is used as is (even when empty), and `@gateway`
|
|
34
|
+
* location hints in the IRI are ignored. Otherwise, up to
|
|
35
|
+
* {@link MAX_GATEWAY_HINTS} valid `@gateway` hints are used. Duplicate
|
|
36
|
+
* gateways are dropped in both cases.
|
|
37
|
+
*
|
|
38
|
+
* @throws {TypeError} If an explicit gateway is not an HTTP(S) origin.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
function getPortableGatewayCandidates(url, gateways) {
|
|
42
|
+
const candidates = [];
|
|
43
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44
|
+
const add = (gateway) => {
|
|
45
|
+
if (seen.has(gateway.href)) return;
|
|
46
|
+
seen.add(gateway.href);
|
|
47
|
+
candidates.push(gateway);
|
|
48
|
+
};
|
|
49
|
+
if (gateways != null) {
|
|
50
|
+
for (const gateway of gateways) {
|
|
51
|
+
const parsed = parseGatewayOrigin(gateway);
|
|
52
|
+
if (parsed == null) throw new TypeError("FEP-ef61 gateways must be HTTP(S) origins with no credentials, path, query, or fragment: " + String(gateway));
|
|
53
|
+
add(parsed);
|
|
54
|
+
}
|
|
55
|
+
return candidates;
|
|
56
|
+
}
|
|
57
|
+
for (const hint of new URLSearchParams(url.search).getAll(LOCATION_HINT_PARAMETER)) {
|
|
58
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
59
|
+
const parsed = parseGatewayOrigin(hint);
|
|
60
|
+
if (parsed == null) {
|
|
61
|
+
logger.debug("Ignoring an invalid FEP-ef61 gateway hint {hint} in {url}.", {
|
|
62
|
+
hint,
|
|
63
|
+
url: require_url.formatIri(url)
|
|
64
|
+
});
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
add(parsed);
|
|
68
|
+
}
|
|
69
|
+
return candidates;
|
|
70
|
+
}
|
|
71
|
+
function parseGatewayOrigin(gateway) {
|
|
72
|
+
let url;
|
|
73
|
+
if (gateway instanceof URL) url = new URL(gateway.href);
|
|
74
|
+
else if (typeof gateway === "string" && URL.canParse(gateway)) url = new URL(gateway);
|
|
75
|
+
else return null;
|
|
76
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.href !== `${url.origin}/`) return null;
|
|
77
|
+
return url;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/internal/portable-dereference.test.ts
|
|
81
|
+
const hrefs = (urls) => urls.map((url) => url.href);
|
|
82
|
+
(0, node_test.test)("isPortableIri()", () => {
|
|
83
|
+
(0, node_assert_strict.ok)(isPortableIri(require_url.parseIri("ap://did:key:z6Mkabc/actor")));
|
|
84
|
+
(0, node_assert_strict.ok)(isPortableIri(require_url.parseIri("ap+ef61://did:key:z6Mkabc/actor")));
|
|
85
|
+
(0, node_assert_strict.ok)(isPortableIri(new URL("ap://did%3Akey%3Az6Mkabc/actor")));
|
|
86
|
+
(0, node_assert_strict.ok)(!isPortableIri(new URL("https://example.com/actor")));
|
|
87
|
+
(0, node_assert_strict.ok)(!isPortableIri(new URL("did:key:z6Mkabc")));
|
|
88
|
+
});
|
|
89
|
+
(0, node_test.test)("getPortableGatewayCandidates() uses explicit gateways", () => {
|
|
90
|
+
const url = require_url.parseIri("ap://did:key:z6Mkabc/actor?@gateway=https%3A%2F%2Fhint.example");
|
|
91
|
+
(0, node_assert_strict.deepStrictEqual)(hrefs(getPortableGatewayCandidates(url, [
|
|
92
|
+
"https://b.example",
|
|
93
|
+
new URL("https://a.example/"),
|
|
94
|
+
"https://b.example/",
|
|
95
|
+
"http://c.example:8080"
|
|
96
|
+
])), [
|
|
97
|
+
"https://b.example/",
|
|
98
|
+
"https://a.example/",
|
|
99
|
+
"http://c.example:8080/"
|
|
100
|
+
]);
|
|
101
|
+
(0, node_assert_strict.deepStrictEqual)(getPortableGatewayCandidates(url, []), []);
|
|
102
|
+
for (const gateway of [
|
|
103
|
+
"https://a.example/path",
|
|
104
|
+
"https://a.example/?",
|
|
105
|
+
"https://a.example/#",
|
|
106
|
+
"https://user:pass@a.example",
|
|
107
|
+
"ftp://a.example",
|
|
108
|
+
"a.example"
|
|
109
|
+
]) (0, node_assert_strict.throws)(() => getPortableGatewayCandidates(url, [gateway]), TypeError);
|
|
110
|
+
});
|
|
111
|
+
(0, node_test.test)("getPortableGatewayCandidates() reads @gateway hints", () => {
|
|
112
|
+
(0, node_assert_strict.deepStrictEqual)(hrefs(getPortableGatewayCandidates(require_url.parseIri("ap://did:key:z6Mkabc/actor?page=1&@gateway=https%3A%2F%2Fa.example&gateways=https%3A%2F%2Flegacy.example&@gateway=not%20a%20URL&@gateway=https%3A%2F%2Fb.example%2Fpath&%40gateway=https%3A%2F%2Fb.example&@gateway=https%3A%2F%2Fa.example%2F"))), ["https://a.example/", "https://b.example/"]);
|
|
113
|
+
(0, node_assert_strict.deepStrictEqual)(getPortableGatewayCandidates(require_url.parseIri("ap://did:key:z6Mkabc/actor")), []);
|
|
114
|
+
const hints = Array.from({ length: 7 }, (_, i) => `@gateway=https%3A%2F%2Fg${i}.example`);
|
|
115
|
+
(0, node_assert_strict.deepStrictEqual)(hrefs(getPortableGatewayCandidates(require_url.parseIri(`ap://did:key:z6Mkabc/actor?${hints.join("&")}`))), [
|
|
116
|
+
0,
|
|
117
|
+
1,
|
|
118
|
+
2,
|
|
119
|
+
3,
|
|
120
|
+
4
|
|
121
|
+
].map((i) => `https://g${i}.example/`));
|
|
122
|
+
});
|
|
123
|
+
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { a as formatIri, m as parseIri } from "../url-DgJM9WJn.mjs";
|
|
2
|
+
import "../jsonld-DweIJ07b.mjs";
|
|
3
|
+
import { deepStrictEqual, ok, throws } from "node:assert/strict";
|
|
4
|
+
import { test } from "node:test";
|
|
5
|
+
import { getLogger } from "@logtape/logtape";
|
|
6
|
+
import "@opentelemetry/api";
|
|
7
|
+
//#region src/internal/portable-dereference.ts
|
|
8
|
+
const logger = getLogger([
|
|
9
|
+
"fedify",
|
|
10
|
+
"vocab",
|
|
11
|
+
"gateway"
|
|
12
|
+
]);
|
|
13
|
+
/**
|
|
14
|
+
* The maximum number of `@gateway` location hints to try for one reference.
|
|
15
|
+
* Hints come from possibly untrusted documents, so they are bounded to keep
|
|
16
|
+
* a single accessor call from fanning out to many servers.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_GATEWAY_HINTS = 5;
|
|
19
|
+
const LOCATION_HINT_PARAMETER = "@gateway";
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether a URL is an FEP-ef61 portable ActivityPub IRI.
|
|
22
|
+
*
|
|
23
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
24
|
+
* part of the public API contract. This is not considered public API for
|
|
25
|
+
* Semantic Versioning decisions.
|
|
26
|
+
*/
|
|
27
|
+
function isPortableIri(url) {
|
|
28
|
+
return url.protocol === "ap+ef61:" || url.protocol === "ap:";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Picks the ordered list of FEP-ef61 gateways to fetch a portable IRI from.
|
|
32
|
+
*
|
|
33
|
+
* If `gateways` is given, it is used as is (even when empty), and `@gateway`
|
|
34
|
+
* location hints in the IRI are ignored. Otherwise, up to
|
|
35
|
+
* {@link MAX_GATEWAY_HINTS} valid `@gateway` hints are used. Duplicate
|
|
36
|
+
* gateways are dropped in both cases.
|
|
37
|
+
*
|
|
38
|
+
* @throws {TypeError} If an explicit gateway is not an HTTP(S) origin.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
function getPortableGatewayCandidates(url, gateways) {
|
|
42
|
+
const candidates = [];
|
|
43
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44
|
+
const add = (gateway) => {
|
|
45
|
+
if (seen.has(gateway.href)) return;
|
|
46
|
+
seen.add(gateway.href);
|
|
47
|
+
candidates.push(gateway);
|
|
48
|
+
};
|
|
49
|
+
if (gateways != null) {
|
|
50
|
+
for (const gateway of gateways) {
|
|
51
|
+
const parsed = parseGatewayOrigin(gateway);
|
|
52
|
+
if (parsed == null) throw new TypeError("FEP-ef61 gateways must be HTTP(S) origins with no credentials, path, query, or fragment: " + String(gateway));
|
|
53
|
+
add(parsed);
|
|
54
|
+
}
|
|
55
|
+
return candidates;
|
|
56
|
+
}
|
|
57
|
+
for (const hint of new URLSearchParams(url.search).getAll(LOCATION_HINT_PARAMETER)) {
|
|
58
|
+
if (candidates.length >= MAX_GATEWAY_HINTS) break;
|
|
59
|
+
const parsed = parseGatewayOrigin(hint);
|
|
60
|
+
if (parsed == null) {
|
|
61
|
+
logger.debug("Ignoring an invalid FEP-ef61 gateway hint {hint} in {url}.", {
|
|
62
|
+
hint,
|
|
63
|
+
url: formatIri(url)
|
|
64
|
+
});
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
add(parsed);
|
|
68
|
+
}
|
|
69
|
+
return candidates;
|
|
70
|
+
}
|
|
71
|
+
function parseGatewayOrigin(gateway) {
|
|
72
|
+
let url;
|
|
73
|
+
if (gateway instanceof URL) url = new URL(gateway.href);
|
|
74
|
+
else if (typeof gateway === "string" && URL.canParse(gateway)) url = new URL(gateway);
|
|
75
|
+
else return null;
|
|
76
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.href !== `${url.origin}/`) return null;
|
|
77
|
+
return url;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/internal/portable-dereference.test.ts
|
|
81
|
+
const hrefs = (urls) => urls.map((url) => url.href);
|
|
82
|
+
test("isPortableIri()", () => {
|
|
83
|
+
ok(isPortableIri(parseIri("ap://did:key:z6Mkabc/actor")));
|
|
84
|
+
ok(isPortableIri(parseIri("ap+ef61://did:key:z6Mkabc/actor")));
|
|
85
|
+
ok(isPortableIri(new URL("ap://did%3Akey%3Az6Mkabc/actor")));
|
|
86
|
+
ok(!isPortableIri(new URL("https://example.com/actor")));
|
|
87
|
+
ok(!isPortableIri(new URL("did:key:z6Mkabc")));
|
|
88
|
+
});
|
|
89
|
+
test("getPortableGatewayCandidates() uses explicit gateways", () => {
|
|
90
|
+
const url = parseIri("ap://did:key:z6Mkabc/actor?@gateway=https%3A%2F%2Fhint.example");
|
|
91
|
+
deepStrictEqual(hrefs(getPortableGatewayCandidates(url, [
|
|
92
|
+
"https://b.example",
|
|
93
|
+
new URL("https://a.example/"),
|
|
94
|
+
"https://b.example/",
|
|
95
|
+
"http://c.example:8080"
|
|
96
|
+
])), [
|
|
97
|
+
"https://b.example/",
|
|
98
|
+
"https://a.example/",
|
|
99
|
+
"http://c.example:8080/"
|
|
100
|
+
]);
|
|
101
|
+
deepStrictEqual(getPortableGatewayCandidates(url, []), []);
|
|
102
|
+
for (const gateway of [
|
|
103
|
+
"https://a.example/path",
|
|
104
|
+
"https://a.example/?",
|
|
105
|
+
"https://a.example/#",
|
|
106
|
+
"https://user:pass@a.example",
|
|
107
|
+
"ftp://a.example",
|
|
108
|
+
"a.example"
|
|
109
|
+
]) throws(() => getPortableGatewayCandidates(url, [gateway]), TypeError);
|
|
110
|
+
});
|
|
111
|
+
test("getPortableGatewayCandidates() reads @gateway hints", () => {
|
|
112
|
+
deepStrictEqual(hrefs(getPortableGatewayCandidates(parseIri("ap://did:key:z6Mkabc/actor?page=1&@gateway=https%3A%2F%2Fa.example&gateways=https%3A%2F%2Flegacy.example&@gateway=not%20a%20URL&@gateway=https%3A%2F%2Fb.example%2Fpath&%40gateway=https%3A%2F%2Fb.example&@gateway=https%3A%2F%2Fa.example%2F"))), ["https://a.example/", "https://b.example/"]);
|
|
113
|
+
deepStrictEqual(getPortableGatewayCandidates(parseIri("ap://did:key:z6Mkabc/actor")), []);
|
|
114
|
+
const hints = Array.from({ length: 7 }, (_, i) => `@gateway=https%3A%2F%2Fg${i}.example`);
|
|
115
|
+
deepStrictEqual(hrefs(getPortableGatewayCandidates(parseIri(`ap://did:key:z6Mkabc/actor?${hints.join("&")}`))), [
|
|
116
|
+
0,
|
|
117
|
+
1,
|
|
118
|
+
2,
|
|
119
|
+
3,
|
|
120
|
+
4
|
|
121
|
+
].map((i) => `https://g${i}.example/`));
|
|
122
|
+
});
|
|
123
|
+
//#endregion
|
|
124
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
2
|
+
let jsonld_dist_jsonld_esm_js = require("jsonld/dist/jsonld.esm.js");
|
|
3
|
+
jsonld_dist_jsonld_esm_js = require_rolldown_runtime.__toESM(jsonld_dist_jsonld_esm_js, 1);
|
|
4
|
+
//#region src/jsonld.ts
|
|
5
|
+
var jsonld_default = jsonld_dist_jsonld_esm_js.default;
|
|
6
|
+
//#endregion
|
|
7
|
+
Object.defineProperty(exports, "jsonld_default", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function() {
|
|
10
|
+
return jsonld_default;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const require_url = require("./url-BqlldzT8.cjs");
|
|
2
|
+
const require_jsonld = require("./jsonld-CmDhHNTx.cjs");
|
|
3
3
|
let node_test = require("node:test");
|
|
4
4
|
let node_assert = require("node:assert");
|
|
5
|
-
let jsonld_dist_jsonld_esm_js = require("jsonld/dist/jsonld.esm.js");
|
|
6
|
-
jsonld_dist_jsonld_esm_js = require_rolldown_runtime.__toESM(jsonld_dist_jsonld_esm_js, 1);
|
|
7
|
-
//#region src/jsonld.ts
|
|
8
|
-
var jsonld_default = jsonld_dist_jsonld_esm_js.default;
|
|
9
|
-
//#endregion
|
|
10
5
|
//#region src/internal/jsonld-cache.ts
|
|
11
6
|
const noJsonLdContext = Symbol("noJsonLdContext");
|
|
12
7
|
/**
|
|
@@ -121,7 +116,7 @@ async function compactJsonLdCache(normalized, original, documentLoader, depth =
|
|
|
121
116
|
const ownContext = getOwnJsonLdContext(original);
|
|
122
117
|
const context = ownContext === noJsonLdContext ? inheritedContext : ownContext;
|
|
123
118
|
if (context == null) return preserveNoContextJsonLdShape(normalized, original, depth);
|
|
124
|
-
return await preserveJsonLdShape(await mergeUnmappedTerms(await jsonld_default.compact(Array.isArray(normalized) && normalized.length === 1 ? normalized[0] : normalized, context, { documentLoader }), original, context, documentLoader), original, context, documentLoader, depth);
|
|
119
|
+
return await preserveJsonLdShape(await mergeUnmappedTerms(await require_jsonld.jsonld_default.compact(Array.isArray(normalized) && normalized.length === 1 ? normalized[0] : normalized, context, { documentLoader }), original, context, documentLoader), original, context, documentLoader, depth);
|
|
125
120
|
}
|
|
126
121
|
function preserveNoContextJsonLdShape(normalized, original, depth = 0) {
|
|
127
122
|
if (depth > 32) return normalized;
|
|
@@ -184,11 +179,11 @@ async function mergeUnmappedTerms(compacted, original, context, documentLoader)
|
|
|
184
179
|
"@context": context,
|
|
185
180
|
...compacted
|
|
186
181
|
} : compacted;
|
|
187
|
-
const compactedTerms = getTopLevelTerms(await jsonld_default.expand(compactedWithContext, { documentLoader }));
|
|
182
|
+
const compactedTerms = getTopLevelTerms(await require_jsonld.jsonld_default.expand(compactedWithContext, { documentLoader }));
|
|
188
183
|
const dummyPrefix = "urn:fedify:dummy:";
|
|
189
184
|
const dummy = { "@context": context };
|
|
190
185
|
for (let i = 0; i < unmappedKeys.length; i++) defineJsonLdProperty(dummy, unmappedKeys[i], `${dummyPrefix}${i}`);
|
|
191
|
-
const expanded = await jsonld_default.expand(dummy, { documentLoader });
|
|
186
|
+
const expanded = await require_jsonld.jsonld_default.expand(dummy, { documentLoader });
|
|
192
187
|
const representedKeys = /* @__PURE__ */ new Set();
|
|
193
188
|
const nodes = Array.isArray(expanded) ? expanded : [expanded];
|
|
194
189
|
for (const node of nodes) {
|
|
@@ -267,8 +262,8 @@ async function compactWithEmptyContext(compacted, context, documentLoader) {
|
|
|
267
262
|
"@context": context,
|
|
268
263
|
...compacted
|
|
269
264
|
} : compacted;
|
|
270
|
-
const expanded = await jsonld_default.expand(compactedWithContext, { documentLoader });
|
|
271
|
-
return await jsonld_default.compact(expanded, {}, { documentLoader });
|
|
265
|
+
const expanded = await require_jsonld.jsonld_default.expand(compactedWithContext, { documentLoader });
|
|
266
|
+
return await require_jsonld.jsonld_default.compact(expanded, {}, { documentLoader });
|
|
272
267
|
}
|
|
273
268
|
function combineContexts(inheritedContext, ownContext) {
|
|
274
269
|
if (ownContext === noJsonLdContext || ownContext === inheritedContext) return inheritedContext;
|
|
@@ -322,7 +317,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
322
317
|
"https://www.w3.org/ns/activitystreams#attributedTo": [{ "@id": "ap://did:key:z6Mkabc/actor" }],
|
|
323
318
|
"https://www.w3.org/ns/activitystreams#content": [{ "@value": "No-context object shape should stay cached." }]
|
|
324
319
|
};
|
|
325
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id", "https://www.w3.org/ns/activitystreams#attributedTo"])), original), {
|
|
320
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id", "https://www.w3.org/ns/activitystreams#attributedTo"])), original), {
|
|
326
321
|
"@id": "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
327
322
|
"@type": ["https://www.w3.org/ns/activitystreams#Note"],
|
|
328
323
|
"https://www.w3.org/ns/activitystreams#attributedTo": [{ "@id": "ap+ef61://did:key:z6Mkabc/actor" }],
|
|
@@ -343,7 +338,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
343
338
|
name: "Nested object"
|
|
344
339
|
}]
|
|
345
340
|
};
|
|
346
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
341
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
347
342
|
"@id": "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
348
343
|
"@type": ["https://www.w3.org/ns/activitystreams#Note"],
|
|
349
344
|
"https://www.w3.org/ns/activitystreams#attachment": [{
|
|
@@ -390,7 +385,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
390
385
|
extra: "This nested unmapped property should stay cached."
|
|
391
386
|
}
|
|
392
387
|
};
|
|
393
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
388
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
394
389
|
"@context": context,
|
|
395
390
|
type: "as:Note",
|
|
396
391
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
@@ -422,7 +417,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
422
417
|
extra
|
|
423
418
|
}
|
|
424
419
|
};
|
|
425
|
-
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
420
|
+
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
426
421
|
(0, node_assert.strictEqual)(compacted.rootExtra, rootExtra);
|
|
427
422
|
(0, node_assert.strictEqual)(compacted.attachment.extra, extra);
|
|
428
423
|
});
|
|
@@ -443,7 +438,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
443
438
|
configurable: true,
|
|
444
439
|
writable: true
|
|
445
440
|
});
|
|
446
|
-
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
441
|
+
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
447
442
|
(0, node_assert.strictEqual)(globalThis.Object.getOwnPropertyDescriptor(compacted, "__proto__")?.value, protoValue);
|
|
448
443
|
(0, node_assert.strictEqual)(globalThis.Object.getPrototypeOf(compacted), Object.prototype);
|
|
449
444
|
});
|
|
@@ -470,7 +465,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
470
465
|
configurable: true,
|
|
471
466
|
writable: true
|
|
472
467
|
});
|
|
473
|
-
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
468
|
+
const compacted = await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original);
|
|
474
469
|
const protoDescriptor = globalThis.Object.getOwnPropertyDescriptor(compacted, "__proto__");
|
|
475
470
|
(0, node_assert.ok)(protoDescriptor?.value === "Alias represented by the compacted term." || Array.isArray(protoDescriptor?.value) && protoDescriptor.value.includes("Alias represented by the compacted term."));
|
|
476
471
|
(0, node_assert.strictEqual)(protoDescriptor?.enumerable, true);
|
|
@@ -500,7 +495,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
500
495
|
title: "Nested title."
|
|
501
496
|
}
|
|
502
497
|
};
|
|
503
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
498
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
504
499
|
"@context": context,
|
|
505
500
|
type: "as:Note",
|
|
506
501
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
@@ -532,7 +527,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
532
527
|
title: "Nested title."
|
|
533
528
|
}
|
|
534
529
|
};
|
|
535
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
530
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
536
531
|
"@context": context,
|
|
537
532
|
type: "as:Note",
|
|
538
533
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
@@ -560,7 +555,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
560
555
|
"https://example.com/ns#title": "Absolute title."
|
|
561
556
|
}
|
|
562
557
|
};
|
|
563
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
558
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
564
559
|
"@context": context,
|
|
565
560
|
type: "as:Note",
|
|
566
561
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
@@ -599,7 +594,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
599
594
|
actorRef: "ap://did:key:z6Mkabc/actor"
|
|
600
595
|
}
|
|
601
596
|
};
|
|
602
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id", "https://www.w3.org/ns/activitystreams#actor"])), original), {
|
|
597
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id", "https://www.w3.org/ns/activitystreams#actor"])), original), {
|
|
603
598
|
"@context": context,
|
|
604
599
|
type: "as:Note",
|
|
605
600
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
@@ -633,7 +628,7 @@ function combineContexts(inheritedContext, ownContext) {
|
|
|
633
628
|
key9: "Extension 9",
|
|
634
629
|
key10: "Alias represented by the compacted term."
|
|
635
630
|
};
|
|
636
|
-
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
631
|
+
(0, node_assert.deepStrictEqual)(await compactJsonLdCache(normalizeJsonLdIris(await require_jsonld.jsonld_default.expand(original), /* @__PURE__ */ new Set(["@id"])), original), {
|
|
637
632
|
"@context": context,
|
|
638
633
|
id: "ap+ef61://did:key:z6Mkabc/objects/1",
|
|
639
634
|
key0: "Extension 0",
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { a as formatIri, c as
|
|
1
|
+
import { a as formatIri, c as haveSameFe34Origin, l as haveSameIriOrigin, m as parseIri } from "./url-DgJM9WJn.mjs";
|
|
2
|
+
import { t as jsonld_default } from "./jsonld-DweIJ07b.mjs";
|
|
2
3
|
import { test } from "node:test";
|
|
3
4
|
import { deepStrictEqual, ok, strictEqual } from "node:assert";
|
|
4
|
-
import jsonld from "jsonld/dist/jsonld.esm.js";
|
|
5
|
-
//#region src/jsonld.ts
|
|
6
|
-
var jsonld_default = jsonld;
|
|
7
|
-
//#endregion
|
|
8
5
|
//#region src/internal/jsonld-cache.ts
|
|
9
6
|
const noJsonLdContext = Symbol("noJsonLdContext");
|
|
10
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
//#region deno.json
|
|
3
3
|
var name = "@fedify/vocab-runtime";
|
|
4
|
-
var version = "2.4.0-dev.
|
|
4
|
+
var version = "2.4.0-dev.2047+140b94db";
|
|
5
5
|
//#endregion
|
|
6
6
|
//#region src/request.ts
|
|
7
7
|
/**
|
|
@@ -31,6 +31,12 @@ var FetchError = class extends Error {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
|
+
* The `Accept` header value for fetching ActivityPub objects. ActivityPub
|
|
35
|
+
* and FEP-ef61 gateways require the ActivityStreams profile on the JSON-LD
|
|
36
|
+
* media type.
|
|
37
|
+
*/
|
|
38
|
+
const ACTIVITYPUB_ACCEPT = "application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
|
|
39
|
+
/**
|
|
34
40
|
* Creates a request for the given URL.
|
|
35
41
|
* @param url The URL to create the request for.
|
|
36
42
|
* @param options The options for the request.
|
|
@@ -40,7 +46,7 @@ var FetchError = class extends Error {
|
|
|
40
46
|
function createActivityPubRequest(url, options = {}) {
|
|
41
47
|
return new Request(url, {
|
|
42
48
|
headers: {
|
|
43
|
-
Accept:
|
|
49
|
+
Accept: ACTIVITYPUB_ACCEPT,
|
|
44
50
|
"User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
|
|
45
51
|
},
|
|
46
52
|
redirect: "manual"
|
|
@@ -3,7 +3,7 @@ let node_process = require("node:process");
|
|
|
3
3
|
node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
4
4
|
//#region deno.json
|
|
5
5
|
var name = "@fedify/vocab-runtime";
|
|
6
|
-
var version = "2.4.0-dev.
|
|
6
|
+
var version = "2.4.0-dev.2047+140b94db";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/request.ts
|
|
9
9
|
/**
|
|
@@ -33,6 +33,12 @@ var FetchError = class extends Error {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
+
* The `Accept` header value for fetching ActivityPub objects. ActivityPub
|
|
37
|
+
* and FEP-ef61 gateways require the ActivityStreams profile on the JSON-LD
|
|
38
|
+
* media type.
|
|
39
|
+
*/
|
|
40
|
+
const ACTIVITYPUB_ACCEPT = "application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
|
|
41
|
+
/**
|
|
36
42
|
* Creates a request for the given URL.
|
|
37
43
|
* @param url The URL to create the request for.
|
|
38
44
|
* @param options The options for the request.
|
|
@@ -42,7 +48,7 @@ var FetchError = class extends Error {
|
|
|
42
48
|
function createActivityPubRequest(url, options = {}) {
|
|
43
49
|
return new Request(url, {
|
|
44
50
|
headers: {
|
|
45
|
-
Accept:
|
|
51
|
+
Accept: ACTIVITYPUB_ACCEPT,
|
|
46
52
|
"User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
|
|
47
53
|
},
|
|
48
54
|
redirect: "manual"
|