@fedify/vocab-runtime 2.1.23 → 2.1.25

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 (56) hide show
  1. package/deno.json +1 -1
  2. package/dist/mod.cjs +220 -107
  3. package/dist/mod.d.cts +10 -0
  4. package/dist/mod.d.ts +10 -0
  5. package/dist/mod.js +220 -108
  6. package/dist/tests/body-D-gC5vdl.cjs +95 -0
  7. package/dist/tests/body-DBqFojnW.mjs +77 -0
  8. package/dist/tests/body.test.cjs +90 -0
  9. package/dist/tests/body.test.d.cts +1 -0
  10. package/dist/tests/body.test.d.mts +1 -0
  11. package/dist/tests/body.test.mjs +90 -0
  12. package/dist/tests/decimal.test.cjs +6 -6
  13. package/dist/tests/decimal.test.mjs +6 -6
  14. package/dist/tests/{docloader-D-CBVlrJ.mjs → docloader-Beoc8qTH.mjs} +66 -37
  15. package/dist/tests/{docloader-BcWmxXdo.cjs → docloader-fn4ICzFS.cjs} +71 -36
  16. package/dist/tests/docloader.test.cjs +321 -4
  17. package/dist/tests/docloader.test.mjs +320 -4
  18. package/dist/tests/internal/multicodec.test.cjs +2 -2
  19. package/dist/tests/internal/multicodec.test.mjs +2 -2
  20. package/dist/tests/{key-BeTHFQJK.mjs → key-BDIsC6hV.mjs} +2 -2
  21. package/dist/tests/{key-DTTIntwb.cjs → key-BarKGLQz.cjs} +2 -2
  22. package/dist/tests/key.test.cjs +3 -3
  23. package/dist/tests/key.test.mjs +3 -3
  24. package/dist/tests/langstr.test.cjs +2 -2
  25. package/dist/tests/langstr.test.mjs +2 -2
  26. package/dist/tests/link.test.cjs +2 -2
  27. package/dist/tests/link.test.mjs +2 -2
  28. package/dist/tests/multibase/multibase.test.cjs +2 -2
  29. package/dist/tests/multibase/multibase.test.mjs +2 -2
  30. package/dist/tests/{request-CdMLb0ba.cjs → request-DrO5xzev.cjs} +1 -1
  31. package/dist/tests/{request-DqsgdBUH.mjs → request-DxeGyJVh.mjs} +1 -1
  32. package/dist/tests/request.test.cjs +2 -2
  33. package/dist/tests/request.test.mjs +2 -2
  34. package/dist/tests/temporal.test.cjs +1 -1
  35. package/dist/tests/temporal.test.mjs +1 -1
  36. package/dist/tests/{url-o0e-aXQY.mjs → url-3fyJuqC0.mjs} +14 -4
  37. package/dist/tests/{url-CWU5HT3Y.cjs → url-vZTgkIZg.cjs} +15 -4
  38. package/dist/tests/url.test.cjs +37 -4
  39. package/dist/tests/url.test.mjs +37 -4
  40. package/package.json +1 -1
  41. package/src/body.test.ts +125 -0
  42. package/src/body.ts +95 -0
  43. package/src/contexts/fep-7aa9.json +24 -0
  44. package/src/contexts.ts +8 -0
  45. package/src/docloader.test.ts +431 -1
  46. package/src/docloader.ts +76 -49
  47. package/src/url.test.ts +29 -3
  48. package/src/url.ts +21 -5
  49. /package/dist/tests/{langstr-CbAxaeEZ.cjs → langstr-BOQHfJDr.cjs} +0 -0
  50. /package/dist/tests/{langstr-Di5AvKpB.mjs → langstr-DDLc4833.mjs} +0 -0
  51. /package/dist/tests/{link-NUUWCdnK.mjs → link-CYszIegt.mjs} +0 -0
  52. /package/dist/tests/{link-FguCydMA.cjs → link-qDTmjPw_.cjs} +0 -0
  53. /package/dist/tests/{multibase-F7LtMMsK.cjs → multibase-8zhYPa7o.cjs} +0 -0
  54. /package/dist/tests/{multibase-BgU9XRf7.mjs → multibase-Ds75BvXs.mjs} +0 -0
  55. /package/dist/tests/{multicodec-CyFp54fI.mjs → multicodec-BBPZjRfg.mjs} +0 -0
  56. /package/dist/tests/{multicodec-CxGVGa91.cjs → multicodec-ByS9XLsw.cjs} +0 -0
