Skip to content

Commit 18e0a1a

Browse files
brunol95wobsoriano
andauthored
feat(clerk-js): add update user metadata method (#8537)
Co-authored-by: Robert Soriano <sorianorobertc@gmail.com>
1 parent 39099b6 commit 18e0a1a

4 files changed

Lines changed: 59 additions & 0 deletions

File tree

.changeset/user-update-metadata.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': minor
3+
'@clerk/shared': minor
4+
---
5+
6+
Add `user.updateMetadata()` for updating current user's metadata attributes by merging existing values with the provided parameters.

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import type {
3535
TOTPJSON,
3636
TOTPResource,
3737
UpdateMeEnterpriseConnectionParams,
38+
UpdateUserMetadataParams,
3839
UpdateUserParams,
3940
UpdateUserPasswordParams,
4041
UserJSON,
@@ -241,6 +242,13 @@ export class User extends BaseResource implements UserResource {
241242
});
242243
};
243244

245+
updateMetadata = (params: UpdateUserMetadataParams): Promise<UserResource> => {
246+
return this._basePatch({
247+
path: `${this.path()}/metadata`,
248+
body: normalizeUnsafeMetadata(params),
249+
});
250+
};
251+
244252
updatePassword = (params: UpdateUserPasswordParams): Promise<UserResource> => {
245253
return this._basePost({
246254
body: params,

packages/clerk-js/src/core/resources/__tests__/User.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,4 +727,38 @@ describe('User', () => {
727727
body: params,
728728
});
729729
});
730+
731+
it('.updateMetadata triggers a PATCH to /me/metadata with stringified unsafe_metadata', async () => {
732+
// @ts-ignore
733+
BaseResource._fetch = vi.fn().mockReturnValue(Promise.resolve({ response: {} }));
734+
735+
const user = new User({} as unknown as UserJSON);
736+
await user.updateMetadata({ unsafeMetadata: { theme: 'dark', nested: { level: 1 } } });
737+
738+
// @ts-ignore
739+
expect(BaseResource._fetch).toHaveBeenCalledWith({
740+
method: 'PATCH',
741+
path: '/me/metadata',
742+
body: {
743+
unsafeMetadata: JSON.stringify({ theme: 'dark', nested: { level: 1 } }),
744+
},
745+
});
746+
});
747+
748+
it('.updateMetadata sends an explicit null patch when a key is being removed', async () => {
749+
// @ts-ignore
750+
BaseResource._fetch = vi.fn().mockReturnValue(Promise.resolve({ response: {} }));
751+
752+
const user = new User({} as unknown as UserJSON);
753+
await user.updateMetadata({ unsafeMetadata: { theme: null as unknown as undefined } });
754+
755+
// @ts-ignore
756+
expect(BaseResource._fetch).toHaveBeenCalledWith({
757+
method: 'PATCH',
758+
path: '/me/metadata',
759+
body: {
760+
unsafeMetadata: JSON.stringify({ theme: null }),
761+
},
762+
});
763+
});
730764
});

packages/shared/src/types/user.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export interface UserResource extends ClerkResource, BillingPayerMethods {
108108
createdAt: Date | null;
109109

110110
update: (params: UpdateUserParams) => Promise<UserResource>;
111+
updateMetadata: (params: UpdateUserMetadataParams) => Promise<UserResource>;
111112
delete: () => Promise<void>;
112113
updatePassword: (params: UpdateUserPasswordParams) => Promise<UserResource>;
113114
removePassword: (params: RemoveUserPasswordParams) => Promise<UserResource>;
@@ -187,6 +188,16 @@ type UpdateUserJSON = Pick<
187188

188189
export type UpdateUserParams = Partial<SnakeToCamel<UpdateUserJSON>>;
189190

191+
/**
192+
* Parameters for {@link UserResource.updateMetadata}. Only `unsafeMetadata`
193+
* is end-user-writable on the Frontend API and the field is required: the
194+
* submitted value is deep-merged with the existing `unsafeMetadata`, and keys
195+
* at any level whose value is `null` are removed.
196+
*/
197+
export type UpdateUserMetadataParams = {
198+
unsafeMetadata: UserUnsafeMetadata;
199+
};
200+
190201
export type UpdateUserPasswordParams = {
191202
newPassword: string;
192203
currentPassword?: string;

0 commit comments

Comments
 (0)