Skip to content

Commit 22e3c8e

Browse files
committed
🐛 Fix base64 encoding in browser
1 parent c462822 commit 22e3c8e

File tree

9 files changed

+77
-30
lines changed

9 files changed

+77
-30
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ pnpm i @coderabbitai/bitbucket
1818
### Cloud
1919

2020
```ts
21-
import { createBitbucketCloudClient } from "@coderabbitai/bitbucket"
21+
import { createBitbucketCloudClient, toBase64 } from "@coderabbitai/bitbucket"
2222
import {
2323
BITBUCKET_CLOUD_APP_PASSWORD,
2424
BITBUCKET_CLOUD_URL,
2525
BITBUCKET_CLOUD_USERNAME,
2626
} from "./env.js"
2727

28-
const basic = Buffer.from(
28+
const basic = toBase64(
2929
BITBUCKET_CLOUD_USERNAME + ":" + BITBUCKET_CLOUD_APP_PASSWORD,
30-
).toString("base64")
30+
)
3131

32-
export const cloud = createBitbucketCloudClient({
33-
baseUrl: BITBUCKET_CLOUD_URL,
32+
export const client = createBitbucketCloudClient({
33+
baseUrl: BITBUCKET_CLOUD_URL.toString(),
3434
headers: { Accept: "application/json", Authorization: `Basic ${basic}` },
3535
})
3636
```

src/base64.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test } from "vitest"
2+
import { fromBase64, toBase64 } from "./base64.js"
3+
4+
test("toBase64", ({ expect }) => {
5+
const based = toBase64("Copyright © 2024 CodeRabbit")
6+
expect(based).toBe("Q29weXJpZ2h0IMKpIDIwMjQgQ29kZVJhYmJpdA==")
7+
})
8+
9+
test("fromBase64", ({ expect }) => {
10+
const debased = fromBase64("Q29weXJpZ2h0IMKpIDIwMjQgQ29kZVJhYmJpdA==")
11+
expect(debased).toBe("Copyright © 2024 CodeRabbit")
12+
})

src/base64.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function toBase64(input: string): string {
2+
const bytes = new TextEncoder().encode(input)
3+
const string = String.fromCodePoint(...bytes)
4+
return btoa(string)
5+
}
6+
7+
export function fromBase64(base64: string): Buffer | Uint8Array | string {
8+
const string = atob(base64)
9+
const bytes = Uint8Array.from(string, v => v.codePointAt(0) ?? 0)
10+
return new TextDecoder().decode(bytes)
11+
}

src/cloud/client.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
import createClient, { type Client, type ClientOptions } from "openapi-fetch"
1+
import type { Client, ClientOptions } from "openapi-fetch"
2+
import createClient from "openapi-fetch"
23
import type { paths } from "./openapi/index.js"
34

5+
/**
6+
* Creates an `openapi-fetch` client using {@link createClient}.
7+
*
8+
* @example
9+
* export client = createBitbucketCloudClient({
10+
* baseUrl: "https://api.bitbucket.org/2.0",
11+
* headers: { Accept: "application/json", Authorization: `Basic ${basic}` },
12+
* })
13+
*/
414
export const createBitbucketCloudClient: (
515
clientOptions?: ClientOptions,
616
) => Client<paths, "application/json"> = createClient<paths, "application/json">

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from "./base64.js"
12
export * from "./cloud/index.js"
23
export * from "./server/index.js"

src/server/client.ts

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ import type { Client, ClientOptions } from "openapi-fetch"
22
import createClient from "openapi-fetch"
33
import type { paths } from "./openapi/index.js"
44

5+
/**
6+
* Creates an `openapi-fetch` client using {@link createClient}.
7+
*
8+
* @example
9+
* export const client = createBitbucketServerClient({
10+
* baseUrl: "https://example.org/rest",
11+
* headers: {
12+
* Accept: "application/json",
13+
* Authorization: `Bearer ${BITBUCKET_SERVER_TOKEN}`,
14+
* },
15+
* })
16+
*/
517
export const createBitbucketServerClient: (
618
clientOptions?: ClientOptions,
719
) => Client<paths, "application/json"> = createClient<paths, "application/json">

