Skip to content

Commit ee3b1cc

Browse files
committed
1.2.0
1 parent b6c15c2 commit ee3b1cc

11 files changed

Lines changed: 231 additions & 156 deletions

File tree

.github/workflows/npm-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
- uses: actions/setup-node@v6
1818
with:
19-
node-version: "26"
19+
node-version: "latest"
2020
check-latest: true
2121

2222
- name: Setup pnpm

.github/workflows/test.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,14 @@ on:
1111

1212
jobs:
1313
test:
14-
strategy:
15-
matrix:
16-
node-version: ["26", "22.0.0"]
1714
runs-on: ubuntu-latest
1815

1916
steps:
2017
- uses: actions/checkout@v6
2118

2219
- uses: actions/setup-node@v6
2320
with:
24-
node-version: ${{ matrix.node-version }}
21+
node-version: "latest"
2522
check-latest: true
2623

2724
- name: Setup pnpm
@@ -30,4 +27,11 @@ jobs:
3027
version: "11"
3128

3229
- run: pnpm i
33-
- run: pnpm test
30+
31+
- run: npm test
32+
33+
- uses: actions/setup-node@v6
34+
with:
35+
node-version: "11.0.0"
36+
37+
- run: npm test

README.md

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,53 @@ npm i @bddjr/base64
1010
import base64 from "@bddjr/base64"
1111

1212
// Encode string to base64
13-
var enc = base64.encode("Hello world!")
13+
var enc = base64.encode("👋Hello!")
1414
console.log(enc)
1515

1616
// Decode base64 to string
17-
var dec = base64.decodeToString("SGVsbG8gd29ybGQh")
17+
var dec = base64.decodeToString("8J+Ri0hlbGxvIQ==")
1818
console.log(dec)
1919

2020
// Encode Uint8Array to base64
2121
var enc = base64.encode(new Uint8Array(16))
2222
console.log(enc)
2323

2424
// Decode base64 to Uint8Array
25-
var dec = base64.decode("nszai3rv7QBp+Co0SgB93g==")
25+
var dec = base64.decode("nszai3rv7QBp+/o0SgB93g==")
2626
console.log(dec)
2727

2828

29+
2930
// Encode string to base64url
30-
var enc = base64.encodeurl("Hello world!")
31+
var enc = base64.encodeurl("👋你好")
3132
console.log(enc)
3233

3334
// Decode base64url to string
34-
var dec = base64.decodeurlToString("SGVsbG8gd29ybGQh")
35+
var dec = base64.decodeurlToString("8J-Ri-S9oOWlvQ==")
3536
console.log(dec)
3637

3738
// Encode Uint8Array to base64url
3839
var enc = base64.encodeurl(new Uint8Array(16))
3940
console.log(enc)
4041

