@fedify/vocab-runtime 2.0.7 → 2.0.9
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 +1 -1
- package/dist/{chunk-CUT6urMc.cjs → chunk-CKQMccvm.cjs} +7 -9
- package/dist/jsonld.cjs +4 -5
- package/dist/jsonld.d.cts +3 -4
- package/dist/jsonld.d.ts +2 -2
- package/dist/jsonld.js +1 -3
- package/dist/mod.cjs +83 -131
- package/dist/mod.d.cts +1 -5
- package/dist/mod.d.ts +1 -5
- package/dist/mod.js +59 -110
- package/dist/tests/{chunk-DWy1uDak.cjs → chunk-Do9eywBl.cjs} +13 -17
- package/dist/tests/docloader.test.cjs +137 -114
- package/dist/tests/{docloader.test.js → docloader.test.mjs} +132 -115
- package/dist/tests/internal/multicodec.test.cjs +5 -7
- package/dist/tests/internal/{multicodec.test.js → multicodec.test.mjs} +3 -4
- package/dist/tests/key.test.cjs +39 -70
- package/dist/tests/{key.test.js → key.test.mjs} +32 -62
- package/dist/tests/langstr.test.cjs +6 -8
- package/dist/tests/{langstr.test.js → langstr.test.mjs} +2 -4
- package/dist/tests/{link-CdFPEo9O.cjs → link-B6ZWBZhf.cjs} +6 -8
- package/dist/tests/{link-Ck2yj4dH.js → link-B8JGXSS2.mjs} +1 -2
- package/dist/tests/link.test.cjs +5 -7
- package/dist/tests/{link.test.js → link.test.mjs} +3 -4
- package/dist/tests/multibase/multibase.test.cjs +10 -17
- package/dist/tests/multibase/{multibase.test.js → multibase.test.mjs} +10 -18
- package/dist/tests/{multibase-B2D6B0V4.cjs → multibase-CgYqpk4Z.cjs} +43 -49
- package/dist/tests/{multibase-BdHCGO4H.js → multibase-jcKrOpuU.mjs} +5 -12
- package/dist/tests/{multicodec-mHcRzSGY.cjs → multicodec-DeYop8xg.cjs} +16 -18
- package/dist/tests/{multicodec-DvC5xnX2.js → multicodec-aqbZnrNi.mjs} +1 -2
- package/dist/tests/{request-BZixuWv5.js → request-AitXfW_2.mjs} +4 -45
- package/dist/tests/{request-78UEYyIx.cjs → request-C6iSYeYi.cjs} +38 -72
- package/dist/tests/request.test.cjs +23 -24
- package/dist/tests/request.test.mjs +42 -0
- package/dist/tests/{url-C5Vs9nYh.cjs → url-Cr2K-wzd.cjs} +31 -35
- package/dist/tests/{url-fW_DHbih.js → url-Djghaq0m.mjs} +3 -7
- package/dist/tests/url.test.cjs +5 -7
- package/dist/tests/{url.test.js → url.test.mjs} +3 -4
- package/package.json +3 -3
- package/src/docloader.test.ts +67 -0
- package/src/docloader.ts +43 -11
- package/dist/tests/request.test.js +0 -43
- /package/dist/tests/{docloader.test.d.ts → docloader.test.d.mts} +0 -0
- /package/dist/tests/internal/{multicodec.test.d.ts → multicodec.test.d.mts} +0 -0
- /package/dist/tests/{key.test.d.ts → key.test.d.mts} +0 -0
- /package/dist/tests/{langstr.test.d.ts → langstr.test.d.mts} +0 -0
- /package/dist/tests/{link.test.d.ts → link.test.d.mts} +0 -0
- /package/dist/tests/multibase/{multibase.test.d.ts → multibase.test.d.mts} +0 -0
- /package/dist/tests/{request.test.d.ts → request.test.d.mts} +0 -0
- /package/dist/tests/{url.test.d.ts → url.test.d.mts} +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
require("./chunk-Do9eywBl.cjs");
|
|
2
|
+
let node_dns_promises = require("node:dns/promises");
|
|
3
|
+
let node_net = require("node:net");
|
|
5
4
|
//#region src/url.ts
|
|
6
5
|
var UrlError = class extends Error {
|
|
7
6
|
constructor(message) {
|
|
@@ -19,8 +18,7 @@ async function validatePublicUrl(url) {
|
|
|
19
18
|
if (hostname.startsWith("[") && hostname.endsWith("]")) hostname = hostname.substring(1, hostname.length - 2);
|
|
20
19
|
if (hostname === "localhost") throw new UrlError("Localhost is not allowed");
|
|
21
20
|
if ("Deno" in globalThis && !(0, node_net.isIP)(hostname)) {
|
|
22
|
-
|
|
23
|
-
if (netPermission.state !== "granted") return;
|
|
21
|
+
if ((await Deno.permissions.query({ name: "net" })).state !== "granted") return;
|
|
24
22
|
}
|
|
25
23
|
if ("Bun" in globalThis) {
|
|
26
24
|
if (hostname === "example.com" || hostname.endsWith(".example.com")) return;
|
|
@@ -56,38 +54,36 @@ function expandIPv6Address(address) {
|
|
|
56
54
|
if (address.startsWith("::")) address = "0000" + address;
|
|
57
55
|
if (address.endsWith("::")) address = address + "0000";
|
|
58
56
|
address = address.replace("::", ":0000".repeat(8 - (address.match(/:/g) || []).length) + ":");
|
|
59
|
-
|
|
60
|
-
return parts.map((part) => part.padStart(4, "0")).join(":");
|
|
57
|
+
return address.split(":").map((part) => part.padStart(4, "0")).join(":");
|
|
61
58
|
}
|
|
62
|
-
|
|
63
59
|
//#endregion
|
|
64
|
-
Object.defineProperty(exports,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
Object.defineProperty(exports, "UrlError", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function() {
|
|
63
|
+
return UrlError;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "expandIPv6Address", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function() {
|
|
69
|
+
return expandIPv6Address;
|
|
70
|
+
}
|
|
69
71
|
});
|
|
70
|
-
Object.defineProperty(exports,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
Object.defineProperty(exports, "isValidPublicIPv4Address", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function() {
|
|
75
|
+
return isValidPublicIPv4Address;
|
|
76
|
+
}
|
|
75
77
|
});
|
|
76
|
-
Object.defineProperty(exports,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
Object.defineProperty(exports, "isValidPublicIPv6Address", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function() {
|
|
81
|
+
return isValidPublicIPv6Address;
|
|
82
|
+
}
|
|
81
83
|
});
|
|
82
|
-
Object.defineProperty(exports,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
Object.defineProperty(exports, "validatePublicUrl", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function() {
|
|
87
|
+
return validatePublicUrl;
|
|
88
|
+
}
|
|
87
89
|
});
|
|
88
|
-
Object.defineProperty(exports, 'validatePublicUrl', {
|
|
89
|
-
enumerable: true,
|
|
90
|
-
get: function () {
|
|
91
|
-
return validatePublicUrl;
|
|
92
|
-
}
|
|
93
|
-
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { lookup } from "node:dns/promises";
|
|
2
2
|
import { isIP } from "node:net";
|
|
3
|
-
|
|
4
3
|
//#region src/url.ts
|
|
5
4
|
var UrlError = class extends Error {
|
|
6
5
|
constructor(message) {
|
|
@@ -18,8 +17,7 @@ async function validatePublicUrl(url) {
|
|
|
18
17
|
if (hostname.startsWith("[") && hostname.endsWith("]")) hostname = hostname.substring(1, hostname.length - 2);
|
|
19
18
|
if (hostname === "localhost") throw new UrlError("Localhost is not allowed");
|
|
20
19
|
if ("Deno" in globalThis && !isIP(hostname)) {
|
|
21
|
-
|
|
22
|
-
if (netPermission.state !== "granted") return;
|
|
20
|
+
if ((await Deno.permissions.query({ name: "net" })).state !== "granted") return;
|
|
23
21
|
}
|
|
24
22
|
if ("Bun" in globalThis) {
|
|
25
23
|
if (hostname === "example.com" || hostname.endsWith(".example.com")) return;
|
|
@@ -55,9 +53,7 @@ function expandIPv6Address(address) {
|
|
|
55
53
|
if (address.startsWith("::")) address = "0000" + address;
|
|
56
54
|
if (address.endsWith("::")) address = address + "0000";
|
|
57
55
|
address = address.replace("::", ":0000".repeat(8 - (address.match(/:/g) || []).length) + ":");
|
|
58
|
-
|
|
59
|
-
return parts.map((part) => part.padStart(4, "0")).join(":");
|
|
56
|
+
return address.split(":").map((part) => part.padStart(4, "0")).join(":");
|
|
60
57
|
}
|
|
61
|
-
|
|
62
58
|
//#endregion
|
|
63
|
-
export {
|
|
59
|
+
export { validatePublicUrl as a, isValidPublicIPv6Address as i, expandIPv6Address as n, isValidPublicIPv4Address as r, UrlError as t };
|
package/dist/tests/url.test.cjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
const require_url = require(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
require("./chunk-Do9eywBl.cjs");
|
|
2
|
+
const require_url = require("./url-Cr2K-wzd.cjs");
|
|
3
|
+
let node_assert = require("node:assert");
|
|
4
|
+
let node_test = require("node:test");
|
|
6
5
|
//#region src/url.test.ts
|
|
7
6
|
(0, node_test.test)("validatePublicUrl()", async () => {
|
|
8
7
|
await (0, node_assert.rejects)(() => require_url.validatePublicUrl("ftp://localhost"), require_url.UrlError);
|
|
@@ -33,5 +32,4 @@ const node_test = require_chunk.__toESM(require("node:test"));
|
|
|
33
32
|
(0, node_assert.deepStrictEqual)(require_url.expandIPv6Address("2001:db8::"), "2001:0db8:0000:0000:0000:0000:0000:0000");
|
|
34
33
|
(0, node_assert.deepStrictEqual)(require_url.expandIPv6Address("2001:db8::1"), "2001:0db8:0000:0000:0000:0000:0000:0001");
|
|
35
34
|
});
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
35
|
+
//#endregion
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as validatePublicUrl, i as isValidPublicIPv6Address, n as expandIPv6Address, r as isValidPublicIPv4Address, t as UrlError } from "./url-Djghaq0m.mjs";
|
|
2
2
|
import { deepStrictEqual, ok, rejects } from "node:assert";
|
|
3
3
|
import { test } from "node:test";
|
|
4
|
-
|
|
5
4
|
//#region src/url.test.ts
|
|
6
5
|
test("validatePublicUrl()", async () => {
|
|
7
6
|
await rejects(() => validatePublicUrl("ftp://localhost"), UrlError);
|
|
@@ -32,5 +31,5 @@ test("expandIPv6Address()", () => {
|
|
|
32
31
|
deepStrictEqual(expandIPv6Address("2001:db8::"), "2001:0db8:0000:0000:0000:0000:0000:0000");
|
|
33
32
|
deepStrictEqual(expandIPv6Address("2001:db8::1"), "2001:0db8:0000:0000:0000:0000:0000:0001");
|
|
34
33
|
});
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
//#endregion
|
|
35
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab-runtime",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"homepage": "https://fedify.dev/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^24.2.1",
|
|
63
63
|
"fetch-mock": "^12.5.4",
|
|
64
|
-
"tsdown": "^0.
|
|
65
|
-
"typescript": "^5.9.
|
|
64
|
+
"tsdown": "^0.21.6",
|
|
65
|
+
"typescript": "^5.9.2"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@logtape/logtape": "^2.0.0",
|
package/src/docloader.test.ts
CHANGED
|
@@ -361,6 +361,73 @@ test("getDocumentLoader()", async (t) => {
|
|
|
361
361
|
);
|
|
362
362
|
});
|
|
363
363
|
|
|
364
|
+
let redirectAttempts = 0;
|
|
365
|
+
fetchMock.get("begin:https://example.com/too-many-redirects/", (cl) => {
|
|
366
|
+
redirectAttempts++;
|
|
367
|
+
const index = Number(cl.url.split("/").at(-1));
|
|
368
|
+
return {
|
|
369
|
+
status: 302,
|
|
370
|
+
headers: {
|
|
371
|
+
Location: `https://example.com/too-many-redirects/${index + 1}`,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
await t.test("too many redirects", async () => {
|
|
377
|
+
redirectAttempts = 0;
|
|
378
|
+
await rejects(
|
|
379
|
+
() => fetchDocumentLoader("https://example.com/too-many-redirects/0"),
|
|
380
|
+
FetchError,
|
|
381
|
+
"Too many redirections",
|
|
382
|
+
);
|
|
383
|
+
deepStrictEqual(redirectAttempts, 21);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
let loopAttempts = 0;
|
|
387
|
+
fetchMock.get("https://example.com/redirect-loop-a", () => {
|
|
388
|
+
loopAttempts++;
|
|
389
|
+
return {
|
|
390
|
+
status: 302,
|
|
391
|
+
headers: { Location: "https://example.com/redirect-loop-b" },
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
fetchMock.get("https://example.com/redirect-loop-b", () => {
|
|
395
|
+
loopAttempts++;
|
|
396
|
+
return {
|
|
397
|
+
status: 302,
|
|
398
|
+
headers: { Location: "https://example.com/redirect-loop-a" },
|
|
399
|
+
};
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await t.test("redirect loop", async () => {
|
|
403
|
+
loopAttempts = 0;
|
|
404
|
+
await rejects(
|
|
405
|
+
() => fetchDocumentLoader("https://example.com/redirect-loop-a"),
|
|
406
|
+
FetchError,
|
|
407
|
+
"Redirect loop detected",
|
|
408
|
+
);
|
|
409
|
+
deepStrictEqual(loopAttempts, 2);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
let relativeLoopAttempts = 0;
|
|
413
|
+
fetchMock.get("https://example.com/redirect-loop-relative", () => {
|
|
414
|
+
relativeLoopAttempts++;
|
|
415
|
+
return {
|
|
416
|
+
status: 302,
|
|
417
|
+
headers: { Location: "/redirect-loop-relative" },
|
|
418
|
+
};
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
await t.test("redirect loop with relative location", async () => {
|
|
422
|
+
relativeLoopAttempts = 0;
|
|
423
|
+
await rejects(
|
|
424
|
+
() => fetchDocumentLoader("https://example.com/redirect-loop-relative"),
|
|
425
|
+
FetchError,
|
|
426
|
+
"Redirect loop detected",
|
|
427
|
+
);
|
|
428
|
+
deepStrictEqual(relativeLoopAttempts, 1);
|
|
429
|
+
});
|
|
430
|
+
|
|
364
431
|
// Regression test for ReDoS vulnerability (CVE-2025-68475)
|
|
365
432
|
// Malicious HTML payload: <a a="b" a="b" ... (unclosed tag)
|
|
366
433
|
// With the vulnerable regex, this causes catastrophic backtracking
|
package/src/docloader.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { UrlError, validatePublicUrl } from "./url.ts";
|
|
13
13
|
|
|
14
14
|
const logger = getLogger(["fedify", "runtime", "docloader"]);
|
|
15
|
+
const DEFAULT_MAX_REDIRECTION = 20;
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* A remote JSON-LD document and its context fetched by
|
|
@@ -292,38 +293,45 @@ export function getDocumentLoader(
|
|
|
292
293
|
async function load(
|
|
293
294
|
url: string,
|
|
294
295
|
options?: DocumentLoaderOptions,
|
|
296
|
+
redirected = 0,
|
|
297
|
+
visited = new Set<string>(),
|
|
295
298
|
): Promise<RemoteDocument> {
|
|
296
299
|
options?.signal?.throwIfAborted();
|
|
297
|
-
|
|
298
|
-
|
|
300
|
+
const currentUrl = new URL(url).href;
|
|
301
|
+
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
302
|
+
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
299
303
|
return {
|
|
300
304
|
contextUrl: null,
|
|
301
|
-
document: preloadedContexts[
|
|
302
|
-
documentUrl:
|
|
305
|
+
document: preloadedContexts[currentUrl],
|
|
306
|
+
documentUrl: currentUrl,
|
|
303
307
|
};
|
|
304
308
|
}
|
|
305
309
|
if (!allowPrivateAddress) {
|
|
306
310
|
try {
|
|
307
|
-
await validatePublicUrl(
|
|
311
|
+
await validatePublicUrl(currentUrl);
|
|
308
312
|
} catch (error) {
|
|
309
313
|
if (error instanceof UrlError) {
|
|
310
|
-
logger.error("Disallowed private URL: {url}", {
|
|
314
|
+
logger.error("Disallowed private URL: {url}", {
|
|
315
|
+
url: currentUrl,
|
|
316
|
+
error,
|
|
317
|
+
});
|
|
311
318
|
}
|
|
312
319
|
throw error;
|
|
313
320
|
}
|
|
314
321
|
}
|
|
322
|
+
visited.add(currentUrl);
|
|
315
323
|
|
|
316
324
|
return await tracer.startActiveSpan(
|
|
317
325
|
"activitypub.fetch_document",
|
|
318
326
|
{
|
|
319
327
|
kind: SpanKind.CLIENT,
|
|
320
328
|
attributes: {
|
|
321
|
-
"url.full":
|
|
329
|
+
"url.full": currentUrl,
|
|
322
330
|
},
|
|
323
331
|
},
|
|
324
332
|
async (span) => {
|
|
325
333
|
try {
|
|
326
|
-
const request = createActivityPubRequest(
|
|
334
|
+
const request = createActivityPubRequest(currentUrl, { userAgent });
|
|
327
335
|
logRequest(logger, request);
|
|
328
336
|
const response = await fetch(request, {
|
|
329
337
|
// Since Bun has a bug that ignores the `Request.redirect` option,
|
|
@@ -339,12 +347,36 @@ export function getDocumentLoader(
|
|
|
339
347
|
response.status >= 300 && response.status < 400 &&
|
|
340
348
|
response.headers.has("Location")
|
|
341
349
|
) {
|
|
342
|
-
|
|
350
|
+
if (redirected >= DEFAULT_MAX_REDIRECTION) {
|
|
351
|
+
logger.error(
|
|
352
|
+
"Too many redirections ({redirections}) while fetching document.",
|
|
353
|
+
{ redirections: redirected + 1, url: currentUrl },
|
|
354
|
+
);
|
|
355
|
+
throw new FetchError(
|
|
356
|
+
currentUrl,
|
|
357
|
+
`Too many redirections (${redirected + 1})`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
const redirectUrl = new URL(
|
|
361
|
+
response.headers.get("Location")!,
|
|
362
|
+
response.url === "" ? currentUrl : response.url,
|
|
363
|
+
).href;
|
|
343
364
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
344
|
-
|
|
365
|
+
if (visited.has(redirectUrl)) {
|
|
366
|
+
logger.error(
|
|
367
|
+
"Detected a redirect loop while fetching document: {url} -> " +
|
|
368
|
+
"{redirectUrl}",
|
|
369
|
+
{ url: currentUrl, redirectUrl },
|
|
370
|
+
);
|
|
371
|
+
throw new FetchError(
|
|
372
|
+
currentUrl,
|
|
373
|
+
`Redirect loop detected: ${redirectUrl}`,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
return await load(redirectUrl, options, redirected + 1, visited);
|
|
345
377
|
}
|
|
346
378
|
|
|
347
|
-
const result = await getRemoteDocument(
|
|
379
|
+
const result = await getRemoteDocument(currentUrl, response, load);
|
|
348
380
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
349
381
|
if (result.contextUrl != null) {
|
|
350
382
|
span.setAttribute("docloader.context_url", result.contextUrl);
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { deno_default, getUserAgent } from "./request-BZixuWv5.js";
|
|
2
|
-
import { deepStrictEqual } from "node:assert";
|
|
3
|
-
import { test } from "node:test";
|
|
4
|
-
import process from "node:process";
|
|
5
|
-
|
|
6
|
-
//#region src/request.test.ts
|
|
7
|
-
test("getUserAgent()", () => {
|
|
8
|
-
if ("Deno" in globalThis) {
|
|
9
|
-
deepStrictEqual(getUserAgent(), `Fedify/${deno_default.version} (Deno/${Deno.version.deno})`);
|
|
10
|
-
deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${deno_default.version}; Deno/${Deno.version.deno})`);
|
|
11
|
-
deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${deno_default.version} (Deno/${Deno.version.deno}; +https://example.com/)`);
|
|
12
|
-
deepStrictEqual(getUserAgent({
|
|
13
|
-
software: "MyApp/1.0.0",
|
|
14
|
-
url: new URL("https://example.com/")
|
|
15
|
-
}), `MyApp/1.0.0 (Fedify/${deno_default.version}; Deno/${Deno.version.deno}; +https://example.com/)`);
|
|
16
|
-
} else if ("Bun" in globalThis) {
|
|
17
|
-
deepStrictEqual(getUserAgent(), `Fedify/${deno_default.version} (Bun/${Bun.version})`);
|
|
18
|
-
deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${deno_default.version}; Bun/${Bun.version})`);
|
|
19
|
-
deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${deno_default.version} (Bun/${Bun.version}; +https://example.com/)`);
|
|
20
|
-
deepStrictEqual(getUserAgent({
|
|
21
|
-
software: "MyApp/1.0.0",
|
|
22
|
-
url: new URL("https://example.com/")
|
|
23
|
-
}), `MyApp/1.0.0 (Fedify/${deno_default.version}; Bun/${Bun.version}; +https://example.com/)`);
|
|
24
|
-
} else if (navigator.userAgent === "Cloudflare-Workers") {
|
|
25
|
-
deepStrictEqual(getUserAgent(), `Fedify/${deno_default.version} (Cloudflare-Workers)`);
|
|
26
|
-
deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${deno_default.version}; Cloudflare-Workers)`);
|
|
27
|
-
deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${deno_default.version} (Cloudflare-Workers; +https://example.com/)`);
|
|
28
|
-
deepStrictEqual(getUserAgent({
|
|
29
|
-
software: "MyApp/1.0.0",
|
|
30
|
-
url: new URL("https://example.com/")
|
|
31
|
-
}), `MyApp/1.0.0 (Fedify/${deno_default.version}; Cloudflare-Workers; +https://example.com/)`);
|
|
32
|
-
} else {
|
|
33
|
-
deepStrictEqual(getUserAgent(), `Fedify/${deno_default.version} (Node.js/${process.versions.node})`);
|
|
34
|
-
deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${deno_default.version}; Node.js/${process.versions.node})`);
|
|
35
|
-
deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${deno_default.version} (Node.js/${process.versions.node}; +https://example.com/)`);
|
|
36
|
-
deepStrictEqual(getUserAgent({
|
|
37
|
-
software: "MyApp/1.0.0",
|
|
38
|
-
url: new URL("https://example.com/")
|
|
39
|
-
}), `MyApp/1.0.0 (Fedify/${deno_default.version}; Node.js/${process.versions.node}; +https://example.com/)`);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|