@fedify/fedify 1.5.0-dev.699 → 1.5.0-dev.714

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/CHANGES.md CHANGED
@@ -37,8 +37,24 @@ To be released.
37
37
  the page.
38
38
  - You can easily copy the fediverse handle of the ephemeral actor.
39
39
 
40
+ - Internalized the [multibase] package, which is obsolete and no longer
41
+ maintained. [[#127], [#215] by Fróði Karlsson]
42
+
43
+ [#127]: https://github.com/fedify-dev/fedify/issues/127
40
44
  [#209]: https://github.com/fedify-dev/fedify/issues/209
41
45
  [#211]: https://github.com/fedify-dev/fedify/issues/211
46
+ [#215]: https://github.com/fedify-dev/fedify/pull/215
47
+ [multibase]: https://github.com/multiformats/js-multibase
48
+
49
+
50
+ Version 1.4.6
51
+ -------------
52
+
53
+ Released on March 9, 2025.
54
+
55
+ - Fedify no more depends on `node:punycode` module, which is deprecated in
56
+ Node.js. Now it uses the built-in `node:url` module instead.
57
+ [[#212], [#214] by Fróði Karlsson]
42
58
 
43
59
 
44
60
  Version 1.4.5
@@ -194,6 +210,16 @@ Released on February 5, 2025.
194
210
  [#195]: https://github.com/fedify-dev/fedify/issues/195
195
211
 
196
212
 
213
+ Version 1.3.13
214
+ --------------
215
+
216
+ Released on March 9, 2025.
217
+
218
+ - Fedify no more depends on `node:punycode` module, which is deprecated in
219
+ Node.js. Now it uses the built-in `node:url` module instead.
220
+ [[#212], [#214] by Fróði Karlsson]
221
+
222
+
197
223
  Version 1.3.12
198
224
  --------------
199
225
 
@@ -463,6 +489,16 @@ Released on November 30, 2024.
463
489
  [#193]: https://github.com/fedify-dev/fedify/issues/193
464
490
 
465
491
 
492
+ Version 1.2.17
493
+ --------------
494
+
495
+ Released on March 9, 2025.
496
+
497
+ - Fedify no more depends on `node:punycode` module, which is deprecated in
498
+ Node.js. Now it uses the built-in `node:url` module instead.
499
+ [[#212], [#214] by Fróði Karlsson]
500
+
501
+
466
502
  Version 1.2.16
467
503
  --------------
468
504
 
@@ -781,6 +817,16 @@ Released on October 31, 2024.
781
817
  [#118]: https://github.com/fedify-dev/fedify/issues/118
782
818
 
783
819
 
820
+ Version 1.1.17
821
+ --------------
822
+
823
+ Released on March 9, 2025.
824
+
825
+ - Fedify no more depends on `node:punycode` module, which is deprecated in
826
+ Node.js. Now it uses the built-in `node:url` module instead.
827
+ [[#212], [#214] by Fróði Karlsson]
828
+
829
+
784
830
  Version 1.1.16
785
831
  --------------
786
832
 
@@ -1140,6 +1186,19 @@ Released on October 20, 2024.
1140
1186
  [#150]: https://github.com/fedify-dev/fedify/issues/150
1141
1187
 
1142
1188
 
1189
+ Version 1.0.20
1190
+ --------------
1191
+
1192
+ Released on March 9, 2025.
1193
+
1194
+ - Fedify no more depends on `node:punycode` module, which is deprecated in
1195
+ Node.js. Now it uses the built-in `node:url` module instead.
1196
+ [[#212], [#214] by Fróði Karlsson]
1197
+
1198
+ [#212]: https://github.com/fedify-dev/fedify/issues/212
1199
+ [#214]: https://github.com/fedify-dev/fedify/pull/214
1200
+
1201
+
1143
1202
  Version 1.0.19
1144
1203
  --------------
1145
1204
 
@@ -3291,4 +3350,5 @@ Version 0.1.0
3291
3350
 
3292
3351
  Initial release. Released on March 8, 2024.
3293
3352
 
3294
- <!-- cSpell: ignore Dogeon Fabien Wressell Emelia Hana Heesun Kyunghee Jiyu -->
3353
+ <!-- cSpell: ignore Dogeon Fabien Wressell Emelia Fróði Karlsson -->
3354
+ <!-- cSpell: ignore Hana Heesun Kyunghee Jiyu -->
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.5.0-dev.699+a9e5f890",
3
+ "version": "1.5.0-dev.714+56abdd05",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./mod.ts",
@@ -40,7 +40,6 @@ export default {
40
40
  "json-canon": "npm:json-canon@^1.0.1",
41
41
  "jsonld": "npm:jsonld@^8.3.2",
42
42
  "mock_fetch": "jsr:@hongminhee/deno-mock-fetch@^0.3.2",
43
- "multibase": "npm:multibase@^4.0.6",
44
43
  "multicodec": "npm:multicodec@^3.2.1",
45
44
  "pkijs": "npm:pkijs@^3.2.4",
46
45
  "uri-template-router": "npm:uri-template-router@^0.0.16",
@@ -4,7 +4,7 @@ import { decodeBase64, encodeBase64 } from "../deps/jsr.io/@std/encoding/1.0.7/b
4
4
  import { decodeBase64Url } from "../deps/jsr.io/@std/encoding/1.0.7/base64url.js";
5
5
  import { decodeHex } from "../deps/jsr.io/@std/encoding/1.0.7/hex.js";
6
6
  import { Integer, Sequence } from "asn1js";
7
- import { decode, encode } from "multibase";
7
+ import { decode, encode } from "./multibase/index.js";
8
8
  import { addPrefix, getCodeFromData, rmPrefix } from "multicodec";
9
9
  import { createPublicKey } from "node:crypto";
10
10
  import { PublicKeyInfo } from "pkijs";
@@ -0,0 +1,30 @@
1
+ import { encodeText } from "./util.js";
2
+ /**
3
+ * Class to encode/decode in the supported Bases
4
+ */
5
+ export class Base {
6
+ name;
7
+ code;
8
+ alphabet;
9
+ codeBuf;
10
+ codec;
11
+ constructor(name, code, factory, alphabet) {
12
+ this.name = name;
13
+ this.code = code;
14
+ this.alphabet = alphabet;
15
+ this.codeBuf = encodeText(this.code);
16
+ this.alphabet = alphabet;
17
+ this.codec = factory(alphabet);
18
+ }
19
+ encode(buf) {
20
+ return this.codec.encode(buf);
21
+ }
22
+ decode(string) {
23
+ for (const char of string) {
24
+ if (this.alphabet && this.alphabet.indexOf(char) < 0) {
25
+ throw new Error(`invalid character '${char}' in '${string}'`);
26
+ }
27
+ }
28
+ return this.codec.decode(string);
29
+ }
30
+ }
@@ -0,0 +1,78 @@
1
+ import baseX from "@multiformats/base-x";
2
+ import { Base } from "./base.js";
3
+ import { rfc4648 } from "./rfc4648.js";
4
+ import { decodeText, encodeText } from "./util.js";
5
+ const identity = () => {
6
+ return {
7
+ encode: decodeText,
8
+ decode: encodeText,
9
+ };
10
+ };
11
+ /**
12
+ * name, code, implementation, alphabet
13
+ *
14
+ * @type {Array<[BaseName, BaseCode, CodecFactory, string]>}
15
+ */
16
+ const constants = [
17
+ ["identity", "\x00", identity, ""],
18
+ ["base2", "0", rfc4648(1), "01"],
19
+ ["base8", "7", rfc4648(3), "01234567"],
20
+ ["base10", "9", baseX, "0123456789"],
21
+ ["base16", "f", rfc4648(4), "0123456789abcdef"],
22
+ ["base16upper", "F", rfc4648(4), "0123456789ABCDEF"],
23
+ ["base32hex", "v", rfc4648(5), "0123456789abcdefghijklmnopqrstuv"],
24
+ ["base32hexupper", "V", rfc4648(5), "0123456789ABCDEFGHIJKLMNOPQRSTUV"],
25
+ ["base32hexpad", "t", rfc4648(5), "0123456789abcdefghijklmnopqrstuv="],
26
+ ["base32hexpadupper", "T", rfc4648(5), "0123456789ABCDEFGHIJKLMNOPQRSTUV="],
27
+ ["base32", "b", rfc4648(5), "abcdefghijklmnopqrstuvwxyz234567"],
28
+ ["base32upper", "B", rfc4648(5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"],
29
+ ["base32pad", "c", rfc4648(5), "abcdefghijklmnopqrstuvwxyz234567="],
30
+ ["base32padupper", "C", rfc4648(5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="],
31
+ ["base32z", "h", rfc4648(5), "ybndrfg8ejkmcpqxot1uwisza345h769"],
32
+ ["base36", "k", baseX, "0123456789abcdefghijklmnopqrstuvwxyz"],
33
+ ["base36upper", "K", baseX, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"],
34
+ [
35
+ "base58btc",
36
+ "z",
37
+ baseX,
38
+ "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
39
+ ],
40
+ [
41
+ "base58flickr",
42
+ "Z",
43
+ baseX,
44
+ "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ",
45
+ ],
46
+ [
47
+ "base64",
48
+ "m",
49
+ rfc4648(6),
50
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
51
+ ],
52
+ [
53
+ "base64pad",
54
+ "M",
55
+ rfc4648(6),
56
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
57
+ ],
58
+ [
59
+ "base64url",
60
+ "u",
61
+ rfc4648(6),
62
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
63
+ ],
64
+ [
65
+ "base64urlpad",
66
+ "U",
67
+ rfc4648(6),
68
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
69
+ ],
70
+ ];
71
+ export const names = constants.reduce((prev, tupple) => {
72
+ prev[tupple[0]] = new Base(tupple[0], tupple[1], tupple[2], tupple[3]);
73
+ return prev;
74
+ }, {});
75
+ export const codes = constants.reduce((prev, tupple) => {
76
+ prev[tupple[1]] = names[tupple[0]];
77
+ return prev;
78
+ }, {});
@@ -0,0 +1,59 @@
1
+ import * as constants from "./constants.js";
2
+ import { concat, decodeText, encodeText } from "./util.js";
3
+ /**
4
+ * Encode data with the specified base and add the multibase prefix.
5
+ *
6
+ * @throws {Error} Will throw if the encoding is not supported
7
+ */
8
+ export function encode(nameOrCode, buf) {
9
+ const enc = encoding(nameOrCode);
10
+ const data = encodeText(enc.encode(buf));
11
+ return concat([enc.codeBuf, data], enc.codeBuf.length + data.length);
12
+ }
13
+ /**
14
+ * Takes a Uint8Array or string encoded with multibase header, decodes it and
15
+ * returns the decoded buffer
16
+ *
17
+ * @throws {Error} Will throw if the encoding is not supported
18
+ */
19
+ export function decode(data) {
20
+ if (data instanceof Uint8Array) {
21
+ data = decodeText(data);
22
+ }
23
+ const prefix = data[0];
24
+ // Make all encodings case-insensitive except the ones that include upper and lower chars in the alphabet
25
+ if (["f", "F", "v", "V", "t", "T", "b", "B", "c", "C", "h", "k", "K"].includes(prefix)) {
26
+ data = data.toLowerCase();
27
+ }
28
+ const enc = encoding(data[0]);
29
+ return enc.decode(data.substring(1));
30
+ }
31
+ /**
32
+ * Get the encoding by name or code
33
+ * @throws {Error} Will throw if the encoding is not supported
34
+ */
35
+ function encoding(nameOrCode) {
36
+ if (Object.prototype.hasOwnProperty.call(constants.names, nameOrCode)) {
37
+ return constants.names[nameOrCode];
38
+ }
39
+ else if (Object.prototype.hasOwnProperty.call(constants.codes,
40
+ /** @type {BaseCode} */ (nameOrCode))) {
41
+ return constants.codes[nameOrCode];
42
+ }
43
+ else {
44
+ throw new Error(`Unsupported encoding: ${nameOrCode}`);
45
+ }
46
+ }
47
+ /**
48
+ * Get encoding from data
49
+ *
50
+ * @param {string|Uint8Array} data
51
+ * @returns {Base}
52
+ * @throws {Error} Will throw if the encoding is not supported
53
+ */
54
+ export function encodingFromData(data) {
55
+ if (data instanceof Uint8Array) {
56
+ data = decodeText(data);
57
+ }
58
+ return encoding(data[0]);
59
+ }
@@ -0,0 +1,79 @@
1
+ const decode = (string, alphabet, bitsPerChar) => {
2
+ // Build the character lookup table:
3
+ const codes = {};
4
+ for (let i = 0; i < alphabet.length; ++i) {
5
+ codes[alphabet[i]] = i;
6
+ }
7
+ // Count the padding bytes:
8
+ let end = string.length;
9
+ while (string[end - 1] === "=") {
10
+ --end;
11
+ }
12
+ // Allocate the output:
13
+ const out = new Uint8Array((end * bitsPerChar / 8) | 0);
14
+ // Parse the data:
15
+ let bits = 0; // Number of bits currently in the buffer
16
+ let buffer = 0; // Bits waiting to be written out, MSB first
17
+ let written = 0; // Next byte to write
18
+ for (let i = 0; i < end; ++i) {
19
+ // Read one character from the string:
20
+ const value = codes[string[i]];
21
+ if (value === undefined) {
22
+ throw new SyntaxError("Invalid character " + string[i]);
23
+ }
24
+ // Append the bits to the buffer:
25
+ buffer = (buffer << bitsPerChar) | value;
26
+ bits += bitsPerChar;
27
+ // Write out some bits if the buffer has a byte's worth:
28
+ if (bits >= 8) {
29
+ bits -= 8;
30
+ out[written++] = 0xff & (buffer >> bits);
31
+ }
32
+ }
33
+ // Verify that we have received just enough bits:
34
+ if (bits >= bitsPerChar || 0xff & (buffer << (8 - bits))) {
35
+ throw new SyntaxError("Unexpected end of data");
36
+ }
37
+ return out;
38
+ };
39
+ const encode = (data, alphabet, bitsPerChar) => {
40
+ const pad = alphabet[alphabet.length - 1] === "=";
41
+ const mask = (1 << bitsPerChar) - 1;
42
+ let out = "";
43
+ let bits = 0; // Number of bits currently in the buffer
44
+ let buffer = 0; // Bits waiting to be written out, MSB first
45
+ for (let i = 0; i < data.length; ++i) {
46
+ // Slurp data into the buffer:
47
+ buffer = (buffer << 8) | data[i];
48
+ bits += 8;
49
+ // Write out as much as we can:
50
+ while (bits > bitsPerChar) {
51
+ bits -= bitsPerChar;
52
+ out += alphabet[mask & (buffer >> bits)];
53
+ }
54
+ }
55
+ // Partial character:
56
+ if (bits) {
57
+ out += alphabet[mask & (buffer << (bitsPerChar - bits))];
58
+ }
59
+ // Add padding characters until we hit a byte boundary:
60
+ if (pad) {
61
+ while ((out.length * bitsPerChar) & 7) {
62
+ out += "=";
63
+ }
64
+ }
65
+ return out;
66
+ };
67
+ /**
68
+ * RFC4648 Factory
69
+ */
70
+ export const rfc4648 = (bitsPerChar) => (alphabet) => {
71
+ return {
72
+ encode(input) {
73
+ return encode(input, alphabet, bitsPerChar);
74
+ },
75
+ decode(input) {
76
+ return decode(input, alphabet, bitsPerChar);
77
+ },
78
+ };
79
+ };
@@ -0,0 +1,13 @@
1
+ const textDecoder = new TextDecoder();
2
+ export const decodeText = (bytes) => textDecoder.decode(bytes);
3
+ const textEncoder = new TextEncoder();
4
+ export const encodeText = (text) => textEncoder.encode(text);
5
+ export function concat(arrs, length) {
6
+ const output = new Uint8Array(length);
7
+ let offset = 0;
8
+ for (const arr of arrs) {
9
+ output.set(arr, offset);
10
+ offset += arr.length;
11
+ }
12
+ return output;
13
+ }
@@ -33,8 +33,13 @@ export async function validatePublicUrl(url) {
33
33
  // FIXME: This is a temporary workaround for the `Bun` runtime; for unknown
34
34
  // reasons, the Web Crypto API does not work as expected after a DNS lookup.
35
35
  // This workaround purposes to prevent unit tests from hanging up:
36
- if ("Bun" in dntShim.dntGlobalThis && hostname === "example.com") {
37
- return;
36
+ if ("Bun" in dntShim.dntGlobalThis) {
37
+ if (hostname === "example.com" || hostname.endsWith(".example.com")) {
38
+ return;
39
+ }
40
+ else if (hostname === "fedify-test.internal") {
41
+ throw new UrlError("Invalid or private address: fedify-test.internal");
42
+ }
38
43
  }
39
44
  // To prevent SSRF via DNS rebinding, we need to resolve all IP addresses
40
45
  // and ensure that they are all public:
@@ -1,5 +1,5 @@
1
1
  import { SpanStatusCode, trace } from "@opentelemetry/api";
2
- import { toASCII, toUnicode } from "node:punycode";
2
+ import { domainToASCII, domainToUnicode } from "node:url";
3
3
  import metadata from "../deno.js";
4
4
  import { lookupWebFinger } from "../webfinger/lookup.js";
5
5
  import { getTypeId } from "./type.js";
@@ -161,7 +161,7 @@ export function normalizeActorHandle(handle, options = {}) {
161
161
  throw new TypeError("Invalid actor handle.");
162
162
  }
163
163
  domain = domain.toLowerCase();
164
- domain = options.punycode ? toASCII(domain) : toUnicode(domain);
164
+ domain = options.punycode ? domainToASCII(domain) : domainToUnicode(domain);
165
165
  domain = domain.toLowerCase();
166
166
  const user = handle.substring(0, atPos);
167
167
  return options.trimLeadingAt ? `${user}@${domain}` : `@${user}@${domain}`;