4142
// Decode base64url to Uint8Array
42-
var dec = base64.decodeurl("dBZ7uNJ0D6_EbZwZnQcEBA==")
43+
var dec = base64.decodeurl("dBZ7uNJ0D-_EbZwZnQcEBA==")
4344
console.log(dec)
45+
46+
47+
48+
// Encode to base64 omit padding characters (=)
49+
var enc = base64.encode("omit", true)
50+
console.log(enc) // b21pdA
51+
52+
// Encode to base64url omit padding characters (=)
53+
var enc = base64.encodeurl("omit", true)
54+
console.log(enc)
4455
```
4556

4657
You can also use `@bddjr/base64/make` to create an encoder/decoder with a custom alphabet:
4758

48-
```js
59+
```ts
4960
import {
5061
make_bytesToBase64,
5162
make_base64ToBytes,
@@ -55,12 +66,22 @@ import {
5566
} from "@bddjr/base64/make"
5667

5768
// base64-no-upper-case
58-
const alphabet = "!#$%&()*,-.:;<>?@[]^_`{|}~abcdefghijklmnopqrstuvwxyz0123456789+/"
59-
60-
const _bytesToBase64 = make_bytesToBase64(alphabet)
61-
const encode = make_encode(_bytesToBase64)
62-
63-
const _base64ToBytes = make_base64ToBytes(alphabet)
64-
const decode = make_decode(_base64ToBytes)
65-
const decodeToString = make_decodeToString(decode)
69+
export const alphabet = "!#$%&()*,-.:;<>?@[]^_`{|}~abcdefghijklmnopqrstuvwxyz0123456789+/"
70+
71+
export const _bytesToBase64 = /*@__PURE__*/ make_bytesToBase64(alphabet)
72+
export const encode = /*@__PURE__*/ make_encode(_bytesToBase64)
73+
74+
export const _base64ToBytes = /*@__PURE__*/ make_base64ToBytes(alphabet)
75+
export const decode = /*@__PURE__*/ _base64ToBytes
76+
export const decodeToString = /*@__PURE__*/ make_decodeToString(decode)
77+
78+
const base64custom = {
79+
alphabet: alphabet as typeof alphabet, // TypeScript
80+
_bytesToBase64,
81+
encode,
82+
_base64ToBytes,
83+
decode,
84+
decodeToString,
85+
}
86+
export default base64custom
6687
```

package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bddjr/base64",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "A high-performance Base64 and Base64url library, featuring automatic native API acceleration, and support for custom alphabets.",
55
"type": "module",
66
"main": "./dist/main.js",
@@ -12,19 +12,18 @@
1212
"./make": {
1313
"types": "./dist/make.d.ts",
1414
"default": "./dist/make.js"
15-
},
16-
"./type": {
17-
"types": "./type.d.ts"
1815
}
1916
},
17+
"engines": {
18+
"node": ">=11.0.0"
19+
},
2020
"scripts": {
2121
"build": "rimraf dist && tsc",
22-
"test": "node --run build && node scripts/test.mjs && node scripts/test-buffer.mjs && node scripts/test-fallback.mjs",
23-
"prepublishOnly": "node --run test"
22+
"test": "npm run build && node scripts/test.mjs && node scripts/test-buffer.mjs && node scripts/test-fallback.mjs",
23+
"prepublishOnly": "npm test"
2424
},
2525
"files": [
26-
"dist",
27-
"type.d.ts"
26+
"dist"
2827
],
2928
"repository": {
3029
"type": "git",
@@ -51,7 +50,7 @@
5150
},
5251
"devDependencies": {
5352
"@bddjr/rimraf": "^0.1.1",
54-
"@types/node": "^24.12.2",
53+
"@types/node": "^20.0.0",
5554
"typescript": "^6.0.3"
5655
}
5756
}

pnpm-lock.yaml

Lines changed: 5 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/test-buffer.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
console.log('test-buffer')
12
if (Uint8Array.fromBase64) {
2-
console.log('test-buffer')
33
delete Uint8Array.fromBase64
44
delete Uint8Array.prototype.toBase64
55
await import('./test.mjs')
6+
} else {
7+
console.log('skip')
8+
console.log()
69
}

scripts/test.mjs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ function test(base64, omitPadding) {
1616
*/
1717
function test2(v) {
1818
console.log('------------------')
19+
console.log('omitPadding:', omitPadding)
1920
console.log(v)
2021
const enc = base64.encode(v, omitPadding)
2122
console.log(enc)
22-
if (omitPadding && enc.endsWith('=')) process.exit(1);
23+
if (omitPadding || v.length % 3 === 0) {
24+
if (enc.endsWith('=')) process.exit(1)
25+
} else if (!enc.endsWith('='.repeat(3 - (v.length % 3)))) {
26+
process.exit(1)
27+
}
2328
var isEqual = false
2429
if (typeof v == 'string') {
2530
const dec = base64.decodeToString(enc)
@@ -42,9 +47,18 @@ function test(base64, omitPadding) {
4247
}
4348

4449
test2("Hello world!")
50+
test2("👋Hello!")
51+
test2("👋你好")
52+
test2("")
53+
test2("1")
54+
test2("12")
55+
test2("123")
56+
test2("1234")
57+
test2("12345")
4558
test2("123456")
4659
test2("1234567")
4760
test2("12345678")
61+
test2("12345678 ")
4862
test2(crypto.getRandomValues(new Uint8Array(12)))
4963
test2(crypto.getRandomValues(new Uint8Array(13)))
5064
test2(crypto.getRandomValues(new Uint8Array(14)))
@@ -61,6 +75,21 @@ for (const omitPadding of [false, true]) {
6175
}, omitPadding);
6276
}
6377

78+
console.log('------------------')
79+
console.log(base64.decode('x\t\n\f\r x'))
80+
console.log(base64.decode('xx\t\n\f\r '))
81+
82+
for (const str of ['x', 'x===', '?', 'vvvvX', 'xx==x', 'xx==xx', 'xx=']) {
83+
console.log('------------------')
84+
console.log(`decode invalid base64: ${str}`)
85+
try {
86+
const v = base64.decode(str)
87+
console.log(v)
88+
process.exit(1)
89+
} catch (e) {
90+
console.log(e)
91+
}
92+
}
6493

6594
console.log('------------------')
6695
console.log('allSuccess:', allSuccess)

src/main.ts

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
import type {
2-
Type_bytesToBase64,
3-
Type_base64ToBytes,
4-
Type_encode,
5-
Type_decode,
6-
Type_decodeToString,
7-
} from '../type.d.ts'
8-
91
import {
2+
type bytesToBase64Func,
3+
type encodeFunc,
4+
type decodeFunc,
5+
type decodeToStringFunc,
106
make_bytesToBase64,
11-
make_base64ToBytes,
12-
make_base64ToBytes_NodeJS,
13-
make_encode,
147
make_decode,
8+
make_encode,
159
make_decodeToString,
1610
} from './make.js'
1711

@@ -23,14 +17,15 @@ export const alphabeturl = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
2317
* A boolean specifying whether to omit padding characters (=) at the end of the base64 string.
2418
* The default is false.
2519
*/
26-
export const _bytesToBase64: Type_bytesToBase64 = /*@__PURE__*/ (
27-
typeof Uint8Array.prototype.toBase64 == 'function' // Node.js v25
20+
export const _bytesToBase64: bytesToBase64Func = /*@__PURE__*/ (
21+
typeof Uint8Array.prototype.toBase64 == 'function' // ES2026, Node.js v25
2822
? (bytes, omitPadding) => Uint8Array.prototype.toBase64.call(bytes, { omitPadding })
2923
: typeof Buffer == 'function' && Buffer.prototype && typeof Buffer.prototype.base64Slice == 'function'
3024
? (bytes, omitPadding) => {
3125
const out = Buffer.prototype.base64Slice.call(bytes) as string // has padding
3226
return omitPadding && out.charCodeAt(out.length - 1) === 61
33-
? out.slice(0, -1 - ((out.charCodeAt(out.length - 2) === 61) as any))
27+
//@ts-ignore
28+
? out.slice(0, -1 - (out.charCodeAt(out.length - 2) === 61))
3429
: out
3530
}
3631
: make_bytesToBase64(alphabet)
@@ -41,8 +36,8 @@ export const _bytesToBase64: Type_bytesToBase64 = /*@__PURE__*/ (
4136
* A boolean specifying whether to omit padding characters (=) at the end of the base64 string.
4237
* The default is false.
4338
*/
44-
export const _bytesToBase64url: Type_bytesToBase64 = /*@__PURE__*/ (
45-
typeof Uint8Array.prototype.toBase64 == 'function' // Node.js v25
39+
export const _bytesToBase64url: bytesToBase64Func = /*@__PURE__*/ (
40+
typeof Uint8Array.prototype.toBase64 == 'function' // ES2026, Node.js v25
4641
? (bytes, omitPadding) => Uint8Array.prototype.toBase64.call(bytes, { alphabet: 'base64url', omitPadding })
4742
: typeof Buffer == 'function' && Buffer.prototype && typeof Buffer.prototype.base64urlSlice == 'function'
4843
? (bytes, omitPadding) => {
@@ -57,22 +52,6 @@ export const _bytesToBase64url: Type_bytesToBase64 = /*@__PURE__*/ (
5752
: make_bytesToBase64(alphabeturl)
5853
)
5954

60-
export const _base64ToBytes: Type_base64ToBytes = /*@__PURE__*/ (
61-
typeof Uint8Array.fromBase64 == 'function' // Node.js v25
62-
? base64 => Uint8Array.fromBase64(base64)
63-
: typeof Buffer == 'function' && Buffer.prototype && typeof Buffer.prototype.base64Write == 'function'
64-
? make_base64ToBytes_NodeJS(Buffer.prototype.base64Write)
65-
: make_base64ToBytes(alphabet)
66-
)
67-
68-
export const _base64urlToBytes: Type_base64ToBytes = /*@__PURE__*/ (
69-
typeof Uint8Array.fromBase64 == 'function' // Node.js v25
70-
? base64 => Uint8Array.fromBase64(base64, { alphabet: 'base64url' })
71-
: typeof Buffer == 'function' && Buffer.prototype && typeof Buffer.prototype.base64urlWrite == 'function'
72-
? make_base64ToBytes_NodeJS(Buffer.prototype.base64urlWrite)
73-
: make_base64ToBytes(alphabeturl)
74-
)
75-
7655
/**
7756
* @param omitPadding
7857
* A boolean specifying whether to omit padding characters (=) at the end of the base64 string.
@@ -87,8 +66,17 @@ export const encode = /*@__PURE__*/ make_encode(_bytesToBase64)
8766
*/
8867
export const encodeurl = /*@__PURE__*/ make_encode(_bytesToBase64url)
8968

90-
export const decode = /*@__PURE__*/ make_decode(_base64ToBytes)
91-
export const decodeurl = /*@__PURE__*/ make_decode(_base64urlToBytes)
69+
export const decode: decodeFunc = /*@__PURE__*/ (
70+
typeof Uint8Array.fromBase64 == 'function' // ES2026, Node.js v25
71+
? base64 => Uint8Array.fromBase64(base64)
72+
: make_decode(alphabet)
73+
)
74+
75+
export const decodeurl: decodeFunc = /*@__PURE__*/ (
76+
typeof Uint8Array.fromBase64 == 'function' // ES2026, Node.js v25
77+
? base64 => Uint8Array.fromBase64(base64, { alphabet: 'base64url' })
78+
: make_decode(alphabeturl)
79+
)
9280

9381
export const decodeToString = /*@__PURE__*/ make_decodeToString(decode)
9482
export const decodeurlToString = /*@__PURE__*/ make_decodeToString(decodeurl)
@@ -98,8 +86,6 @@ const base64 = {
9886
alphabeturl: alphabeturl as typeof alphabeturl,
9987
_bytesToBase64,
10088
_bytesToBase64url,
101-
_base64ToBytes,
102-
_base64urlToBytes,
10389
encode,
10490
encodeurl,
10591
decode,

0 commit comments

Comments
 (0)