Skip to content

Commit fd15b34

Browse files
committed
feat(clerk-js): User.setProfileImage accepts file a Base64 string
Sets Content type to be `application/octet-stream`
1 parent 5abe0c6 commit fd15b34

4 files changed

Lines changed: 30 additions & 8 deletions

File tree

.changeset/silver-days-sit.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Add support for dataURLs in User.setProfileImage

packages/clerk-js/src/core/fapiClient.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,26 @@ export default function createFapiClient(clerkInstance: Clerk): FapiClient {
173173
sessionId: clerkInstance.session?.id,
174174
});
175175

176+
// Initialize the headers if they're not provided.
176177
if (!requestInit.headers) {
177178
requestInit.headers = new Headers();
178179
}
179180

180-
// In case FormData is provided, we don't want to mess with the headers,
181-
// because for file uploads the header is properly set by the browser.
182-
if (method !== 'GET' && !(body instanceof FormData)) {
183-
requestInit.body = qs.stringify(body, { encoder: camelToSnakeEncoder, indices: false });
181+
// Set the default content type for non-GET requests.
182+
// Skip for FormData, because the browser knows how to construct it later on.
183+
// Skip if the content-type header has already been set, somebody intends to override it.
184+
// @ts-ignore
185+
if (method !== 'GET' && !(body instanceof FormData) && !requestInit.headers.has('content-type')) {
184186
// @ts-ignore
185-
requestInit.headers.set('Content-Type', 'application/x-www-form-urlencoded');
187+
requestInit.headers.set('content-type', 'application/x-www-form-urlencoded');
188+
}
189+
190+
// Massage the body depending on the content type if needed.
191+
// Currently, this is needed only for form-urlencoded, so that the values reach the server in the form
192+
// foo=bar&baz=bar&whatever=1
193+
// @ts-ignore
194+
if (requestInit.headers.get('content-type') === 'application/x-www-form-urlencoded') {
195+
requestInit.body = qs.stringify(body, { encoder: camelToSnakeEncoder, indices: false });
186196
}
187197

188198
const beforeRequestCallbacksResult = await runBeforeRequestCallbacks(requestInit);

packages/clerk-js/src/core/resources/Image.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ export class Image extends BaseResource implements ImageResource {
99

1010
static async create(path: string, body: any = {}): Promise<ImageResource> {
1111
let fd = body;
12-
13-
if (body['file']) {
12+
let headers;
13+
if (typeof body['file'] === 'string') {
14+
fd = body['file'];
15+
headers = new Headers({
16+
'Content-Type': 'application/octet-stream',
17+
});
18+
} else if (body['file']) {
1419
fd = new FormData();
1520
fd.append('file', body['file']);
1621
}
@@ -20,6 +25,7 @@ export class Image extends BaseResource implements ImageResource {
2025
path,
2126
method: 'POST',
2227
body: fd,
28+
headers,
2329
})
2430
)?.response as unknown as ImageJSON;
2531

packages/types/src/user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export interface UserResource extends ClerkResource {
107107
export type CreateEmailAddressParams = { email: string };
108108
export type CreatePhoneNumberParams = { phoneNumber: string };
109109
export type CreateWeb3WalletParams = { web3Wallet: string };
110-
export type SetProfileImageParams = { file: Blob | File | null };
110+
export type SetProfileImageParams = { file: Blob | File | string | null };
111111
export type CreateExternalAccountParams = {
112112
strategy: OAuthStrategy;
113113
redirectUrl?: string;

0 commit comments

Comments
 (0)