@fedify/vocab-runtime 2.5.0-dev.2448 → 2.5.0-dev.2494
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 +5 -2
- package/dist/{docloader-BBnBpbsG.d.cts → docloader-DD6binpN.d.cts} +4 -8
- package/dist/{docloader-BBnBpbsG.d.ts → docloader-DD6binpN.d.ts} +4 -8
- package/dist/internal/jsonld-cache.cjs +1 -1
- package/dist/internal/jsonld-cache.d.cts +1 -1
- package/dist/internal/jsonld-cache.d.ts +1 -1
- package/dist/internal/jsonld-cache.js +1 -1
- package/dist/internal/portable-dereference.cjs +1 -1
- package/dist/internal/portable-dereference.d.cts +2 -2
- package/dist/internal/portable-dereference.d.ts +2 -2
- package/dist/internal/portable-dereference.js +1 -1
- package/dist/internal.cjs +6 -0
- package/dist/internal.d.cts +108 -0
- package/dist/internal.d.ts +108 -0
- package/dist/internal.js +3 -0
- package/dist/mod.cjs +104 -38
- package/dist/mod.d.cts +3 -336
- package/dist/mod.d.ts +4 -336
- package/dist/mod.js +104 -38
- package/dist/{portable-BDydjp5H.d.ts → portable-1VSnSJFj.d.ts} +1 -1
- package/dist/{portable-Dfvcg_Wy.d.cts → portable-Cr7NwZwb.d.cts} +1 -1
- package/dist/public-fetch-Dvfvawei.cjs +527 -0
- package/dist/public-fetch-ziZ39L5I.js +510 -0
- package/dist/tests/{body-DP2u2wUX.cjs → body-0Or8U7lA.cjs} +1 -1
- package/dist/tests/{body-oV99TVdA.mjs → body-DfH6VTh9.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 +4 -4
- package/dist/tests/decimal.test.mjs +4 -4
- package/dist/tests/{docloader-D3mA7aPJ.mjs → docloader-BZvFOza_.mjs} +106 -40
- package/dist/tests/{docloader-CwxZguqN.cjs → docloader-W_RHEh5W.cjs} +111 -39
- package/dist/tests/docloader.test.cjs +531 -1293
- package/dist/tests/docloader.test.mjs +472 -1252
- package/dist/tests/esm-Ds-eHTfY.mjs +1229 -0
- package/dist/tests/esm-Q2tdh5f3.cjs +1215 -0
- package/dist/tests/internal/portable-dereference.test.cjs +3 -3
- package/dist/tests/internal/portable-dereference.test.mjs +3 -3
- package/dist/tests/{jsonld-cache-BEXiiM-V.cjs → jsonld-cache-DKIWKxEX.cjs} +1 -1
- package/dist/tests/{jsonld-cache-DFnWsLuZ.mjs → jsonld-cache-KH40z9_7.mjs} +1 -1
- package/dist/tests/jsonld-cache.test.cjs +2 -2
- package/dist/tests/jsonld-cache.test.mjs +2 -2
- package/dist/tests/node-CbBR-th-.mjs +84 -0
- package/dist/tests/node-Ch29PDXR.cjs +89 -0
- package/dist/tests/pin-grant-CPrpk1l4.cjs +70 -0
- package/dist/tests/pin-grant-H5XhM1Xs.mjs +53 -0
- package/dist/tests/pin-grant.test.cjs +87 -0
- package/dist/tests/pin-grant.test.d.cts +1 -0
- package/dist/tests/pin-grant.test.d.mts +1 -0
- package/dist/tests/pin-grant.test.mjs +88 -0
- package/dist/tests/pinners/bun.test.cjs +166 -0
- package/dist/tests/pinners/bun.test.d.cts +1 -0
- package/dist/tests/pinners/bun.test.d.mts +1 -0
- package/dist/tests/pinners/bun.test.mjs +167 -0
- package/dist/tests/pinners/node.test.cjs +269 -0
- package/dist/tests/pinners/node.test.d.cts +1 -0
- package/dist/tests/pinners/node.test.d.mts +1 -0
- package/dist/tests/pinners/node.test.mjs +268 -0
- package/dist/tests/pinners/pinners.test.cjs +196 -0
- package/dist/tests/pinners/pinners.test.d.cts +1 -0
- package/dist/tests/pinners/pinners.test.d.mts +1 -0
- package/dist/tests/pinners/pinners.test.mjs +197 -0
- package/dist/tests/pinners/testdata/node-child.cjs +135 -0
- package/dist/tests/pinners/testdata/node-child.d.cts +1 -0
- package/dist/tests/pinners/testdata/node-child.d.mts +1 -0
- package/dist/tests/pinners/testdata/node-child.mjs +134 -0
- package/dist/tests/pinners-DLH_npLf.cjs +220 -0
- package/dist/tests/pinners-tGcl49uF.mjs +203 -0
- package/dist/tests/{portable-dereference-DaTBBvCj.cjs → portable-dereference-BUoDzMxk.cjs} +2 -2
- package/dist/tests/{portable-dereference-sGRs_qdT.mjs → portable-dereference-Du2k3ngE.mjs} +2 -2
- package/dist/tests/{portable-media-B-oCeotd.mjs → portable-media-CqCq3wqj.mjs} +3 -3
- package/dist/tests/{portable-media-D7ClSjFO.cjs → portable-media-Ls_EOkMN.cjs} +3 -3
- package/dist/tests/portable-media.test.cjs +1 -1
- package/dist/tests/portable-media.test.mjs +1 -1
- package/dist/tests/portable-workers.test.cjs +2 -2
- package/dist/tests/portable-workers.test.mjs +2 -2
- package/dist/tests/public-fetch-BGj5pzUD.cjs +186 -0
- package/dist/tests/public-fetch-Cxo3Yzdf.mjs +170 -0
- package/dist/tests/public-fetch.test.cjs +1073 -0
- package/dist/tests/public-fetch.test.d.cts +1 -0
- package/dist/tests/public-fetch.test.d.mts +1 -0
- package/dist/tests/public-fetch.test.mjs +1074 -0
- package/dist/tests/{request-BlLYI4x3.mjs → request-Bo8cJJhV.mjs} +2 -2
- package/dist/tests/{request-B77_oZnk.cjs → request-Cb6h3X72.cjs} +2 -2
- package/dist/tests/request.test.cjs +2 -2
- package/dist/tests/request.test.mjs +2 -2
- package/dist/tests/support-Bj44xlQu.mjs +272 -0
- package/dist/tests/support-BrdlbLJk.cjs +363 -0
- package/dist/tests/{url-BNakuZ8k.cjs → url-Bdj-rTcC.cjs} +88 -12
- package/dist/tests/{url-DMxmp7ZG.mjs → url-COj5Q8mb.mjs} +65 -13
- package/dist/tests/url.test.cjs +4 -1
- package/dist/tests/url.test.mjs +4 -1
- package/dist/url-4EE56sNP.d.cts +352 -0
- package/dist/url-4EE56sNP.d.ts +352 -0
- package/dist/{url-DrGTR8yv.cjs → url-DIKZnaJv.cjs} +88 -12
- package/dist/{url-Dzyp-NsC.js → url-mWveR5GA.js} +65 -13
- package/package.json +14 -3
- package/src/docloader.test.ts +696 -48
- package/src/docloader.ts +186 -75
- package/src/internal.ts +13 -0
- package/src/pin-grant.test.ts +118 -0
- package/src/pin-grant.ts +99 -0
- package/src/pinners/bun.test.ts +278 -0
- package/src/pinners/bun.ts +223 -0
- package/src/pinners/mod.ts +59 -0
- package/src/pinners/node.test.ts +415 -0
- package/src/pinners/node.ts +144 -0
- package/src/pinners/pinners.test.ts +316 -0
- package/src/pinners/testdata/node-child.ts +147 -0
- package/src/pinners/testdata/proxy-child.ts +82 -0
- package/src/pinners/testdata/support.ts +343 -0
- package/src/pinners/testdata/tls-cert.pem +12 -0
- package/src/pinners/testdata/tls-child.ts +88 -0
- package/src/pinners/testdata/tls-key.pem +5 -0
- package/src/pinners/types.ts +48 -0
- package/src/public-fetch.test.ts +1286 -0
- package/src/public-fetch.ts +338 -0
- package/src/testdata/public-fetch-deno-worker.ts +74 -0
- package/src/url.test.ts +11 -0
- package/src/url.ts +113 -22
- package/tsdown.config.ts +7 -2
package/deno.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab-runtime",
|
|
3
|
-
"version": "2.5.0-dev.
|
|
3
|
+
"version": "2.5.0-dev.2494+f2e9b5d3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./src/mod.ts",
|
|
7
7
|
"./internal/jsonld-cache": "./src/internal/jsonld-cache.ts",
|
|
8
8
|
"./internal/portable-dereference": "./src/internal/portable-dereference.ts",
|
|
9
9
|
"./internal/signed-representation": "./src/internal/signed-representation.ts",
|
|
10
|
+
"./internal": "./src/internal.ts",
|
|
10
11
|
"./jsonld": "./src/jsonld.ts",
|
|
11
12
|
"./temporal": "./src/temporal.ts"
|
|
12
13
|
},
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
"byte-encodings": "npm:byte-encodings@^1.0.11",
|
|
23
24
|
"fetch-mock": "npm:fetch-mock@^12.5.4",
|
|
24
25
|
"jsonld": "npm:jsonld@^9.0.0",
|
|
25
|
-
"pkijs": "npm:pkijs@^3.2.5"
|
|
26
|
+
"pkijs": "npm:pkijs@^3.2.5",
|
|
27
|
+
"undici": "npm:undici@^7.30.1"
|
|
26
28
|
},
|
|
27
29
|
"exclude": [
|
|
28
30
|
"dist",
|
|
@@ -31,6 +33,7 @@
|
|
|
31
33
|
"publish": {
|
|
32
34
|
"exclude": [
|
|
33
35
|
"**/*.test.ts",
|
|
36
|
+
"src/**/testdata/",
|
|
34
37
|
"tsdown.config.ts"
|
|
35
38
|
]
|
|
36
39
|
},
|
|
@@ -221,7 +221,9 @@ type AuthenticatedDocumentLoaderFactory = (identity: {
|
|
|
221
221
|
* Gets a {@link RemoteDocument} from the given response.
|
|
222
222
|
* @param url The URL of the document to load.
|
|
223
223
|
* @param response The response to get the document from.
|
|
224
|
-
* @param fetch The function to fetch the document.
|
|
224
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
225
|
+
* of an alternate document, if any, after the response body has
|
|
226
|
+
* been either read or its cancellation has been started.
|
|
225
227
|
* @param options The options for loading the document.
|
|
226
228
|
* @returns The loaded remote document.
|
|
227
229
|
* @throws {FetchError} If the response is not OK.
|
|
@@ -292,12 +294,6 @@ interface GetDocumentLoaderOptions extends DocumentLoaderFactoryOptions {
|
|
|
292
294
|
* @returns The document loader.
|
|
293
295
|
* @since 1.3.0
|
|
294
296
|
*/
|
|
295
|
-
declare function getDocumentLoader(
|
|
296
|
-
allowPrivateAddress,
|
|
297
|
-
maxRedirection,
|
|
298
|
-
skipPreloadedContexts,
|
|
299
|
-
timeout,
|
|
300
|
-
userAgent
|
|
301
|
-
}?: GetDocumentLoaderOptions): DocumentLoader;
|
|
297
|
+
declare function getDocumentLoader(options?: GetDocumentLoaderOptions): DocumentLoader;
|
|
302
298
|
//#endregion
|
|
303
299
|
export { isTransientFetchError as _, DocumentLoaderOptions as a, getDocumentLoader as c, withDocumentLoaderTimeout as d, CreateRequestOptions as f, getUserAgent as g, createActivityPubRequest as h, DocumentLoaderFactoryOptions as i, getRemoteDocument as l, GetUserAgentOptions as m, DocumentLoader as n, GetDocumentLoaderOptions as o, FetchError as p, DocumentLoaderFactory as r, RemoteDocument as s, AuthenticatedDocumentLoaderFactory as t, resolveDocumentLoaderTimeout as u, logRequest as v };
|
|
@@ -221,7 +221,9 @@ type AuthenticatedDocumentLoaderFactory = (identity: {
|
|
|
221
221
|
* Gets a {@link RemoteDocument} from the given response.
|
|
222
222
|
* @param url The URL of the document to load.
|
|
223
223
|
* @param response The response to get the document from.
|
|
224
|
-
* @param fetch The function to fetch the document.
|
|
224
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
225
|
+
* of an alternate document, if any, after the response body has
|
|
226
|
+
* been either read or its cancellation has been started.
|
|
225
227
|
* @param options The options for loading the document.
|
|
226
228
|
* @returns The loaded remote document.
|
|
227
229
|
* @throws {FetchError} If the response is not OK.
|
|
@@ -292,12 +294,6 @@ interface GetDocumentLoaderOptions extends DocumentLoaderFactoryOptions {
|
|
|
292
294
|
* @returns The document loader.
|
|
293
295
|
* @since 1.3.0
|
|
294
296
|
*/
|
|
295
|
-
declare function getDocumentLoader(
|
|
296
|
-
allowPrivateAddress,
|
|
297
|
-
maxRedirection,
|
|
298
|
-
skipPreloadedContexts,
|
|
299
|
-
timeout,
|
|
300
|
-
userAgent
|
|
301
|
-
}?: GetDocumentLoaderOptions): DocumentLoader;
|
|
297
|
+
declare function getDocumentLoader(options?: GetDocumentLoaderOptions): DocumentLoader;
|
|
302
298
|
//#endregion
|
|
303
299
|
export { isTransientFetchError as _, DocumentLoaderOptions as a, getDocumentLoader as c, withDocumentLoaderTimeout as d, CreateRequestOptions as f, getUserAgent as g, createActivityPubRequest as h, DocumentLoaderFactoryOptions as i, getRemoteDocument as l, GetUserAgentOptions as m, DocumentLoader as n, GetDocumentLoaderOptions as o, FetchError as p, DocumentLoaderFactory as r, RemoteDocument as s, AuthenticatedDocumentLoaderFactory as t, resolveDocumentLoaderTimeout as u, logRequest as v };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_url = require("../url-
|
|
3
|
+
const require_url = require("../url-DIKZnaJv.cjs");
|
|
4
4
|
const require_jsonld = require("../jsonld.cjs");
|
|
5
5
|
//#region src/internal/jsonld-cache.ts
|
|
6
6
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { b as parseIri, c as fromCompatibleEf61Id, d as haveSameFe34Origin, f as haveSameIriOrigin, l as getFe34Origin, s as formatIri } from "../url-mWveR5GA.js";
|
|
3
3
|
import jsonld_default from "../jsonld.js";
|
|
4
4
|
//#region src/internal/jsonld-cache.ts
|
|
5
5
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_contexts = require("../contexts-B09jb9Pi.cjs");
|
|
4
|
-
const require_url = require("../url-
|
|
4
|
+
const require_url = require("../url-DIKZnaJv.cjs");
|
|
5
5
|
const require_jsonld = require("../jsonld.cjs");
|
|
6
6
|
const require_internal_jsonld_cache = require("./jsonld-cache.cjs");
|
|
7
7
|
let _logtape_logtape = require("@logtape/logtape");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { n as DocumentLoader, s as RemoteDocument } from "../docloader-
|
|
3
|
-
import { r as PortableObjectVerifier } from "../portable-
|
|
2
|
+
import { n as DocumentLoader, s as RemoteDocument } from "../docloader-DD6binpN.cjs";
|
|
3
|
+
import { r as PortableObjectVerifier } from "../portable-Cr7NwZwb.cjs";
|
|
4
4
|
import { Span, TracerProvider } from "@opentelemetry/api";
|
|
5
5
|
|
|
6
6
|
//#region src/internal/portable-dereference.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { n as DocumentLoader, s as RemoteDocument } from "../docloader-
|
|
3
|
-
import { r as PortableObjectVerifier } from "../portable-
|
|
2
|
+
import { n as DocumentLoader, s as RemoteDocument } from "../docloader-DD6binpN.js";
|
|
3
|
+
import { r as PortableObjectVerifier } from "../portable-1VSnSJFj.js";
|
|
4
4
|
import { Span, TracerProvider } from "@opentelemetry/api";
|
|
5
5
|
|
|
6
6
|
//#region src/internal/portable-dereference.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { t as preloadedContexts } from "../contexts-DWrj4AGR.js";
|
|
3
|
-
import {
|
|
3
|
+
import { C as toCompatibleEf61Id, a as canonicalizePortableUri, b as parseIri, c as fromCompatibleEf61Id, d as haveSameFe34Origin, s as formatIri, t as GATEWAY_HINT_PARAMETER, v as parseGatewayOrigin } from "../url-mWveR5GA.js";
|
|
4
4
|
import jsonld_default from "../jsonld.js";
|
|
5
5
|
import { createScopedContextLoader, registerDocumentLoaderWrapper, unwrapReleasedDocumentLoader } from "./jsonld-cache.js";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_public_fetch = require("./public-fetch-Dvfvawei.cjs");
|
|
4
|
+
exports.openDirectFetch = require_public_fetch.openDirectFetch;
|
|
5
|
+
exports.openPublicFetch = require_public_fetch.openPublicFetch;
|
|
6
|
+
exports.withPublicFetch = require_public_fetch.withPublicFetch;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
import { t as ResolvedAddress } from "./url-4EE56sNP.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/public-fetch.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for {@link openPublicFetch} and {@link withPublicFetch}.
|
|
7
|
+
*/
|
|
8
|
+
interface PublicFetchOptions {
|
|
9
|
+
/**
|
|
10
|
+
* An `AbortSignal` for cancelling the DNS lookup.
|
|
11
|
+
*/
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
/**
|
|
14
|
+
* A function that resolves all addresses of a hostname, used instead of
|
|
15
|
+
* `node:dns.lookup()`. The addresses it returns are validated in the same
|
|
16
|
+
* way as the default lookup's.
|
|
17
|
+
*/
|
|
18
|
+
readonly lookup?: (hostname: string) => Promise<readonly ResolvedAddress[]>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A session for fetching resources from a single origin. Its `fetch()`
|
|
22
|
+
* connects only to the addresses validated when the session was opened, on
|
|
23
|
+
* runtimes that support it.
|
|
24
|
+
*/
|
|
25
|
+
interface PublicFetchSession {
|
|
26
|
+
/**
|
|
27
|
+
* A copy of the URL the session was opened for.
|
|
28
|
+
*/
|
|
29
|
+
readonly url: URL;
|
|
30
|
+
/**
|
|
31
|
+
* Fetches a resource from the session's origin. Redirects are never
|
|
32
|
+
* followed; the redirect mode is always `"manual"`.
|
|
33
|
+
* @throws {TypeError} If the input's origin differs from the session's, or
|
|
34
|
+
* if the session is closed.
|
|
35
|
+
*/
|
|
36
|
+
fetch(input: Request | URL | string, init?: RequestInit): Promise<Response>;
|
|
37
|
+
/**
|
|
38
|
+
* Closes the session. The cancellation of response bodies that have been
|
|
39
|
+
* neither consumed nor cancelled is started (without waiting for it), and
|
|
40
|
+
* the session can no longer fetch. Calling this more than once has no
|
|
41
|
+
* effect.
|
|
42
|
+
*/
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The functions created by {@link createPublicFetch}.
|
|
47
|
+
*/
|
|
48
|
+
interface PublicFetch {
|
|
49
|
+
/**
|
|
50
|
+
* Validates the URL, resolves its hostname, checks that every resolved
|
|
51
|
+
* address is public, and opens a session that connects only to those
|
|
52
|
+
* addresses.
|
|
53
|
+
* @param url The URL to open a session for.
|
|
54
|
+
* @param options The options.
|
|
55
|
+
* @returns The session. It must be closed.
|
|
56
|
+
* @throws {UrlError} If the URL is not allowed, or its hostname cannot be
|
|
57
|
+
* resolved (with `reason: "dns"`).
|
|
58
|
+
*/
|
|
59
|
+
openPublicFetch(url: URL | string, options?: PublicFetchOptions): Promise<PublicFetchSession>;
|
|
60
|
+
/**
|
|
61
|
+
* Opens a session with {@link PublicFetch.openPublicFetch}, runs the given
|
|
62
|
+
* function with its `fetch()`, and closes the session afterwards.
|
|
63
|
+
* @param url The URL to open a session for.
|
|
64
|
+
* @param fn The function to run. It must not return a `Response`, since
|
|
65
|
+
* the response bodies are cancelled when the session is closed.
|
|
66
|
+
* @param options The options.
|
|
67
|
+
* @returns The value returned by `fn`.
|
|
68
|
+
* @throws {UrlError} If the URL is not allowed.
|
|
69
|
+
* @throws {TypeError} If `fn` returns a `Response`.
|
|
70
|
+
*/
|
|
71
|
+
withPublicFetch<T>(url: URL | string, fn: (fetch: PublicFetchSession["fetch"]) => Promise<T>, options?: PublicFetchOptions): Promise<T>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validates the URL, resolves its hostname, checks that every resolved
|
|
75
|
+
* address is public, and opens a session that connects only to those
|
|
76
|
+
* addresses. Connections are pinned on Node.js and Bun. On other runtimes,
|
|
77
|
+
* the session uses the global `fetch()` after the check.
|
|
78
|
+
* @param url The URL to open a session for.
|
|
79
|
+
* @param options The options.
|
|
80
|
+
* @returns The session. It must be closed.
|
|
81
|
+
* @throws {UrlError} If the URL is not allowed, or its hostname cannot be
|
|
82
|
+
* resolved (with `reason: "dns"`).
|
|
83
|
+
*/
|
|
84
|
+
declare const openPublicFetch: PublicFetch["openPublicFetch"];
|
|
85
|
+
/**
|
|
86
|
+
* Opens a session with {@link openPublicFetch}, runs the given function with
|
|
87
|
+
* its `fetch()`, and closes the session afterwards.
|
|
88
|
+
* @param url The URL to open a session for.
|
|
89
|
+
* @param fn The function to run. It must not return a `Response`, since
|
|
90
|
+
* the response bodies are cancelled when the session is closed.
|
|
91
|
+
* @param options The options.
|
|
92
|
+
* @returns The value returned by `fn`.
|
|
93
|
+
* @throws {UrlError} If the URL is not allowed.
|
|
94
|
+
* @throws {TypeError} If `fn` returns a `Response`.
|
|
95
|
+
*/
|
|
96
|
+
declare const withPublicFetch: PublicFetch["withPublicFetch"];
|
|
97
|
+
/**
|
|
98
|
+
* Opens a session that neither validates nor pins addresses, for callers that
|
|
99
|
+
* allow private addresses. It has the same rules as {@link openPublicFetch}
|
|
100
|
+
* sessions otherwise: requests are limited to the URL's origin, redirects are
|
|
101
|
+
* never followed, and unconsumed response bodies are cancelled on close.
|
|
102
|
+
* It grants nothing beyond calling the global `fetch()` directly.
|
|
103
|
+
* @param url The URL to open a session for.
|
|
104
|
+
* @returns The session. It must be closed.
|
|
105
|
+
*/
|
|
106
|
+
declare function openDirectFetch(url: URL | string): Promise<PublicFetchSession>;
|
|
107
|
+
//#endregion
|
|
108
|
+
export { type PublicFetchOptions, type PublicFetchSession, openDirectFetch, openPublicFetch, withPublicFetch };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
import { t as ResolvedAddress } from "./url-4EE56sNP.js";
|
|
3
|
+
|
|
4
|
+
//#region src/public-fetch.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for {@link openPublicFetch} and {@link withPublicFetch}.
|
|
7
|
+
*/
|
|
8
|
+
interface PublicFetchOptions {
|
|
9
|
+
/**
|
|
10
|
+
* An `AbortSignal` for cancelling the DNS lookup.
|
|
11
|
+
*/
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
/**
|
|
14
|
+
* A function that resolves all addresses of a hostname, used instead of
|
|
15
|
+
* `node:dns.lookup()`. The addresses it returns are validated in the same
|
|
16
|
+
* way as the default lookup's.
|
|
17
|
+
*/
|
|
18
|
+
readonly lookup?: (hostname: string) => Promise<readonly ResolvedAddress[]>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A session for fetching resources from a single origin. Its `fetch()`
|
|
22
|
+
* connects only to the addresses validated when the session was opened, on
|
|
23
|
+
* runtimes that support it.
|
|
24
|
+
*/
|
|
25
|
+
interface PublicFetchSession {
|
|
26
|
+
/**
|
|
27
|
+
* A copy of the URL the session was opened for.
|
|
28
|
+
*/
|
|
29
|
+
readonly url: URL;
|
|
30
|
+
/**
|
|
31
|
+
* Fetches a resource from the session's origin. Redirects are never
|
|
32
|
+
* followed; the redirect mode is always `"manual"`.
|
|
33
|
+
* @throws {TypeError} If the input's origin differs from the session's, or
|
|
34
|
+
* if the session is closed.
|
|
35
|
+
*/
|
|
36
|
+
fetch(input: Request | URL | string, init?: RequestInit): Promise<Response>;
|
|
37
|
+
/**
|
|
38
|
+
* Closes the session. The cancellation of response bodies that have been
|
|
39
|
+
* neither consumed nor cancelled is started (without waiting for it), and
|
|
40
|
+
* the session can no longer fetch. Calling this more than once has no
|
|
41
|
+
* effect.
|
|
42
|
+
*/
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The functions created by {@link createPublicFetch}.
|
|
47
|
+
*/
|
|
48
|
+
interface PublicFetch {
|
|
49
|
+
/**
|
|
50
|
+
* Validates the URL, resolves its hostname, checks that every resolved
|
|
51
|
+
* address is public, and opens a session that connects only to those
|
|
52
|
+
* addresses.
|
|
53
|
+
* @param url The URL to open a session for.
|
|
54
|
+
* @param options The options.
|
|
55
|
+
* @returns The session. It must be closed.
|
|
56
|
+
* @throws {UrlError} If the URL is not allowed, or its hostname cannot be
|
|
57
|
+
* resolved (with `reason: "dns"`).
|
|
58
|
+
*/
|
|
59
|
+
openPublicFetch(url: URL | string, options?: PublicFetchOptions): Promise<PublicFetchSession>;
|
|
60
|
+
/**
|
|
61
|
+
* Opens a session with {@link PublicFetch.openPublicFetch}, runs the given
|
|
62
|
+
* function with its `fetch()`, and closes the session afterwards.
|
|
63
|
+
* @param url The URL to open a session for.
|
|
64
|
+
* @param fn The function to run. It must not return a `Response`, since
|
|
65
|
+
* the response bodies are cancelled when the session is closed.
|
|
66
|
+
* @param options The options.
|
|
67
|
+
* @returns The value returned by `fn`.
|
|
68
|
+
* @throws {UrlError} If the URL is not allowed.
|
|
69
|
+
* @throws {TypeError} If `fn` returns a `Response`.
|
|
70
|
+
*/
|
|
71
|
+
withPublicFetch<T>(url: URL | string, fn: (fetch: PublicFetchSession["fetch"]) => Promise<T>, options?: PublicFetchOptions): Promise<T>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validates the URL, resolves its hostname, checks that every resolved
|
|
75
|
+
* address is public, and opens a session that connects only to those
|
|
76
|
+
* addresses. Connections are pinned on Node.js and Bun. On other runtimes,
|
|
77
|
+
* the session uses the global `fetch()` after the check.
|
|
78
|
+
* @param url The URL to open a session for.
|
|
79
|
+
* @param options The options.
|
|
80
|
+
* @returns The session. It must be closed.
|
|
81
|
+
* @throws {UrlError} If the URL is not allowed, or its hostname cannot be
|
|
82
|
+
* resolved (with `reason: "dns"`).
|
|
83
|
+
*/
|
|
84
|
+
declare const openPublicFetch: PublicFetch["openPublicFetch"];
|
|
85
|
+
/**
|
|
86
|
+
* Opens a session with {@link openPublicFetch}, runs the given function with
|
|
87
|
+
* its `fetch()`, and closes the session afterwards.
|
|
88
|
+
* @param url The URL to open a session for.
|
|
89
|
+
* @param fn The function to run. It must not return a `Response`, since
|
|
90
|
+
* the response bodies are cancelled when the session is closed.
|
|
91
|
+
* @param options The options.
|
|
92
|
+
* @returns The value returned by `fn`.
|
|
93
|
+
* @throws {UrlError} If the URL is not allowed.
|
|
94
|
+
* @throws {TypeError} If `fn` returns a `Response`.
|
|
95
|
+
*/
|
|
96
|
+
declare const withPublicFetch: PublicFetch["withPublicFetch"];
|
|
97
|
+
/**
|
|
98
|
+
* Opens a session that neither validates nor pins addresses, for callers that
|
|
99
|
+
* allow private addresses. It has the same rules as {@link openPublicFetch}
|
|
100
|
+
* sessions otherwise: requests are limited to the URL's origin, redirects are
|
|
101
|
+
* never followed, and unconsumed response bodies are cancelled on close.
|
|
102
|
+
* It grants nothing beyond calling the global `fetch()` directly.
|
|
103
|
+
* @param url The URL to open a session for.
|
|
104
|
+
* @returns The session. It must be closed.
|
|
105
|
+
*/
|
|
106
|
+
declare function openDirectFetch(url: URL | string): Promise<PublicFetchSession>;
|
|
107
|
+
//#endregion
|
|
108
|
+
export { type PublicFetchOptions, type PublicFetchSession, openDirectFetch, openPublicFetch, withPublicFetch };
|
package/dist/internal.js
ADDED
package/dist/mod.cjs
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_rolldown_runtime = require("./rolldown-runtime-B7lfambq.cjs");
|
|
4
4
|
const require_contexts = require("./contexts-B09jb9Pi.cjs");
|
|
5
|
-
const require_url = require("./url-
|
|
5
|
+
const require_url = require("./url-DIKZnaJv.cjs");
|
|
6
|
+
const require_public_fetch = require("./public-fetch-Dvfvawei.cjs");
|
|
6
7
|
let _logtape_logtape = require("@logtape/logtape");
|
|
7
8
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
9
|
let node_process = require("node:process");
|
|
@@ -16,7 +17,7 @@ let _multiformats_base_x = require("@multiformats/base-x");
|
|
|
16
17
|
_multiformats_base_x = require_rolldown_runtime.__toESM(_multiformats_base_x, 1);
|
|
17
18
|
//#region deno.json
|
|
18
19
|
var name = "@fedify/vocab-runtime";
|
|
19
|
-
var version = "2.5.0-dev.
|
|
20
|
+
var version = "2.5.0-dev.2494+f2e9b5d3";
|
|
20
21
|
//#endregion
|
|
21
22
|
//#region src/request.ts
|
|
22
23
|
/**
|
|
@@ -525,7 +526,7 @@ async function bufferErrorResponse(response, url, signal) {
|
|
|
525
526
|
try {
|
|
526
527
|
await readBoundedBytes(response, MAX_ERROR_BODY_SIZE, url);
|
|
527
528
|
} catch (error) {
|
|
528
|
-
|
|
529
|
+
clone.body?.cancel().catch(() => {});
|
|
529
530
|
if (signal?.aborted) throw error;
|
|
530
531
|
logger.debug("Failed to read the error response body from {url}: {error}", {
|
|
531
532
|
url,
|
|
@@ -557,14 +558,48 @@ async function bufferErrorResponse(response, url, signal) {
|
|
|
557
558
|
* Gets a {@link RemoteDocument} from the given response.
|
|
558
559
|
* @param url The URL of the document to load.
|
|
559
560
|
* @param response The response to get the document from.
|
|
560
|
-
* @param fetch The function to fetch the document.
|
|
561
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
562
|
+
* of an alternate document, if any, after the response body has
|
|
563
|
+
* been either read or its cancellation has been started.
|
|
561
564
|
* @param options The options for loading the document.
|
|
562
565
|
* @returns The loaded remote document.
|
|
563
566
|
* @throws {FetchError} If the response is not OK.
|
|
564
567
|
* @internal
|
|
565
568
|
*/
|
|
566
569
|
async function getRemoteDocument(url, response, fetch, options) {
|
|
567
|
-
const
|
|
570
|
+
const result = await parseRemoteDocument(url, response, options);
|
|
571
|
+
if ("alternate" in result) return await fetch(result.alternate, options);
|
|
572
|
+
return result.document;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
576
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
577
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
578
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
579
|
+
* @param response The response whose body is cancelled.
|
|
580
|
+
* @param url The URL of the response, for logging.
|
|
581
|
+
*/
|
|
582
|
+
function cancelResponseBody(response, url) {
|
|
583
|
+
response.body?.cancel().catch((error) => {
|
|
584
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
585
|
+
url,
|
|
586
|
+
error
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
592
|
+
* alternate document to load instead. When an alternate document is found,
|
|
593
|
+
* the response body has been either read or its cancellation has been started
|
|
594
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
595
|
+
* the response's session is closed.
|
|
596
|
+
* @param url The URL of the document to load.
|
|
597
|
+
* @param response The response to get the document from.
|
|
598
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
599
|
+
* @throws {FetchError} If the response is not OK.
|
|
600
|
+
*/
|
|
601
|
+
async function parseRemoteDocument(url, response, options) {
|
|
602
|
+
const documentUrl = url;
|
|
568
603
|
const docUrl = new URL(documentUrl);
|
|
569
604
|
if (!response.ok) {
|
|
570
605
|
if (options?.suppressError) logger.warn("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -606,7 +641,8 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
606
641
|
alternateUrl: altUri.href,
|
|
607
642
|
url: documentUrl
|
|
608
643
|
});
|
|
609
|
-
|
|
644
|
+
cancelResponseBody(response, documentUrl);
|
|
645
|
+
return { alternate: altUri.href };
|
|
610
646
|
}
|
|
611
647
|
}
|
|
612
648
|
}
|
|
@@ -642,7 +678,7 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
642
678
|
alternateUrl: attribs.href,
|
|
643
679
|
url: documentUrl
|
|
644
680
|
});
|
|
645
|
-
return
|
|
681
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
646
682
|
}
|
|
647
683
|
}
|
|
648
684
|
try {
|
|
@@ -657,11 +693,11 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
657
693
|
url: documentUrl,
|
|
658
694
|
headers: Object.fromEntries(response.headers.entries())
|
|
659
695
|
});
|
|
660
|
-
return {
|
|
696
|
+
return { document: {
|
|
661
697
|
contextUrl,
|
|
662
698
|
document,
|
|
663
699
|
documentUrl
|
|
664
|
-
};
|
|
700
|
+
} };
|
|
665
701
|
}
|
|
666
702
|
/**
|
|
667
703
|
* Resolves {@link DocumentLoaderFactoryOptions.timeout} into milliseconds.
|
|
@@ -766,10 +802,59 @@ function withDocumentLoaderTimeout(loader, timeout) {
|
|
|
766
802
|
* @returns The document loader.
|
|
767
803
|
* @since 1.3.0
|
|
768
804
|
*/
|
|
769
|
-
function getDocumentLoader(
|
|
805
|
+
function getDocumentLoader(options = {}) {
|
|
806
|
+
return createDocumentLoader(options);
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
810
|
+
* dependencies. This is not exported from any entry point.
|
|
811
|
+
* @param options Options for the document loader.
|
|
812
|
+
* @param deps The dependencies.
|
|
813
|
+
* @returns The document loader.
|
|
814
|
+
*/
|
|
815
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, timeout, userAgent } = {}, deps = {}) {
|
|
770
816
|
const resolvedTimeout = resolveDocumentLoaderTimeout(timeout);
|
|
771
817
|
const tracer = _opentelemetry_api.trace.getTracerProvider().getTracer(name, version);
|
|
772
818
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
819
|
+
async function openHop(url, options) {
|
|
820
|
+
try {
|
|
821
|
+
const session = deps.openHop != null ? await deps.openHop(url) : allowPrivateAddress ? await require_public_fetch.openDirectFetch(url) : await require_public_fetch.openPublicFetch(url, { signal: options?.signal });
|
|
822
|
+
if (options?.signal?.aborted) {
|
|
823
|
+
await session.close();
|
|
824
|
+
options.signal.throwIfAborted();
|
|
825
|
+
}
|
|
826
|
+
return session;
|
|
827
|
+
} catch (error) {
|
|
828
|
+
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
829
|
+
url,
|
|
830
|
+
error
|
|
831
|
+
});
|
|
832
|
+
else logger[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
833
|
+
url,
|
|
834
|
+
error
|
|
835
|
+
});
|
|
836
|
+
throw error;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
async function fetchHop(session, url, span, options) {
|
|
840
|
+
try {
|
|
841
|
+
const request = createActivityPubRequest(url, { userAgent });
|
|
842
|
+
logRequest(logger, request);
|
|
843
|
+
const response = await session.fetch(request, {
|
|
844
|
+
redirect: "manual",
|
|
845
|
+
signal: options?.signal
|
|
846
|
+
});
|
|
847
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
848
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
849
|
+
const location = response.headers.get("Location");
|
|
850
|
+
cancelResponseBody(response, url);
|
|
851
|
+
return { location };
|
|
852
|
+
}
|
|
853
|
+
return await parseRemoteDocument(url, response, options);
|
|
854
|
+
} finally {
|
|
855
|
+
await session.close();
|
|
856
|
+
}
|
|
857
|
+
}
|
|
773
858
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
774
859
|
options?.signal?.throwIfAborted();
|
|
775
860
|
const parsedUrl = new URL(url);
|
|
@@ -784,36 +869,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
784
869
|
documentUrl: currentUrl
|
|
785
870
|
};
|
|
786
871
|
}
|
|
787
|
-
|
|
788
|
-
try {
|
|
789
|
-
await require_url.validatePublicUrl(currentUrl);
|
|
790
|
-
} catch (error) {
|
|
791
|
-
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
792
|
-
url: currentUrl,
|
|
793
|
-
error
|
|
794
|
-
});
|
|
795
|
-
else logger[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
796
|
-
url: currentUrl,
|
|
797
|
-
error
|
|
798
|
-
});
|
|
799
|
-
throw error;
|
|
800
|
-
}
|
|
801
|
-
options?.signal?.throwIfAborted();
|
|
802
|
-
}
|
|
872
|
+
const session = await openHop(currentUrl, options);
|
|
803
873
|
visited.add(currentUrl);
|
|
804
874
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
805
875
|
kind: _opentelemetry_api.SpanKind.CLIENT,
|
|
806
876
|
attributes: { "url.full": currentUrl }
|
|
807
877
|
}, async (span) => {
|
|
808
878
|
try {
|
|
809
|
-
const
|
|
810
|
-
|
|
811
|
-
const response = await fetch(request, {
|
|
812
|
-
redirect: "manual",
|
|
813
|
-
signal: options?.signal
|
|
814
|
-
});
|
|
815
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
816
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
879
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
880
|
+
if ("location" in outcome) {
|
|
817
881
|
if (redirected >= maximumRedirection) {
|
|
818
882
|
logger[options?.suppressError ? "warn" : "error"]("Too many redirections ({redirections}) while fetching document.", {
|
|
819
883
|
redirections: redirected + 1,
|
|
@@ -821,7 +885,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
821
885
|
});
|
|
822
886
|
throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
823
887
|
}
|
|
824
|
-
const redirectUrl = new URL(
|
|
888
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
825
889
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
826
890
|
if (visited.has(redirectUrl)) {
|
|
827
891
|
logger[options?.suppressError ? "warn" : "error"]("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -832,12 +896,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
832
896
|
}
|
|
833
897
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
834
898
|
}
|
|
835
|
-
|
|
899
|
+
let result;
|
|
900
|
+
if ("alternate" in outcome) {
|
|
901
|
+
const alternateUrl = outcome.alternate;
|
|
836
902
|
options?.signal?.throwIfAborted();
|
|
837
903
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
838
904
|
if (visited.has(alternateUrl)) throw new FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
839
|
-
|
|
840
|
-
}
|
|
905
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
906
|
+
} else result = outcome.document;
|
|
841
907
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
842
908
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
843
909
|
return result;
|