@wtasnorg/node-lib 0.0.9 → 0.0.11
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/changelog.txt +14 -0
- package/dev_checklist.txt +9 -3
- package/docs/README.md +12 -0
- package/docs/docs.json +1523 -233
- package/docs/functions/createFindDirectories.md +1 -1
- package/docs/functions/decode.md +1 -1
- package/docs/functions/decode32.md +49 -0
- package/docs/functions/decode58.md +49 -0
- package/docs/functions/decode85.md +49 -0
- package/docs/functions/encode.md +1 -1
- package/docs/functions/encode32.md +45 -0
- package/docs/functions/encode58.md +45 -0
- package/docs/functions/encode85.md +45 -0
- package/docs/functions/hello.md +35 -3
- package/docs/functions/parseUserAgent.md +1 -1
- package/docs/functions/pojo.md +1 -1
- package/docs/interfaces/FileSystemDependencies.md +3 -3
- package/docs/interfaces/FindDirectoriesOptions.md +5 -5
- package/docs/interfaces/UserAgentInfo.md +6 -6
- package/docs/type-aliases/Base32CharsetType.md +13 -0
- package/docs/type-aliases/Base58CharsetType.md +13 -0
- package/docs/type-aliases/Base64CharsetType.md +1 -1
- package/docs/type-aliases/Base85CharsetType.md +13 -0
- package/docs/variables/Base32Charset.md +16 -0
- package/docs/variables/Base58Charset.md +16 -0
- package/docs/variables/Base64Charset.md +1 -1
- package/docs/variables/Base85Charset.md +16 -0
- package/package.json +44 -3
- package/readme.txt +12 -0
- package/src/base32.d.ts +58 -0
- package/src/base32.js +143 -0
- package/src/base32.test.d.ts +2 -0
- package/src/base32.test.js +121 -0
- package/src/base32.test.ts +144 -0
- package/src/base32.ts +169 -0
- package/src/base58.d.ts +58 -0
- package/src/base58.js +155 -0
- package/src/base58.test.d.ts +2 -0
- package/src/base58.test.js +108 -0
- package/src/base58.test.ts +128 -0
- package/src/base58.ts +177 -0
- package/src/base85.d.ts +58 -0
- package/src/base85.js +173 -0
- package/src/base85.test.d.ts +2 -0
- package/src/base85.test.js +107 -0
- package/src/base85.test.ts +125 -0
- package/src/base85.ts +199 -0
- package/src/hello.d.ts +27 -2
- package/src/hello.js +29 -4
- package/src/hello.test.js +11 -0
- package/src/hello.test.ts +13 -0
- package/src/hello.ts +29 -4
- package/src/index.d.ts +8 -2
- package/src/index.js +4 -1
- package/src/index.ts +20 -2
package/package.json
CHANGED
|
@@ -1,8 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wtasnorg/node-lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "node library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"module": "src/index.js",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"import": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./base64": {
|
|
14
|
+
"types": "./src/base64.d.ts",
|
|
15
|
+
"import": "./src/base64.js"
|
|
16
|
+
},
|
|
17
|
+
"./base58": {
|
|
18
|
+
"types": "./src/base58.d.ts",
|
|
19
|
+
"import": "./src/base58.js"
|
|
20
|
+
},
|
|
21
|
+
"./base85": {
|
|
22
|
+
"types": "./src/base85.d.ts",
|
|
23
|
+
"import": "./src/base85.js"
|
|
24
|
+
},
|
|
25
|
+
"./base32": {
|
|
26
|
+
"types": "./src/base32.d.ts",
|
|
27
|
+
"import": "./src/base32.js"
|
|
28
|
+
},
|
|
29
|
+
"./find": {
|
|
30
|
+
"types": "./src/find.d.ts",
|
|
31
|
+
"import": "./src/find.js"
|
|
32
|
+
},
|
|
33
|
+
"./user-agent": {
|
|
34
|
+
"types": "./src/user-agent.d.ts",
|
|
35
|
+
"import": "./src/user-agent.js"
|
|
36
|
+
},
|
|
37
|
+
"./pojo": {
|
|
38
|
+
"types": "./src/pojo.d.ts",
|
|
39
|
+
"import": "./src/pojo.js"
|
|
40
|
+
},
|
|
41
|
+
"./hello": {
|
|
42
|
+
"types": "./src/hello.d.ts",
|
|
43
|
+
"import": "./src/hello.js"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
6
46
|
"scripts": {
|
|
7
47
|
"build": "./node_modules/.bin/tsc --project tsconfig.json",
|
|
8
48
|
"docs": "./node_modules/.bin/typedoc",
|
|
@@ -38,5 +78,6 @@
|
|
|
38
78
|
"typedoc-plugin-markdown": "^4.9.0",
|
|
39
79
|
"typescript": "^5.9.3",
|
|
40
80
|
"typescript-eslint": "^8.48.1"
|
|
41
|
-
}
|
|
42
|
-
|
|
81
|
+
},
|
|
82
|
+
"sideEffects": false
|
|
83
|
+
}
|
package/readme.txt
CHANGED
|
@@ -12,6 +12,9 @@ A library project for nodejs. #nodejs #typescript #library
|
|
|
12
12
|
3. `createFindDirectories` as a factory for finding directories; think `find path -type d`.
|
|
13
13
|
4. `parseUserAgent` for extracting information from user-agent strings.
|
|
14
14
|
5. `encode` / `decode` for Base64 encoding/decoding with charset variants (`standard`, `urlsafe`, `imap`, `radix64`).
|
|
15
|
+
6. `encode58` / `decode58` for Base58 encoding/decoding with charset variants (`bitcoin`, `flickr`, `ripple`).
|
|
16
|
+
7. `encode85` / `decode85` for Base85 encoding/decoding with charset variants (`ascii85`, `z85`, `rfc1924`).
|
|
17
|
+
8. `encode32` / `decode32` for Base32 encoding/decoding with charset variants (`rfc4648`, `hex`, `crockford`).
|
|
15
18
|
|
|
16
19
|
## Develop
|
|
17
20
|
|
|
@@ -38,6 +41,15 @@ await hello();
|
|
|
38
41
|
// "hello from @wtasnorg/node-lib"
|
|
39
42
|
```
|
|
40
43
|
|
|
44
|
+
## Tree Shaking
|
|
45
|
+
|
|
46
|
+
Import only what you need for smaller bundles:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { encode58 } from "@wtasnorg/node-lib/base58";
|
|
50
|
+
import { encode32 } from "@wtasnorg/node-lib/base32";
|
|
51
|
+
```
|
|
52
|
+
|
|
41
53
|
## License: MIT
|
|
42
54
|
|
|
43
55
|
[MIT License file](LICENSE)
|
package/src/base32.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base32 encoding/decoding with multiple charset variants.
|
|
3
|
+
* Base32 is case-insensitive and useful for human-readable encoding (TOTP codes).
|
|
4
|
+
* @module base32
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Available Base32 charset variants.
|
|
8
|
+
* - `rfc4648`: Standard RFC 4648 alphabet (A-Z, 2-7)
|
|
9
|
+
* - `hex`: Extended hex alphabet (0-9, A-V)
|
|
10
|
+
* - `crockford`: Douglas Crockford's alphabet (excludes I, L, O, U)
|
|
11
|
+
*/
|
|
12
|
+
declare const Base32Charset: readonly ["rfc4648", "hex", "crockford"];
|
|
13
|
+
/**
|
|
14
|
+
* Base32 charset type.
|
|
15
|
+
*/
|
|
16
|
+
type Base32CharsetType = (typeof Base32Charset)[number];
|
|
17
|
+
/**
|
|
18
|
+
* Encode a string to Base32.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { encode32 } from "./base32.js";
|
|
23
|
+
*
|
|
24
|
+
* encode32("Hello");
|
|
25
|
+
* // => "JBSWY3DP"
|
|
26
|
+
*
|
|
27
|
+
* encode32("test", "hex");
|
|
28
|
+
* // => "EHMP6SS="
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param input - The string to encode.
|
|
32
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
33
|
+
* @returns The Base32 encoded string.
|
|
34
|
+
*/
|
|
35
|
+
declare function encode32(input: string, charset?: Base32CharsetType): string;
|
|
36
|
+
/**
|
|
37
|
+
* Decode a Base32 string.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { decode32 } from "./base32.js";
|
|
42
|
+
*
|
|
43
|
+
* decode32("JBSWY3DP");
|
|
44
|
+
* // => "Hello"
|
|
45
|
+
*
|
|
46
|
+
* decode32("EHMP6SS=", "hex");
|
|
47
|
+
* // => "test"
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @param input - The Base32 encoded string.
|
|
51
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
52
|
+
* @returns The decoded string.
|
|
53
|
+
* @throws Error if the input contains invalid characters.
|
|
54
|
+
*/
|
|
55
|
+
declare function decode32(input: string, charset?: Base32CharsetType): string;
|
|
56
|
+
export { encode32, decode32, Base32Charset };
|
|
57
|
+
export type { Base32CharsetType };
|
|
58
|
+
//# sourceMappingURL=base32.d.ts.map
|
package/src/base32.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base32 encoding/decoding with multiple charset variants.
|
|
3
|
+
* Base32 is case-insensitive and useful for human-readable encoding (TOTP codes).
|
|
4
|
+
* @module base32
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Available Base32 charset variants.
|
|
8
|
+
* - `rfc4648`: Standard RFC 4648 alphabet (A-Z, 2-7)
|
|
9
|
+
* - `hex`: Extended hex alphabet (0-9, A-V)
|
|
10
|
+
* - `crockford`: Douglas Crockford's alphabet (excludes I, L, O, U)
|
|
11
|
+
*/
|
|
12
|
+
const Base32Charset = ["rfc4648", "hex", "crockford"];
|
|
13
|
+
/**
|
|
14
|
+
* Charset alphabets for Base32 variants.
|
|
15
|
+
*/
|
|
16
|
+
const CHARSETS = {
|
|
17
|
+
rfc4648: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
|
|
18
|
+
hex: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
|
|
19
|
+
crockford: "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Padding character for Base32 encoding.
|
|
23
|
+
*/
|
|
24
|
+
const PAD = "=";
|
|
25
|
+
/**
|
|
26
|
+
* Build a reverse lookup table for decoding.
|
|
27
|
+
* @param alphabet - The 32-character alphabet string.
|
|
28
|
+
* @param caseInsensitive - Whether to add lowercase mappings.
|
|
29
|
+
* @returns Map of character to index.
|
|
30
|
+
*/
|
|
31
|
+
function buildDecodeTable(alphabet, caseInsensitive = true) {
|
|
32
|
+
const table = new Map();
|
|
33
|
+
for (let i = 0; i < alphabet.length; i++) {
|
|
34
|
+
const char = alphabet[i];
|
|
35
|
+
if (char !== undefined) {
|
|
36
|
+
table.set(char, i);
|
|
37
|
+
if (caseInsensitive) {
|
|
38
|
+
table.set(char.toLowerCase(), i);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return table;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Pre-built decode tables for each charset.
|
|
46
|
+
*/
|
|
47
|
+
const DECODE_TABLES = {
|
|
48
|
+
rfc4648: buildDecodeTable(CHARSETS.rfc4648),
|
|
49
|
+
hex: buildDecodeTable(CHARSETS.hex),
|
|
50
|
+
crockford: buildDecodeTable(CHARSETS.crockford)
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Encode a string to Base32.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { encode32 } from "./base32.js";
|
|
58
|
+
*
|
|
59
|
+
* encode32("Hello");
|
|
60
|
+
* // => "JBSWY3DP"
|
|
61
|
+
*
|
|
62
|
+
* encode32("test", "hex");
|
|
63
|
+
* // => "EHMP6SS="
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @param input - The string to encode.
|
|
67
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
68
|
+
* @returns The Base32 encoded string.
|
|
69
|
+
*/
|
|
70
|
+
function encode32(input, charset = "rfc4648") {
|
|
71
|
+
if (input === "") {
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
const alphabet = CHARSETS[charset];
|
|
75
|
+
const bytes = new TextEncoder().encode(input);
|
|
76
|
+
let result = "";
|
|
77
|
+
let buffer = 0;
|
|
78
|
+
let bitsInBuffer = 0;
|
|
79
|
+
for (const byte of bytes) {
|
|
80
|
+
buffer = (buffer << 8) | byte;
|
|
81
|
+
bitsInBuffer += 8;
|
|
82
|
+
while (bitsInBuffer >= 5) {
|
|
83
|
+
bitsInBuffer -= 5;
|
|
84
|
+
const index = (buffer >> bitsInBuffer) & 0x1f;
|
|
85
|
+
result += alphabet[index];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Handle remaining bits
|
|
89
|
+
if (bitsInBuffer > 0) {
|
|
90
|
+
const index = (buffer << (5 - bitsInBuffer)) & 0x1f;
|
|
91
|
+
result += alphabet[index];
|
|
92
|
+
}
|
|
93
|
+
// Add padding to make length a multiple of 8
|
|
94
|
+
while (result.length % 8 !== 0) {
|
|
95
|
+
result += PAD;
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Decode a Base32 string.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import { decode32 } from "./base32.js";
|
|
105
|
+
*
|
|
106
|
+
* decode32("JBSWY3DP");
|
|
107
|
+
* // => "Hello"
|
|
108
|
+
*
|
|
109
|
+
* decode32("EHMP6SS=", "hex");
|
|
110
|
+
* // => "test"
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @param input - The Base32 encoded string.
|
|
114
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
115
|
+
* @returns The decoded string.
|
|
116
|
+
* @throws Error if the input contains invalid characters.
|
|
117
|
+
*/
|
|
118
|
+
function decode32(input, charset = "rfc4648") {
|
|
119
|
+
if (input === "") {
|
|
120
|
+
return "";
|
|
121
|
+
}
|
|
122
|
+
const decodeTable = DECODE_TABLES[charset];
|
|
123
|
+
// Remove padding
|
|
124
|
+
const cleanInput = input.replace(/=+$/, "");
|
|
125
|
+
const bytes = [];
|
|
126
|
+
let buffer = 0;
|
|
127
|
+
let bitsInBuffer = 0;
|
|
128
|
+
for (const char of cleanInput) {
|
|
129
|
+
const value = decodeTable.get(char);
|
|
130
|
+
if (value === undefined) {
|
|
131
|
+
throw new Error(`Invalid Base32 character: ${char}`);
|
|
132
|
+
}
|
|
133
|
+
buffer = (buffer << 5) | value;
|
|
134
|
+
bitsInBuffer += 5;
|
|
135
|
+
if (bitsInBuffer >= 8) {
|
|
136
|
+
bitsInBuffer -= 8;
|
|
137
|
+
bytes.push((buffer >> bitsInBuffer) & 0xff);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return new TextDecoder().decode(new Uint8Array(bytes));
|
|
141
|
+
}
|
|
142
|
+
export { encode32, decode32, Base32Charset };
|
|
143
|
+
//# sourceMappingURL=base32.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import { encode32, decode32, Base32Charset } from "./base32.js";
|
|
4
|
+
describe("Base32 encode32", () => {
|
|
5
|
+
it("encodes empty string", () => {
|
|
6
|
+
strictEqual(encode32(""), "");
|
|
7
|
+
});
|
|
8
|
+
it("encodes 'Hello' with rfc4648 charset", () => {
|
|
9
|
+
strictEqual(encode32("Hello"), "JBSWY3DP");
|
|
10
|
+
});
|
|
11
|
+
it("encodes single character", () => {
|
|
12
|
+
strictEqual(encode32("A"), "IE======");
|
|
13
|
+
});
|
|
14
|
+
it("encodes two characters", () => {
|
|
15
|
+
strictEqual(encode32("AB"), "IFBA====");
|
|
16
|
+
});
|
|
17
|
+
it("encodes 'test'", () => {
|
|
18
|
+
strictEqual(encode32("test"), "ORSXG5A=");
|
|
19
|
+
});
|
|
20
|
+
it("encodes with hex charset", () => {
|
|
21
|
+
const rfc4648 = encode32("test", "rfc4648");
|
|
22
|
+
const hex = encode32("test", "hex");
|
|
23
|
+
strictEqual(rfc4648 !== hex, true);
|
|
24
|
+
});
|
|
25
|
+
it("encodes with crockford charset", () => {
|
|
26
|
+
const rfc4648 = encode32("test", "rfc4648");
|
|
27
|
+
const crockford = encode32("test", "crockford");
|
|
28
|
+
strictEqual(rfc4648 !== crockford, true);
|
|
29
|
+
});
|
|
30
|
+
it("encodes UTF-8 characters", () => {
|
|
31
|
+
const input = "こんにちは";
|
|
32
|
+
const encoded = encode32(input);
|
|
33
|
+
const decoded = decode32(encoded);
|
|
34
|
+
strictEqual(decoded, input);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe("Base32 decode32", () => {
|
|
38
|
+
it("decodes empty string", () => {
|
|
39
|
+
strictEqual(decode32(""), "");
|
|
40
|
+
});
|
|
41
|
+
it("decodes 'JBSWY3DP' to 'Hello'", () => {
|
|
42
|
+
strictEqual(decode32("JBSWY3DP"), "Hello");
|
|
43
|
+
});
|
|
44
|
+
it("decodes single character with padding", () => {
|
|
45
|
+
strictEqual(decode32("IE======"), "A");
|
|
46
|
+
});
|
|
47
|
+
it("decodes 'ORSXG5A=' to 'test'", () => {
|
|
48
|
+
strictEqual(decode32("ORSXG5A="), "test");
|
|
49
|
+
});
|
|
50
|
+
it("decodes without padding", () => {
|
|
51
|
+
strictEqual(decode32("JBSWY3DP"), "Hello");
|
|
52
|
+
});
|
|
53
|
+
it("decodes lowercase (case-insensitive)", () => {
|
|
54
|
+
strictEqual(decode32("jbswy3dp"), "Hello");
|
|
55
|
+
});
|
|
56
|
+
it("decodes mixed case", () => {
|
|
57
|
+
strictEqual(decode32("JbSwY3Dp"), "Hello");
|
|
58
|
+
});
|
|
59
|
+
it("throws on invalid character", () => {
|
|
60
|
+
throws(() => decode32("!!!"), /Invalid Base32 character/);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("Base32 round-trip", () => {
|
|
64
|
+
const testCases = [
|
|
65
|
+
"",
|
|
66
|
+
"a",
|
|
67
|
+
"ab",
|
|
68
|
+
"abc",
|
|
69
|
+
"abcd",
|
|
70
|
+
"abcde",
|
|
71
|
+
"Hello, World!",
|
|
72
|
+
"The quick brown fox jumps over the lazy dog",
|
|
73
|
+
"こんにちは世界",
|
|
74
|
+
"🎉🚀✨",
|
|
75
|
+
"1234567890"
|
|
76
|
+
];
|
|
77
|
+
for (const charset of Base32Charset) {
|
|
78
|
+
describe(`charset: ${charset}`, () => {
|
|
79
|
+
for (const input of testCases) {
|
|
80
|
+
it(`round-trips: ${JSON.stringify(input)}`, () => {
|
|
81
|
+
const encoded = encode32(input, charset);
|
|
82
|
+
const decoded = decode32(encoded, charset);
|
|
83
|
+
strictEqual(decoded, input);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
describe("Base32Charset", () => {
|
|
90
|
+
it("exports array with three charsets", () => {
|
|
91
|
+
strictEqual(Base32Charset.length, 3);
|
|
92
|
+
strictEqual(Base32Charset[0], "rfc4648");
|
|
93
|
+
strictEqual(Base32Charset[1], "hex");
|
|
94
|
+
strictEqual(Base32Charset[2], "crockford");
|
|
95
|
+
});
|
|
96
|
+
it("charset type works correctly", () => {
|
|
97
|
+
const cs = "hex";
|
|
98
|
+
strictEqual(encode32("test", cs), encode32("test", "hex"));
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe("Base32 RFC 4648 test vectors", () => {
|
|
102
|
+
// Test vectors from RFC 4648
|
|
103
|
+
const vectors = [
|
|
104
|
+
["", ""],
|
|
105
|
+
["f", "MY======"],
|
|
106
|
+
["fo", "MZXQ===="],
|
|
107
|
+
["foo", "MZXW6==="],
|
|
108
|
+
["foob", "MZXW6YQ="],
|
|
109
|
+
["fooba", "MZXW6YTB"],
|
|
110
|
+
["foobar", "MZXW6YTBOI======"]
|
|
111
|
+
];
|
|
112
|
+
for (const [input, expected] of vectors) {
|
|
113
|
+
it(`encodes "${input}" to "${expected}"`, () => {
|
|
114
|
+
strictEqual(encode32(input), expected);
|
|
115
|
+
});
|
|
116
|
+
it(`decodes "${expected}" to "${input}"`, () => {
|
|
117
|
+
strictEqual(decode32(expected), input);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=base32.test.js.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import { encode32, decode32, Base32Charset } from "./base32.js";
|
|
4
|
+
import type { Base32CharsetType } from "./base32.js";
|
|
5
|
+
|
|
6
|
+
describe("Base32 encode32", () => {
|
|
7
|
+
it("encodes empty string", () => {
|
|
8
|
+
strictEqual(encode32(""), "");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("encodes 'Hello' with rfc4648 charset", () => {
|
|
12
|
+
strictEqual(encode32("Hello"), "JBSWY3DP");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("encodes single character", () => {
|
|
16
|
+
strictEqual(encode32("A"), "IE======");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("encodes two characters", () => {
|
|
20
|
+
strictEqual(encode32("AB"), "IFBA====");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("encodes 'test'", () => {
|
|
24
|
+
strictEqual(encode32("test"), "ORSXG5A=");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("encodes with hex charset", () => {
|
|
28
|
+
const rfc4648 = encode32("test", "rfc4648");
|
|
29
|
+
const hex = encode32("test", "hex");
|
|
30
|
+
strictEqual(rfc4648 !== hex, true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("encodes with crockford charset", () => {
|
|
34
|
+
const rfc4648 = encode32("test", "rfc4648");
|
|
35
|
+
const crockford = encode32("test", "crockford");
|
|
36
|
+
strictEqual(rfc4648 !== crockford, true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("encodes UTF-8 characters", () => {
|
|
40
|
+
const input = "こんにちは";
|
|
41
|
+
const encoded = encode32(input);
|
|
42
|
+
const decoded = decode32(encoded);
|
|
43
|
+
strictEqual(decoded, input);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("Base32 decode32", () => {
|
|
48
|
+
it("decodes empty string", () => {
|
|
49
|
+
strictEqual(decode32(""), "");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("decodes 'JBSWY3DP' to 'Hello'", () => {
|
|
53
|
+
strictEqual(decode32("JBSWY3DP"), "Hello");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("decodes single character with padding", () => {
|
|
57
|
+
strictEqual(decode32("IE======"), "A");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("decodes 'ORSXG5A=' to 'test'", () => {
|
|
61
|
+
strictEqual(decode32("ORSXG5A="), "test");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("decodes without padding", () => {
|
|
65
|
+
strictEqual(decode32("JBSWY3DP"), "Hello");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("decodes lowercase (case-insensitive)", () => {
|
|
69
|
+
strictEqual(decode32("jbswy3dp"), "Hello");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("decodes mixed case", () => {
|
|
73
|
+
strictEqual(decode32("JbSwY3Dp"), "Hello");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("throws on invalid character", () => {
|
|
77
|
+
throws(() => decode32("!!!"), /Invalid Base32 character/);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("Base32 round-trip", () => {
|
|
82
|
+
const testCases = [
|
|
83
|
+
"",
|
|
84
|
+
"a",
|
|
85
|
+
"ab",
|
|
86
|
+
"abc",
|
|
87
|
+
"abcd",
|
|
88
|
+
"abcde",
|
|
89
|
+
"Hello, World!",
|
|
90
|
+
"The quick brown fox jumps over the lazy dog",
|
|
91
|
+
"こんにちは世界",
|
|
92
|
+
"🎉🚀✨",
|
|
93
|
+
"1234567890"
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
for (const charset of Base32Charset) {
|
|
97
|
+
describe(`charset: ${charset}`, () => {
|
|
98
|
+
for (const input of testCases) {
|
|
99
|
+
it(`round-trips: ${JSON.stringify(input)}`, () => {
|
|
100
|
+
const encoded = encode32(input, charset);
|
|
101
|
+
const decoded = decode32(encoded, charset);
|
|
102
|
+
strictEqual(decoded, input);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe("Base32Charset", () => {
|
|
110
|
+
it("exports array with three charsets", () => {
|
|
111
|
+
strictEqual(Base32Charset.length, 3);
|
|
112
|
+
strictEqual(Base32Charset[0], "rfc4648");
|
|
113
|
+
strictEqual(Base32Charset[1], "hex");
|
|
114
|
+
strictEqual(Base32Charset[2], "crockford");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("charset type works correctly", () => {
|
|
118
|
+
const cs: Base32CharsetType = "hex";
|
|
119
|
+
strictEqual(encode32("test", cs), encode32("test", "hex"));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("Base32 RFC 4648 test vectors", () => {
|
|
124
|
+
// Test vectors from RFC 4648
|
|
125
|
+
const vectors: [string, string][] = [
|
|
126
|
+
["", ""],
|
|
127
|
+
["f", "MY======"],
|
|
128
|
+
["fo", "MZXQ===="],
|
|
129
|
+
["foo", "MZXW6==="],
|
|
130
|
+
["foob", "MZXW6YQ="],
|
|
131
|
+
["fooba", "MZXW6YTB"],
|
|
132
|
+
["foobar", "MZXW6YTBOI======"]
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
for (const [input, expected] of vectors) {
|
|
136
|
+
it(`encodes "${input}" to "${expected}"`, () => {
|
|
137
|
+
strictEqual(encode32(input), expected);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it(`decodes "${expected}" to "${input}"`, () => {
|
|
141
|
+
strictEqual(decode32(expected), input);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|