tests/cloud/client.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import type { Client } from "openapi-fetch"
2-
import type { paths } from "../../src/cloud/openapi/openapi-typescript.js"
3-
import { createBitbucketCloudClient } from "../../src/index.js"
1+
import { createBitbucketCloudClient, toBase64 } from "../../src/index.js"
42
import {
53
BITBUCKET_CLOUD_APP_PASSWORD,
64
BITBUCKET_CLOUD_URL,
75
BITBUCKET_CLOUD_USERNAME,
86
} from "../env.js"
97

10-
const basic = Buffer.from(
8+
const basic = toBase64(
119
BITBUCKET_CLOUD_USERNAME + ":" + BITBUCKET_CLOUD_APP_PASSWORD,
12-
).toString("base64")
10+
)
1311

14-
export const cloud: Client<paths, "application/json"> =
15-
createBitbucketCloudClient({
16-
baseUrl: BITBUCKET_CLOUD_URL,
17-
headers: { Accept: "application/json", Authorization: `Basic ${basic}` },
18-
})
12+
export const cloud = createBitbucketCloudClient({
13+
baseUrl: BITBUCKET_CLOUD_URL.toString(),
14+
headers: { Accept: "application/json", Authorization: `Basic ${basic}` },
15+
})

tests/env.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ function envString(key: string) {
1818
return value
1919
}
2020

21+
function envUrl(key: string) {
22+
const str = envString(key)
23+
try {
24+
return new URL(str)
25+
} catch (error) {
26+
throw new Error(`$${key} is not a URL: ${str}`, { cause: error })
27+
}
28+
}
29+
2130
export function isNodeEnv(value: unknown): value is NodeEnv {
2231
return Object.values<unknown>(nodeEnvs).includes(value)
2332
}
@@ -72,12 +81,10 @@ const nodeEnvs = {
7281
test: "test",
7382
} as const
7483
const parsed = loadEnv()
75-
76-
export const BITBUCKET_CLOUD_URL = envString("BITBUCKET_CLOUD_URL")
84+
export const BITBUCKET_CLOUD_URL = envUrl("BITBUCKET_CLOUD_URL")
7785
export const BITBUCKET_CLOUD_USERNAME = envString("BITBUCKET_CLOUD_USERNAME")
7886
export const BITBUCKET_CLOUD_APP_PASSWORD = envString(
7987
"BITBUCKET_CLOUD_APP_PASSWORD",
8088
)
81-
82-
export const BITBUCKET_SERVER_URL = envString("BITBUCKET_SERVER_URL")
89+
export const BITBUCKET_SERVER_URL = envUrl("BITBUCKET_SERVER_URL")
8390
export const BITBUCKET_SERVER_TOKEN = envString("BITBUCKET_SERVER_TOKEN")

tests/server/client.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import type { Client } from "openapi-fetch"
21
import { createBitbucketServerClient } from "../../src/index.js"
3-
import type { paths } from "../../src/server/openapi/openapi-typescript.js"
42
import { BITBUCKET_SERVER_TOKEN, BITBUCKET_SERVER_URL } from "../env.js"
53

6-
export const server: Client<paths, "application/json"> =
7-
createBitbucketServerClient({
8-
baseUrl: BITBUCKET_SERVER_URL,
9-
headers: {
10-
Accept: "application/json",
11-
Authorization: `Bearer ${BITBUCKET_SERVER_TOKEN}`,
12-
},
13-
})
4+
export const server = createBitbucketServerClient({
5+
baseUrl: BITBUCKET_SERVER_URL.toString(),
6+
headers: {
7+
Accept: "application/json",
8+
Authorization: `Bearer ${BITBUCKET_SERVER_TOKEN}`,
9+
},
10+
})

0 commit comments

Comments
 (0)