package/src/url.test.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { deepStrictEqual, ok, rejects, throws } from "node:assert";
1
+ import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert";
2
2
  import { test } from "node:test";
3
3
  import {
4
4
  expandIPv6Address,
@@ -9,6 +9,28 @@ import {
9
9
  validatePublicUrl,
10
10
  } from "./url.ts";
11
11
 
12
+ test("UrlError reason is independent of its cause", () => {
13
+ const cause = new Error("Underlying failure");
14
+ strictEqual(new UrlError("Rejected URL").reason, "disallowed");
15
+ const disallowedError = new UrlError("Rejected URL", { cause });
16
+ strictEqual(disallowedError.reason, "disallowed");
17
+ strictEqual(disallowedError.cause, cause);
18
+ const dnsError = new UrlError("Lookup failed", { reason: "dns", cause });
19
+ strictEqual(dnsError.reason, "dns");
20
+ strictEqual(dnsError.cause, cause);
21
+ });
22
+
23
+ test("validatePublicUrl() classifies disallowed URLs", async () => {
24
+ for (
25
+ const url of ["ftp://example.com", "https://localhost", "https://127.0.0.1"]
26
+ ) {
27
+ await rejects(() => validatePublicUrl(url), {
28
+ name: "UrlError",
29
+ reason: "disallowed",
30
+ });
31
+ }
32
+ });
33
+
12
34
  test("validatePublicUrl()", async () => {
13
35
  await rejects(() => validatePublicUrl("ftp://localhost"), UrlError);
14
36
  await rejects(
@@ -81,15 +103,19 @@ test("validateLookupAddresses() rejects unsafe or CNAME-only Cloudflare Workers
81
103
  { address: "private-host.example.net.", family: 4 },
82
104
  { address: "127.0.0.1", family: 4 },
83
105
  ]),
84
- UrlError,
106
+ { name: "UrlError", reason: "disallowed" },
85
107
  );
86
108
  throws(
87
109
  () =>
88
110
  validateLookupAddresses([
89
111
  { address: "app-host.example.net.", family: 4 },
90
112
  ]),
91
- UrlError,
113
+ { name: "UrlError", reason: "dns" },
92
114
  );
115
+ throws(() => validateLookupAddresses([]), {
116
+ name: "UrlError",
117
+ reason: "dns",
118
+ });
93
119
  });
94
120
 
95
121
  test("isValidPublicIPv4Address()", () => {
package/src/url.ts CHANGED
@@ -1,11 +1,25 @@
1
1
  import type { LookupAddress } from "node:dns";
2
- import { lookup } from "node:dns/promises";
2
+ // FIXME: the default dns import exists since tests can stub `dns.lookup()`.
3
+ // This should be replaced by injecting the lookup function such as an internal
4
+ // option on `validatePublicUrl()`
5
+ import dns from "node:dns/promises";
3
6
  import { isIP } from "node:net";
4
7
 
5
8
  export class UrlError extends Error {
6
- constructor(message: string, options?: { cause?: unknown }) {
9
+ /**
10
+ * The failure category. Defaults to `"disallowed"`.
11
+ * `"dns"` includes lookup errors and results with no usable IP addresses.
12
+ * @since 2.0.29
13
+ */
14
+ readonly reason: "dns" | "disallowed";
15
+
16
+ constructor(
17
+ message: string,
18
+ options?: { cause?: unknown; reason?: "dns" | "disallowed" },
19
+ ) {
7
20
  super(message, options);
8
21
  this.name = "UrlError";
22
+ this.reason = options?.reason ?? "disallowed";
9
23
  }
10
24
  }
11
25
 
@@ -50,9 +64,9 @@ export async function validatePublicUrl(url: string): Promise<void> {
50
64
  // and ensure that they are all public:
51
65
  let addresses: LookupAddress[];
52
66
  try {
53
- addresses = await lookup(hostname, { all: true });
67
+ addresses = await dns.lookup(hostname, { all: true });
54
68
  } catch (error) {
55
- throw new UrlError("DNS lookup failed", { cause: error });
69
+ throw new UrlError("DNS lookup failed", { cause: error, reason: "dns" });
56
70
  }
57
71
  validateLookupAddresses(addresses);
58
72
  }
@@ -85,7 +99,9 @@ export function validateLookupAddresses(
85
99
  validatePublicIpAddress(address, family);
86
100
  }
87
101
  if (ipAddressCount === 0) {
88
- throw new UrlError("DNS lookup did not return any IP address");
102
+ throw new UrlError("DNS lookup did not return any IP address", {
103
+ reason: "dns",
104
+ });
89
105
  }
90
106
  }
91
107