bufferbase 1.3.0 → 2.0.0

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 (107) hide show
  1. package/README.md +99 -18
  2. package/dist/cjs/bases.d.ts +82 -0
  3. package/dist/cjs/bases.d.ts.map +1 -0
  4. package/dist/cjs/bases.js +121 -0
  5. package/dist/cjs/bases.js.map +1 -0
  6. package/dist/cjs/bufferbase.d.ts +19 -36
  7. package/dist/cjs/bufferbase.d.ts.map +1 -1
  8. package/dist/cjs/bufferbase.js +27 -111
  9. package/dist/cjs/bufferbase.js.map +1 -1
  10. package/dist/cjs/codec.d.ts +124 -0
  11. package/dist/cjs/codec.d.ts.map +1 -0
  12. package/dist/cjs/codec.js +247 -0
  13. package/dist/cjs/codec.js.map +1 -0
  14. package/dist/cjs/codecs.d.ts +71 -0
  15. package/dist/cjs/codecs.d.ts.map +1 -0
  16. package/dist/cjs/codecs.js +92 -0
  17. package/dist/cjs/codecs.js.map +1 -0
  18. package/dist/cjs/errors.d.ts +76 -0
  19. package/dist/cjs/errors.d.ts.map +1 -0
  20. package/dist/cjs/errors.js +92 -0
  21. package/dist/cjs/errors.js.map +1 -0
  22. package/dist/cjs/example.js +20 -27
  23. package/dist/cjs/example.js.map +1 -1
  24. package/dist/cjs/functions.d.ts +62 -0
  25. package/dist/cjs/functions.d.ts.map +1 -0
  26. package/dist/cjs/functions.js +93 -0
  27. package/dist/cjs/functions.js.map +1 -0
  28. package/dist/cjs/index.d.ts +8 -1
  29. package/dist/cjs/index.d.ts.map +1 -1
  30. package/dist/cjs/index.js +25 -4
  31. package/dist/cjs/index.js.map +1 -1
  32. package/dist/cjs/package.json +6 -7
  33. package/dist/cjs/types.d.ts +107 -0
  34. package/dist/cjs/types.d.ts.map +1 -0
  35. package/dist/cjs/types.js +3 -0
  36. package/dist/cjs/types.js.map +1 -0
  37. package/dist/esm/bases.d.ts +82 -0
  38. package/dist/esm/bases.d.ts.map +1 -0
  39. package/dist/esm/bases.js +116 -0
  40. package/dist/esm/bases.js.map +1 -0
  41. package/dist/esm/bufferbase.d.ts +19 -36
  42. package/dist/esm/bufferbase.d.ts.map +1 -1
  43. package/dist/esm/bufferbase.js +25 -107
  44. package/dist/esm/bufferbase.js.map +1 -1
  45. package/dist/esm/codec.d.ts +124 -0
  46. package/dist/esm/codec.d.ts.map +1 -0
  47. package/dist/esm/codec.js +242 -0
  48. package/dist/esm/codec.js.map +1 -0
  49. package/dist/esm/codecs.d.ts +71 -0
  50. package/dist/esm/codecs.d.ts.map +1 -0
  51. package/dist/esm/codecs.js +89 -0
  52. package/dist/esm/codecs.js.map +1 -0
  53. package/dist/esm/errors.d.ts +76 -0
  54. package/dist/esm/errors.d.ts.map +1 -0
  55. package/dist/esm/errors.js +86 -0
  56. package/dist/esm/errors.js.map +1 -0
  57. package/dist/esm/example.js +19 -26
  58. package/dist/esm/example.js.map +1 -1
  59. package/dist/esm/functions.d.ts +62 -0
  60. package/dist/esm/functions.d.ts.map +1 -0
  61. package/dist/esm/functions.js +87 -0
  62. package/dist/esm/functions.js.map +1 -0
  63. package/dist/esm/index.d.ts +8 -1
  64. package/dist/esm/index.d.ts.map +1 -1
  65. package/dist/esm/index.js +12 -1
  66. package/dist/esm/index.js.map +1 -1
  67. package/dist/esm/package.json +6 -7
  68. package/dist/esm/types.d.ts +107 -0
  69. package/dist/esm/types.d.ts.map +1 -0
  70. package/dist/esm/types.js +2 -0
  71. package/dist/esm/types.js.map +1 -0
  72. package/package.json +8 -9
  73. package/src/bases.ts +120 -0
  74. package/src/bufferbase.test.ts +44 -27
  75. package/src/bufferbase.ts +31 -106
  76. package/src/codec.test.ts +320 -0
  77. package/src/codec.ts +266 -0
  78. package/src/codecs.ts +118 -0
  79. package/src/errors.ts +87 -0
  80. package/src/example.ts +20 -30
  81. package/src/functions.ts +93 -0
  82. package/src/index.ts +21 -8
  83. package/src/types.ts +129 -0
  84. package/dist/cjs/bufferbase.d.mts +0 -60
  85. package/dist/cjs/bufferbase.d.mts.map +0 -1
  86. package/dist/cjs/bufferbase.mjs +0 -150
  87. package/dist/cjs/bufferbase.mjs.map +0 -1
  88. package/dist/cjs/example.d.mts +0 -2
  89. package/dist/cjs/example.d.mts.map +0 -1
  90. package/dist/cjs/example.mjs +0 -39
  91. package/dist/cjs/example.mjs.map +0 -1
  92. package/dist/cjs/index.d.mts +0 -2
  93. package/dist/cjs/index.d.mts.map +0 -1
  94. package/dist/cjs/index.mjs +0 -11
  95. package/dist/cjs/index.mjs.map +0 -1
  96. package/dist/esm/bufferbase.d.mts +0 -60
  97. package/dist/esm/bufferbase.d.mts.map +0 -1
  98. package/dist/esm/bufferbase.mjs +0 -141
  99. package/dist/esm/bufferbase.mjs.map +0 -1
  100. package/dist/esm/example.d.mts +0 -2
  101. package/dist/esm/example.d.mts.map +0 -1
  102. package/dist/esm/example.mjs +0 -37
  103. package/dist/esm/example.mjs.map +0 -1
  104. package/dist/esm/index.d.mts +0 -2
  105. package/dist/esm/index.d.mts.map +0 -1
  106. package/dist/esm/index.mjs +0 -2
  107. package/dist/esm/index.mjs.map +0 -1
