@fedify/vocab-runtime 2.1.0 → 2.1.2

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.
Files changed (58) hide show
  1. package/deno.json +1 -1
  2. package/dist/{chunk-CUT6urMc.cjs → chunk-CKQMccvm.cjs} +7 -9
  3. package/dist/jsonld.cjs +4 -5
  4. package/dist/jsonld.d.cts +3 -4
  5. package/dist/jsonld.d.ts +2 -2
  6. package/dist/jsonld.js +1 -3
  7. package/dist/mod.cjs +107 -180
  8. package/dist/mod.d.cts +1 -2
  9. package/dist/mod.d.ts +1 -2
  10. package/dist/mod.js +83 -159
  11. package/dist/tests/{chunk-DWy1uDak.cjs → chunk-Do9eywBl.cjs} +13 -17
  12. package/dist/tests/decimal.test.cjs +12 -21
  13. package/dist/tests/{decimal.test.js → decimal.test.mjs} +10 -18
  14. package/dist/tests/{docloader-D3nu2LmR.cjs → docloader-0Yz9aPvU.cjs} +78 -91
  15. package/dist/tests/{docloader-U31begIa.js → docloader-DiLx08rm.mjs} +62 -75
  16. package/dist/tests/docloader.test.cjs +98 -88
  17. package/dist/tests/{docloader.test.js → docloader.test.mjs} +98 -94
  18. package/dist/tests/internal/multicodec.test.cjs +5 -7
  19. package/dist/tests/internal/{multicodec.test.js → multicodec.test.mjs} +3 -4
  20. package/dist/tests/{key-ByCmSI2y.js → key-BeTHFQJK.mjs} +14 -25
  21. package/dist/tests/{key-CCPn6TEY.cjs → key-DTTIntwb.cjs} +60 -71
  22. package/dist/tests/key.test.cjs +23 -45
  23. package/dist/tests/{key.test.js → key.test.mjs} +21 -42
  24. package/dist/tests/{langstr-EPh86hXK.cjs → langstr-CbAxaeEZ.cjs} +6 -8
  25. package/dist/tests/{langstr-BsVE3s9u.js → langstr-Di5AvKpB.mjs} +1 -2
  26. package/dist/tests/langstr.test.cjs +7 -8
  27. package/dist/tests/{langstr.test.js → langstr.test.mjs} +3 -4
  28. package/dist/tests/{link-DYNFAdNu.cjs → link-FguCydMA.cjs} +6 -8
  29. package/dist/tests/{link-C3q2TC2G.js → link-NUUWCdnK.mjs} +1 -2
  30. package/dist/tests/link.test.cjs +5 -7
  31. package/dist/tests/{link.test.js → link.test.mjs} +3 -4
  32. package/dist/tests/multibase/multibase.test.cjs +10 -17
  33. package/dist/tests/multibase/{multibase.test.js → multibase.test.mjs} +10 -18
  34. package/dist/tests/{multibase-B4g8pz6F.js → multibase-BgU9XRf7.mjs} +5 -12
  35. package/dist/tests/{multibase-o_ovPHYJ.cjs → multibase-F7LtMMsK.cjs} +43 -49
  36. package/dist/tests/{multicodec--6hQ74zI.cjs → multicodec-CxGVGa91.cjs} +16 -18
  37. package/dist/tests/{multicodec-Dq3IiOV4.js → multicodec-CyFp54fI.mjs} +1 -2
  38. package/dist/tests/{request-DyrEDYQ-.cjs → request-B4BOehn0.cjs} +38 -72
  39. package/dist/tests/{request-BH_NlxCL.js → request-Nob25QBF.mjs} +4 -45
  40. package/dist/tests/request.test.cjs +23 -24
  41. package/dist/tests/request.test.mjs +42 -0
  42. package/dist/tests/{url-CWEP9Zs9.js → url-BQ_kgmCk.mjs} +3 -7
  43. package/dist/tests/{url-DIjOdK8Q.cjs → url-pFuSds44.cjs} +31 -35
  44. package/dist/tests/url.test.cjs +5 -7
  45. package/dist/tests/{url.test.js → url.test.mjs} +3 -4
  46. package/package.json +3 -3
  47. package/src/docloader.test.ts +67 -0
  48. package/src/docloader.ts +43 -11
  49. package/dist/tests/request.test.js +0 -43
  50. /package/dist/tests/{decimal.test.d.ts → decimal.test.d.mts} +0 -0
  51. /package/dist/tests/{docloader.test.d.ts → docloader.test.d.mts} +0 -0
  52. /package/dist/tests/internal/{multicodec.test.d.ts → multicodec.test.d.mts} +0 -0
  53. /package/dist/tests/{key.test.d.ts → key.test.d.mts} +0 -0
  54. /package/dist/tests/{langstr.test.d.ts → langstr.test.d.mts} +0 -0
  55. /package/dist/tests/{link.test.d.ts → link.test.d.mts} +0 -0
  56. /package/dist/tests/multibase/{multibase.test.d.ts → multibase.test.d.mts} +0 -0
  57. /package/dist/tests/{request.test.d.ts → request.test.d.mts} +0 -0
  58. /package/dist/tests/{url.test.d.ts → url.test.d.mts} +0 -0