package/src/codec.ts ADDED
@@ -0,0 +1,266 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import type { ICodec, DecodeOptions, BufferLike } from './types.js';
3
+ import { InvalidCharacterError, BufferSizeError } from './errors.js';
4
+
5
+ /**
6
+ * Converts a BufferLike (Buffer or Uint8Array) to a Buffer.
7
+ * @internal
8
+ */
9
+ function toBuffer(input: BufferLike): Buffer {
10
+ if (Buffer.isBuffer(input)) {
11
+ return input;
12
+ }
13
+ return Buffer.from(input);
14
+ }
15
+
16
+ /**
17
+ * Codec for encoding and decoding buffers to/from a specific base.
18
+ *
19
+ * Use pre-defined codecs from `Codecs` for common encodings,
20
+ * or create custom codecs with `createCodec()`.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { Codec, Codecs, createCodec } from 'bufferbase';
25
+ *
26
+ * // Use pre-defined codec
27
+ * const encoded = Codecs.base58.encode(Buffer.from('Hello'));
28
+ *
29
+ * // Create custom codec
30
+ * const binary = createCodec('01');
31
+ * const bits = binary.encode(Buffer.from([5])); // '101'
32
+ * ```
33
+ */
34
+ export class Codec implements ICodec {
35
+ /** Character set used for encoding. */
36
+ readonly chars: string;
37
+
38
+ /** @internal */
39
+ private readonly charToIndex: Map<string, number>;
40
+
41
+ /**
42
+ * Creates a new codec with the specified character set.
43
+ * @param chars - The character set to use for encoding/decoding
44
+ */
45
+ constructor(chars: string) {
46
+ this.chars = chars;
47
+ this.charToIndex = new Map();
48
+ for (let i = 0; i < chars.length; i++) {
49
+ this.charToIndex.set(chars[i], i);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Encodes a buffer to a base-encoded string.
55
+ *
56
+ * Leading zero bytes in the buffer are preserved as the first character
57
+ * of the encoding alphabet (e.g., '1' for Base58).
58
+ *
59
+ * @param input - The buffer or Uint8Array to encode
60
+ * @returns Base-encoded string
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const codec = Codecs.base58;
65
+ * codec.encode(Buffer.from('Hello')); // '9Ajdvzr'
66
+ * codec.encode(new Uint8Array([0, 0, 1])); // '112' (preserves leading zeros)
67
+ * ```
68
+ */
69
+ encode(input: BufferLike): string {
70
+ const buffer = toBuffer(input);
71
+ if (buffer.length === 0) {
72
+ return '';
73
+ }
74
+
75
+ const base = this.chars.length;
76
+ const result: number[] = [];
77
+
78
+ // Count leading zeros
79
+ let leadingZeros = 0;
80
+ for (const byte of buffer) {
81
+ if (byte === 0) {
82
+ leadingZeros++;
83
+ } else {
84
+ break;
85
+ }
86
+ }
87
+
88
+ // Convert to base
89
+ for (const byte of buffer) {
90
+ let carry = byte;
91
+ for (let j = 0; j < result.length; j++) {
92
+ carry += result[j] * 256;
93
+ result[j] = carry % base;
94
+ carry = Math.floor(carry / base);
95
+ }
96
+ while (carry > 0) {
97
+ result.push(carry % base);
98
+ carry = Math.floor(carry / base);
99
+ }
100
+ }
101
+
102
+ // Add leading zeros
103
+ for (let i = 0; i < leadingZeros; i++) {
104
+ result.push(0);
105
+ }
106
+
107
+ // Reverse and convert to string
108
+ return result
109
+ .reverse()
110
+ .map((index) => this.chars[index])
111
+ .join('');
112
+ }
113
+
114
+ /**
115
+ * Decodes a base-encoded string to a buffer.
116
+ *
117
+ * Leading characters that represent zero (first char of alphabet)
118
+ * are converted to leading zero bytes in the result.
119
+ *
120
+ * @param encoded - The string to decode
121
+ * @param options - Decode options
122
+ * @returns Decoded buffer
123
+ * @throws {InvalidCharacterError} If the string contains invalid characters
124
+ * @throws {BufferSizeError} If the result exceeds the specified size
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const codec = Codecs.base58;
129
+ * codec.decode('9Ajdvzr'); // Buffer('Hello')
130
+ * codec.decode('9Ajdvzr', { size: 32 }); // Pads to 32 bytes
131
+ * ```
132
+ */
133
+ decode(encoded: string, options?: DecodeOptions): Buffer {
134
+ if (encoded.length === 0) {
135
+ if (options?.size !== undefined && options.size > 0) {
136
+ return Buffer.alloc(options.size);
137
+ }
138
+ return Buffer.alloc(0);
139
+ }
140
+
141
+ const base = this.chars.length;
142
+ const zeroChar = this.chars[0];
143
+
144
+ // Count leading zeros in encoded string
145
+ let leadingZeros = 0;
146
+ for (const char of encoded) {
147
+ if (char === zeroChar) {
148
+ leadingZeros++;
149
+ } else {
150
+ break;
151
+ }
152
+ }
153
+
154
+ // Convert from base
155
+ const result: number[] = [];
156
+ for (const char of encoded) {
157
+ const value = this.charToIndex.get(char);
158
+ if (value === undefined) {
159
+ throw new InvalidCharacterError(char);
160
+ }
161
+
162
+ let carry = value;
163
+ for (let i = 0; i < result.length; i++) {
164
+ carry += result[i] * base;
165
+ result[i] = carry % 256;
166
+ carry = Math.floor(carry / 256);
167
+ }
168
+ while (carry > 0) {
169
+ result.push(carry % 256);
170
+ carry = Math.floor(carry / 256);
171
+ }
172
+ }
173
+
174
+ // Add leading zeros
175
+ for (let i = 0; i < leadingZeros; i++) {
176
+ result.push(0);
177
+ }
178
+
179
+ result.reverse();
180
+
181
+ // Handle size option
182
+ const size = options?.size;
183
+ if (size !== undefined) {
184
+ if (result.length > size) {
185
+ throw new BufferSizeError(result.length, size);
186
+ }
187
+ if (result.length < size) {
188
+ // Pad with leading zeros
189
+ const padded = new Array(size - result.length).fill(0).concat(result);
190
+ return Buffer.from(padded);
191
+ }
192
+ }
193
+
194
+ return Buffer.from(result);
195
+ }
196
+
197
+ /**
198
+ * Validates if a string contains only valid characters for this base.
199
+ *
200
+ * This is a fast check that doesn't perform full decoding.
201
+ *
202
+ * @param input - The string to validate
203
+ * @returns `true` if all characters are valid, `false` otherwise
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * Codecs.base58.validate('9Ajdvzr'); // true
208
+ * Codecs.base58.validate('0invalid'); // false ('0' not in Base58)
209
+ * ```
210
+ */
211
+ validate(input: string): boolean {
212
+ for (const char of input) {
213
+ if (!this.charToIndex.has(char)) {
214
+ return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+
220
+ /**
221
+ * Converts a string from this base to another base.
222
+ *
223
+ * Internally decodes to a buffer, then encodes with the target codec.
224
+ *
225
+ * @param target - Target codec to convert to
226
+ * @param input - The string to convert
227
+ * @returns String in the target base encoding
228
+ * @throws {InvalidCharacterError} If the input contains invalid characters
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * const base58str = '9Ajdvzr';
233
+ * const base64str = Codecs.base58.convertTo(Codecs.base64url, base58str);
234
+ * ```
235
+ */
236
+ convertTo(target: ICodec, input: string): string {
237
+ const buffer = this.decode(input);
238
+ return target.encode(buffer);
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Creates a new codec with the specified character set.
244
+ *
245
+ * Use this to create codecs for custom base encodings.
246
+ * The base is determined by the length of the character set.
247
+ *
248
+ * @param chars - The character set to use for encoding/decoding
249
+ * @returns A new Codec instance
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * import { createCodec } from 'bufferbase';
254
+ *
255
+ * // Binary codec (base 2)
256
+ * const binary = createCodec('01');
257
+ * binary.encode(Buffer.from([5])); // '101'
258
+ *
259
+ * // Octal codec (base 8)
260
+ * const octal = createCodec('01234567');
261
+ * octal.encode(Buffer.from([255])); // '377'
262
+ * ```
263
+ */
264
+ export function createCodec(chars: string): Codec {
265
+ return new Codec(chars);
266
+ }
package/src/codecs.ts ADDED
@@ -0,0 +1,118 @@
1
+ import { Codec } from './codec.js';
2
+ import { Chars } from './bases.js';
3
+
4
+ /** Decimal (base 10) codec: 0-9 */
5
+ const decimal = new Codec(Chars.Decimal);
6
+
7
+ /** Hexadecimal (base 16) codec: 0-9A-F */
8
+ const base16 = new Codec(Chars.Base16);
9
+
10
+ /** Alias for base16 */
11
+ const hex = base16;
12
+
13
+ /** RFC 4648 Base32 codec: A-Z2-7 */
14
+ const base32 = new Codec(Chars.Base32);
15
+
16
+ /** Crockford's Base32 codec: 0-9A-HJKMNP-TV-Z (no I, L, O, U) */
17
+ const base32crockford = new Codec(Chars.Base32Crockford);
18
+
19
+ /** Base36 codec: 0-9A-Z */
20
+ const base36 = new Codec(Chars.Base36);
21
+
22
+ /** Base52 codec: A-Za-z (letters only) */
23
+ const base52 = new Codec(Chars.Base52);
24
+
25
+ /** Bitcoin Base58 codec: 1-9A-HJ-NP-Za-km-z (no 0, O, I, l) */
26
+ const base58 = new Codec(Chars.Base58);
27
+
28
+ /** Standard Base64 codec: A-Za-z0-9+/ */
29
+ const base64 = new Codec(Chars.Base64);
30
+
31
+ /** URL-safe Base64 codec: A-Za-z0-9-_ */
32
+ const base64url = new Codec(Chars.Base64Url);
33
+
34
+ /** XML token Base64 codec: A-Za-z0-9._ */
35
+ const base64xml = new Codec(Chars.Base64Xml);
36
+
37
+ /** XML name Base64 codec: A-Za-z0-9_: */
38
+ const base64xmlname = new Codec(Chars.Base64XmlName);
39
+
40
+ /** ASCII85 codec */
41
+ const ascii85 = new Codec(Chars.Ascii85);
42
+
43
+ /** Base85 codec */
44
+ const base85 = new Codec(Chars.Base85);
45
+
46
+ /** ZeroMQ Z85 codec */
47
+ const z85 = new Codec(Chars.Z85);
48
+
49
+ /**
50
+ * Pre-defined codec instances for common base encodings.
51
+ *
52
+ * Use these for encoding/decoding without creating codec instances manually.
53
+ * Each codec provides `encode()`, `decode()`, `validate()`, and `convertTo()` methods.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { Codecs } from 'bufferbase';
58
+ *
59
+ * // Encode to Base58
60
+ * const encoded = Codecs.base58.encode(Buffer.from('Hello'));
61
+ *
62
+ * // Decode from Base58
63
+ * const decoded = Codecs.base58.decode(encoded);
64
+ *
65
+ * // Convert between bases
66
+ * const base64 = Codecs.base58.convertTo(Codecs.base64url, encoded);
67
+ *
68
+ * // Validate
69
+ * Codecs.base58.validate(encoded); // true
70
+ * ```
71
+ *
72
+ * Available codecs:
73
+ * - `decimal` - Base 10 (0-9)
74
+ * - `base16` / `hex` - Hexadecimal (0-9A-F)
75
+ * - `base32` - RFC 4648 Base32 (A-Z2-7)
76
+ * - `base32crockford` - Crockford's Base32
77
+ * - `base36` - Alphanumeric (0-9A-Z)
78
+ * - `base52` - Letters only (A-Za-z)
79
+ * - `base58` - Bitcoin alphabet
80
+ * - `base64` - Standard Base64
81
+ * - `base64url` - URL-safe Base64
82
+ * - `base64xml` - XML token Base64
83
+ * - `base64xmlname` - XML name Base64
84
+ * - `ascii85` - ASCII85 encoding
85
+ * - `base85` - Base85 encoding
86
+ * - `z85` - ZeroMQ Z85 encoding
87
+ */
88
+ export const Codecs = {
89
+ decimal,
90
+ base16,
91
+ hex,
92
+ base32,
93
+ base32crockford,
94
+ base36,
95
+ base52,
96
+ base58,
97
+ base64,
98
+ base64url,
99
+ base64xml,
100
+ base64xmlname,
101
+ ascii85,
102
+ base85,
103
+ z85,
104
+ } as const;
105
+
106
+ /**
107
+ * Type representing valid codec names in the `Codecs` object.
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * import { Codecs, CodecName } from 'bufferbase';
112
+ *
113
+ * function getCodec(name: CodecName) {
114
+ * return Codecs[name];
115
+ * }
116
+ * ```
117
+ */
118
+ export type CodecName = keyof typeof Codecs;
package/src/errors.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Error thrown when an invalid character is encountered during decoding.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { decode, InvalidCharacterError } from 'bufferbase';
7
+ *
8
+ * try {
9
+ * decode('invalid!', 'base58');
10
+ * } catch (e) {
11
+ * if (e instanceof InvalidCharacterError) {
12
+ * console.log(e.message); // "Invalid character found: '!'"
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export class InvalidCharacterError extends Error {
18
+ /**
19
+ * @param char - The invalid character that was encountered (optional)
20
+ */
21
+ constructor(char?: string) {
22
+ const message = char ? `Invalid character found: '${char}'` : 'Invalid character found';
23
+ super(message);
24
+ this.name = 'InvalidCharacterError';
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Error thrown when decoded buffer size exceeds the specified size.
30
+ *
31
+ * This error is thrown when using the `size` option in decode operations
32
+ * and the decoded data is larger than the specified size.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { decode, BufferSizeError } from 'bufferbase';
37
+ *
38
+ * try {
39
+ * // Trying to decode into a buffer too small
40
+ * decode('72k1xXWG59fYdzSNoA', 'base58', { size: 2 });
41
+ * } catch (e) {
42
+ * if (e instanceof BufferSizeError) {
43
+ * console.log(e.message); // "Buffer size 13 exceeds specified size 2"
44
+ * }
45
+ * }
46
+ * ```
47
+ */
48
+ export class BufferSizeError extends Error {
49
+ /**
50
+ * @param actual - The actual decoded buffer size
51
+ * @param expected - The expected (specified) buffer size
52
+ */
53
+ constructor(actual: number, expected: number) {
54
+ super(`Buffer size ${actual} exceeds specified size ${expected}`);
55
+ this.name = 'BufferSizeError';
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Error thrown when an unknown base name is provided.
61
+ *
62
+ * This error is thrown when using the function API with an invalid base name
63
+ * that is neither a known encoding name nor a valid custom character set
64
+ * (character sets must be longer than 15 characters).
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * import { encode, UnknownBaseError } from 'bufferbase';
69
+ *
70
+ * try {
71
+ * encode(Buffer.from('test'), 'invalidbase');
72
+ * } catch (e) {
73
+ * if (e instanceof UnknownBaseError) {
74
+ * console.log(e.message); // "Unknown base encoding: 'invalidbase'"
75
+ * }
76
+ * }
77
+ * ```
78
+ */
79
+ export class UnknownBaseError extends Error {
80
+ /**
81
+ * @param name - The unknown base name that was provided
82
+ */
83
+ constructor(name: string) {
84
+ super(`Unknown base encoding: '${name}'`);
85
+ this.name = 'UnknownBaseError';
86
+ }
87
+ }
package/src/example.ts CHANGED
@@ -1,28 +1,17 @@
1
- import { Chars, BufferEncoder, Converter, Validator } from './bufferbase.js';
1
+ import { Buffer } from 'node:buffer';
2
+ import { encode, decode, convert, validate, Codecs } from './index.js';
2
3
 
3
4
  // Example buffer
4
5
  const bytes = Buffer.from('Hello, World!', 'utf8');
5
6
 
6
- // Encoding buffer to Base32
7
- const encoder = new BufferEncoder(Chars.Base32Crockford);
8
- const base32encoded = encoder.encode(bytes);
9
-
10
- // Converting Base32 to Base58
11
- const converter_32to58 = new Converter(Chars.Base32Crockford, Chars.Base58);
12
- const base58encoded = converter_32to58.convert(base32encoded);
13
-
14
- // Converting Base32 to Base58
15
- const converter_58to64 = new Converter(Chars.Base58, Chars.Base64_URL_SAFE);
16
- const base64encoded = converter_58to64.convert(base58encoded);
17
-
18
- // Validating Base64
19
- const validatorB64 = new Validator(Chars.Base64_URL_SAFE);
20
- const isValidAsBase64 = validatorB64.validate(base64encoded);
21
-
22
- // Decoding Base64
23
- const decoder = new BufferEncoder(Chars.Base64_URL_SAFE);
24
- const decoded = decoder.decode(base64encoded);
7
+ // Using simple function API
8
+ const base32encoded = encode(bytes, 'base32crockford');
9
+ const base58encoded = convert(base32encoded, 'base32crockford', 'base58');
10
+ const base64encoded = convert(base58encoded, 'base58', 'base64url');
11
+ const isValidAsBase64 = validate(base64encoded, 'base64url');
12
+ const decoded = decode(base64encoded, 'base64url');
25
13
 
14
+ console.log('=== Function API ===');
26
15
  console.table({
27
16
  bytes: bytes.toString('utf8'),
28
17
  base32encoded,
@@ -31,13 +20,14 @@ console.table({
31
20
  isValidAsBase64,
32
21
  decoded: decoded.toString('utf8'),
33
22
  });
34
- // ┌─────────────────┬─────────────────────────┐
35
- // (index) │ Values │
36
- // ├─────────────────┼─────────────────────────┤
37
- // bytes │ 'Hello, World!' │
38
- // base32encoded │ '4GSBCDHQJR82QDXS6RS11'
39
- // │ base58encoded │ '72k1xXWG59fYdzSNoA' │
40
- // │ base64encoded │ 'BIZWxsbywgV29ybGQh'
41
- // │ isValidAsBase64 │ true │
42
- // │ decoded │ 'Hello, World!' │
43
- // └─────────────────┴─────────────────────────┘
23
+
24
+ // Using Codecs object
25
+ console.log('\n=== Codecs API ===');
26
+ const encoded = Codecs.base58.encode(bytes);
27
+ const converted = Codecs.base58.convertTo(Codecs.base64url, encoded);
28
+ console.table({
29
+ original: bytes.toString('utf8'),
30
+ base58: encoded,
31
+ base64url: converted,
32
+ valid: Codecs.base64url.validate(converted),
33
+ });
@@ -0,0 +1,93 @@
1
+ import type { BaseName, DecodeOptions, BufferLike } from './types.js';
2
+ import { Codec } from './codec.js';
3
+ import { resolveChars } from './bases.js';
4
+
5
+ // Cache for codec instances
6
+ const codecCache = new Map<string, Codec>();
7
+
8
+ /**
9
+ * Gets or creates a codec for the specified base.
10
+ */
11
+ function getCodec(base: BaseName | string): Codec {
12
+ const chars = resolveChars(base);
13
+ let codec = codecCache.get(chars);
14
+ if (!codec) {
15
+ codec = new Codec(chars);
16
+ codecCache.set(chars, codec);
17
+ }
18
+ return codec;
19
+ }
20
+
21
+ /**
22
+ * Encodes a buffer to a base-encoded string.
23
+ *
24
+ * @param buffer - Buffer or Uint8Array to encode
25
+ * @param base - Base name (e.g., 'base58') or custom character set
26
+ * @returns Encoded string
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Node.js Buffer
31
+ * const encoded = encode(Buffer.from('Hello'), 'base58');
32
+ *
33
+ * // Browser Uint8Array
34
+ * const encoded = encode(new Uint8Array([72, 101, 108, 108, 111]), 'base58');
35
+ * ```
36
+ */
37
+ export function encode(buffer: BufferLike, base: BaseName | string): string {
38
+ return getCodec(base).encode(buffer);
39
+ }
40
+
41
+ /**
42
+ * Decodes a base-encoded string to a buffer.
43
+ *
44
+ * @param encoded - String to decode
45
+ * @param base - Base name (e.g., 'base58') or custom character set
46
+ * @param options - Decode options (e.g., { size: 32 })
47
+ * @returns Decoded buffer
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const buffer = decode('9Ajdvz', 'base58');
52
+ * const fixedSize = decode('9Ajdvz', 'base58', { size: 32 });
53
+ * ```
54
+ */
55
+ export function decode(encoded: string, base: BaseName | string, options?: DecodeOptions): Buffer {
56
+ return getCodec(base).decode(encoded, options);
57
+ }
58
+
59
+ /**
60
+ * Converts a string from one base to another.
61
+ *
62
+ * @param input - String to convert
63
+ * @param from - Source base name or character set
64
+ * @param to - Target base name or character set
65
+ * @returns Converted string
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const base64 = convert('9Ajdvz', 'base58', 'base64url');
70
+ * ```
71
+ */
72
+ export function convert(input: string, from: BaseName | string, to: BaseName | string): string {
73
+ const fromCodec = getCodec(from);
74
+ const toCodec = getCodec(to);
75
+ return fromCodec.convertTo(toCodec, input);
76
+ }
77
+
78
+ /**
79
+ * Validates if a string contains only valid characters for the specified base.
80
+ *
81
+ * @param input - String to validate
82
+ * @param base - Base name or character set
83
+ * @returns true if valid, false otherwise
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * validate('9Ajdvz', 'base58'); // true
88
+ * validate('0Ajdvz', 'base58'); // false ('0' is not in base58)
89
+ * ```
90
+ */
91
+ export function validate(input: string, base: BaseName | string): boolean {
92
+ return getCodec(base).validate(input);
93
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,21 @@
1
- export {
2
- Chars,
3
- BufferEncoder,
4
- Converter,
5
- InvalidCharacterError,
6
- Validator,
7
- validate,
8
- } from './bufferbase.js';
1
+ // Types
2
+ export type { BaseName, DecodeOptions, ICodec, BufferLike } from './types.js';
3
+ export type { CodecName } from './codecs.js';
4
+
5
+ // Errors
6
+ export { InvalidCharacterError, BufferSizeError, UnknownBaseError } from './errors.js';
7
+
8
+ // Codec class and factory
9
+ export { Codec, createCodec } from './codec.js';
10
+
11
+ // Character sets and utilities
12
+ export { Chars, resolveChars, isBaseName } from './bases.js';
13
+
14
+ // Simple function API
15
+ export { encode, decode, convert, validate } from './functions.js';
16
+
17
+ // Pre-defined codecs (namespaced)
18
+ export { Codecs } from './codecs.js';
19
+
20
+ // Deprecated exports for backward compatibility
21
+ export { BufferEncoder, Converter, Validator } from './bufferbase.js';