@@ -0,0 +1,42 @@
1
+ import { o as version, r as getUserAgent } from "./request-Nob25QBF.mjs";
2
+ import { deepStrictEqual } from "node:assert";
3
+ import { test } from "node:test";
4
+ import process from "node:process";
5
+ //#region src/request.test.ts
6
+ test("getUserAgent()", () => {
7
+ if ("Deno" in globalThis) {
8
+ deepStrictEqual(getUserAgent(), `Fedify/${version} (Deno/${Deno.version.deno})`);
9
+ deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${version}; Deno/${Deno.version.deno})`);
10
+ deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${version} (Deno/${Deno.version.deno}; +https://example.com/)`);
11
+ deepStrictEqual(getUserAgent({
12
+ software: "MyApp/1.0.0",
13
+ url: new URL("https://example.com/")
14
+ }), `MyApp/1.0.0 (Fedify/${version}; Deno/${Deno.version.deno}; +https://example.com/)`);
15
+ } else if ("Bun" in globalThis) {
16
+ deepStrictEqual(getUserAgent(), `Fedify/${version} (Bun/${Bun.version})`);
17
+ deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${version}; Bun/${Bun.version})`);
18
+ deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${version} (Bun/${Bun.version}; +https://example.com/)`);
19
+ deepStrictEqual(getUserAgent({
20
+ software: "MyApp/1.0.0",
21
+ url: new URL("https://example.com/")
22
+ }), `MyApp/1.0.0 (Fedify/${version}; Bun/${Bun.version}; +https://example.com/)`);
23
+ } else if (navigator.userAgent === "Cloudflare-Workers") {
24
+ deepStrictEqual(getUserAgent(), `Fedify/${version} (Cloudflare-Workers)`);
25
+ deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${version}; Cloudflare-Workers)`);
26
+ deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${version} (Cloudflare-Workers; +https://example.com/)`);
27
+ deepStrictEqual(getUserAgent({
28
+ software: "MyApp/1.0.0",
29
+ url: new URL("https://example.com/")
30
+ }), `MyApp/1.0.0 (Fedify/${version}; Cloudflare-Workers; +https://example.com/)`);
31
+ } else {
32
+ deepStrictEqual(getUserAgent(), `Fedify/${version} (Node.js/${process.versions.node})`);
33
+ deepStrictEqual(getUserAgent({ software: "MyApp/1.0.0" }), `MyApp/1.0.0 (Fedify/${version}; Node.js/${process.versions.node})`);
34
+ deepStrictEqual(getUserAgent({ url: "https://example.com/" }), `Fedify/${version} (Node.js/${process.versions.node}; +https://example.com/)`);
35
+ deepStrictEqual(getUserAgent({
36
+ software: "MyApp/1.0.0",
37
+ url: new URL("https://example.com/")
38
+ }), `MyApp/1.0.0 (Fedify/${version}; Node.js/${process.versions.node}; +https://example.com/)`);
39
+ }
40
+ });
41
+ //#endregion
42
+ export {};
@@ -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
- const netPermission = await Deno.permissions.query({ name: "net" });
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
- const parts = address.split(":");
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 { UrlError, expandIPv6Address, isValidPublicIPv4Address, isValidPublicIPv6Address, validatePublicUrl };
59
+ export { validatePublicUrl as a, isValidPublicIPv6Address as i, expandIPv6Address as n, isValidPublicIPv4Address as r, UrlError as t };
@@ -1,7 +1,6 @@
1
- const require_chunk = require('./chunk-DWy1uDak.cjs');
2
- const node_dns_promises = require_chunk.__toESM(require("node:dns/promises"));
3
- const node_net = require_chunk.__toESM(require("node:net"));
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
- const netPermission = await Deno.permissions.query({ name: "net" });
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
- const parts = address.split(":");
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, 'UrlError', {
65
- enumerable: true,
66
- get: function () {
67
- return UrlError;
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, 'expandIPv6Address', {
71
- enumerable: true,
72
- get: function () {
73
- return expandIPv6Address;
74
- }
72
+ Object.defineProperty(exports, "isValidPublicIPv4Address", {
73
+ enumerable: true,
74
+ get: function() {
75
+ return isValidPublicIPv4Address;
76
+ }
75
77
  });
76
- Object.defineProperty(exports, 'isValidPublicIPv4Address', {
77
- enumerable: true,
78
- get: function () {
79
- return isValidPublicIPv4Address;
80
- }
78
+ Object.defineProperty(exports, "isValidPublicIPv6Address", {
79
+ enumerable: true,
80
+ get: function() {
81
+ return isValidPublicIPv6Address;
82
+ }
81
83
  });
82
- Object.defineProperty(exports, 'isValidPublicIPv6Address', {
83
- enumerable: true,
84
- get: function () {
85
- return isValidPublicIPv6Address;
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,8 +1,7 @@
1
- const require_chunk = require('./chunk-DWy1uDak.cjs');
2
- const require_url = require('./url-DIjOdK8Q.cjs');
3
- const node_assert = require_chunk.__toESM(require("node:assert"));
4
- const node_test = require_chunk.__toESM(require("node:test"));
5
-
1
+ require("./chunk-Do9eywBl.cjs");
2
+ const require_url = require("./url-pFuSds44.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 { UrlError, expandIPv6Address, isValidPublicIPv4Address, isValidPublicIPv6Address, validatePublicUrl } from "./url-CWEP9Zs9.js";
1
+ import { a as validatePublicUrl, i as isValidPublicIPv6Address, n as expandIPv6Address, r as isValidPublicIPv4Address, t as UrlError } from "./url-BQ_kgmCk.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
- //#endregion
34
+ //#endregion
35
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-runtime",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
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.12.9",
65
- "typescript": "^5.9.3"
64
+ "tsdown": "^0.21.6",
65
+ "typescript": "^5.9.2"
66
66
  },
67
67
  "dependencies": {
68
68
  "@logtape/logtape": "^2.0.5",
@@ -369,6 +369,73 @@ test("getDocumentLoader()", async (t) => {
369
369
  );
370
370
  });
371
371
 
372
+ let redirectAttempts = 0;
373
+ fetchMock.get("begin:https://example.com/too-many-redirects/", (cl) => {
374
+ redirectAttempts++;
375
+ const index = Number(cl.url.split("/").at(-1));
376
+ return {
377
+ status: 302,
378
+ headers: {
379
+ Location: `https://example.com/too-many-redirects/${index + 1}`,
380
+ },
381
+ };
382
+ });
383
+
384
+ await t.test("too many redirects", async () => {
385
+ redirectAttempts = 0;
386
+ await rejects(
387
+ () => fetchDocumentLoader("https://example.com/too-many-redirects/0"),
388
+ FetchError,
389
+ "Too many redirections",
390
+ );
391
+ deepStrictEqual(redirectAttempts, 21);
392
+ });
393
+
394
+ let loopAttempts = 0;
395
+ fetchMock.get("https://example.com/redirect-loop-a", () => {
396
+ loopAttempts++;
397
+ return {
398
+ status: 302,
399
+ headers: { Location: "https://example.com/redirect-loop-b" },
400
+ };
401
+ });
402
+ fetchMock.get("https://example.com/redirect-loop-b", () => {
403
+ loopAttempts++;
404
+ return {
405
+ status: 302,
406
+ headers: { Location: "https://example.com/redirect-loop-a" },
407
+ };
408
+ });
409
+
410
+ await t.test("redirect loop", async () => {
411
+ loopAttempts = 0;
412
+ await rejects(
413
+ () => fetchDocumentLoader("https://example.com/redirect-loop-a"),
414
+ FetchError,
415
+ "Redirect loop detected",
416
+ );
417
+ deepStrictEqual(loopAttempts, 2);
418
+ });
419
+
420
+ let relativeLoopAttempts = 0;
421
+ fetchMock.get("https://example.com/redirect-loop-relative", () => {
422
+ relativeLoopAttempts++;
423
+ return {
424
+ status: 302,
425
+ headers: { Location: "/redirect-loop-relative" },
426
+ };
427
+ });
428
+
429
+ await t.test("redirect loop with relative location", async () => {
430
+ relativeLoopAttempts = 0;
431
+ await rejects(
432
+ () => fetchDocumentLoader("https://example.com/redirect-loop-relative"),
433
+ FetchError,
434
+ "Redirect loop detected",
435
+ );
436
+ deepStrictEqual(relativeLoopAttempts, 1);
437
+ });
438
+
372
439
  // Regression test for ReDoS vulnerability (CVE-2025-68475)
373
440
  // Malicious HTML payload: <a a="b" a="b" ... (unclosed tag)
374
441
  // 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
@@ -293,38 +294,45 @@ export function getDocumentLoader(
293
294
  async function load(
294
295
  url: string,
295
296
  options?: DocumentLoaderOptions,
297
+ redirected = 0,
298
+ visited = new Set<string>(),
296
299
  ): Promise<RemoteDocument> {
297
300
  options?.signal?.throwIfAborted();
298
- if (!skipPreloadedContexts && url in preloadedContexts) {
299
- logger.debug("Using preloaded context: {url}.", { url });
301
+ const currentUrl = new URL(url).href;
302
+ if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
303
+ logger.debug("Using preloaded context: {url}.", { url: currentUrl });
300
304
  return {
301
305
  contextUrl: null,
302
- document: preloadedContexts[url],
303
- documentUrl: url,
306
+ document: preloadedContexts[currentUrl],
307
+ documentUrl: currentUrl,
304
308
  };
305
309
  }
306
310
  if (!allowPrivateAddress) {
307
311
  try {
308
- await validatePublicUrl(url);
312
+ await validatePublicUrl(currentUrl);
309
313
  } catch (error) {
310
314
  if (error instanceof UrlError) {
311
- logger.error("Disallowed private URL: {url}", { url, error });
315
+ logger.error("Disallowed private URL: {url}", {
316
+ url: currentUrl,
317
+ error,
318
+ });
312
319
  }
313
320
  throw error;
314
321
  }
315
322
  }
323
+ visited.add(currentUrl);
316
324
 
317
325
  return await tracer.startActiveSpan(
318
326
  "activitypub.fetch_document",
319
327
  {
320
328
  kind: SpanKind.CLIENT,
321
329
  attributes: {
322
- "url.full": url,
330
+ "url.full": currentUrl,
323
331
  },
324
332
  },
325
333
  async (span) => {
326
334
  try {
327
- const request = createActivityPubRequest(url, { userAgent });
335
+ const request = createActivityPubRequest(currentUrl, { userAgent });
328
336
  logRequest(logger, request);
329
337
  const response = await fetch(request, {
330
338
  // Since Bun has a bug that ignores the `Request.redirect` option,
@@ -340,12 +348,36 @@ export function getDocumentLoader(
340
348
  response.status >= 300 && response.status < 400 &&
341
349
  response.headers.has("Location")
342
350
  ) {
343
- const redirectUrl = response.headers.get("Location")!;
351
+ if (redirected >= DEFAULT_MAX_REDIRECTION) {
352
+ logger.error(
353
+ "Too many redirections ({redirections}) while fetching document.",
354
+ { redirections: redirected + 1, url: currentUrl },
355
+ );
356
+ throw new FetchError(
357
+ currentUrl,
358
+ `Too many redirections (${redirected + 1})`,
359
+ );
360
+ }
361
+ const redirectUrl = new URL(
362
+ response.headers.get("Location")!,
363
+ response.url === "" ? currentUrl : response.url,
364
+ ).href;
344
365
  span.setAttribute("http.redirect.url", redirectUrl);
345
- return await load(redirectUrl, options);
366
+ if (visited.has(redirectUrl)) {
367
+ logger.error(
368
+ "Detected a redirect loop while fetching document: {url} -> " +
369
+ "{redirectUrl}",
370
+ { url: currentUrl, redirectUrl },
371
+ );
372
+ throw new FetchError(
373
+ currentUrl,
374
+ `Redirect loop detected: ${redirectUrl}`,
375
+ );
376
+ }
377
+ return await load(redirectUrl, options, redirected + 1, visited);
346
378
  }
347
379
 
348
- const result = await getRemoteDocument(url, response, load);
380
+ const result = await getRemoteDocument(currentUrl, response, load);
349
381
  span.setAttribute("docloader.document_url", result.documentUrl);
350
382
  if (result.contextUrl != null) {
351
383
  span.setAttribute("docloader.context_url", result.contextUrl);
@@ -1,43 +0,0 @@
1
- import { deno_default, getUserAgent } from "./request-BH_NlxCL.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