Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-pillows-slide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': minor
---

Reuse SignIn and SignUp instances on Client when processing Client response JSON.
15 changes: 13 additions & 2 deletions packages/clerk-js/src/core/resources/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,19 @@ export class Client extends BaseResource implements ClientResource {
if (data) {
this.id = data.id;
this.sessions = (data.sessions || []).map(s => new Session(s));
this.signUp = new SignUp(data.sign_up);
this.signIn = new SignIn(data.sign_in);

if (data.sign_up && this.signUp instanceof SignUp && this.signUp.id === data.sign_up.id) {
this.signUp.__internal_updateFromJSON(data.sign_up);
} else {
this.signUp = new SignUp(data.sign_up);
}

if (data.sign_in && this.signIn instanceof SignIn && this.signIn.id === data.sign_in.id) {
this.signIn.__internal_updateFromJSON(data.sign_in);
} else {
this.signIn = new SignIn(data.sign_in);
}

this.lastActiveSessionId = data.last_active_session_id;
this.captchaBypass = data.captcha_bypass || false;
this.cookieExpiresAt = data.cookie_expires_at ? unixEpochToDate(data.cookie_expires_at) : null;
Expand Down
4 changes: 4 additions & 0 deletions packages/clerk-js/src/core/resources/SignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,10 @@ export class SignIn extends BaseResource implements SignInResource {
return this;
}

public __internal_updateFromJSON(data: SignInJSON | SignInJSONSnapshot | null): this {
return this.fromJSON(data);
}

public __internal_toSnapshot(): SignInJSONSnapshot {
return {
object: 'sign_in',
Expand Down
4 changes: 4 additions & 0 deletions packages/clerk-js/src/core/resources/SignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@ export class SignUp extends BaseResource implements SignUpResource {
return this;
}

public __internal_updateFromJSON(data: SignUpJSON | SignUpJSONSnapshot | null): this {
return this.fromJSON(data);
}

public __internal_toSnapshot(): SignUpJSONSnapshot {
return {
object: 'sign_up',
Expand Down
78 changes: 78 additions & 0 deletions packages/clerk-js/src/core/resources/__tests__/Client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,84 @@ describe('Client Singleton', () => {
});
});

it('preserves sign up and sign in identity when fromJSON receives matching ids', () => {
const user = createUser({ first_name: 'John', last_name: 'Doe', id: 'user_1' });
const session = createSession({ id: 'session_1' }, user);
const initialClientJSON: ClientJSON = {
object: 'client',
id: 'test_id',
status: 'active',
last_active_session_id: 'test_session_id',
sign_in: createSignIn({ id: 'test_sign_in_id', status: 'needs_first_factor' }, user),
sign_up: createSignUp({ id: 'test_sign_up_id', status: 'missing_requirements' }),
sessions: [session],
created_at: Date.now() - 1000,
updated_at: Date.now(),
} as any;

// @ts-expect-error We cannot mess with the singleton when tests are running in parallel
const client = new Client(initialClientJSON);
const initialSignUp = client.signUp;
const initialSignIn = client.signIn;

client.fromJSON({
...initialClientJSON,
sign_in: createSignIn(
{
id: 'test_sign_in_id',
status: 'needs_second_factor',
identifier: 'updated@example.com',
},
user,
),
sign_up: createSignUp({
id: 'test_sign_up_id',
status: 'missing_requirements',
email_address: 'updated@example.com',
}),
updated_at: Date.now() + 1000,
});

expect(client.signUp).toBe(initialSignUp);
expect(client.signIn).toBe(initialSignIn);
expect(client.signUp.emailAddress).toBe('updated@example.com');
expect(client.signIn.identifier).toBe('updated@example.com');
expect(client.signIn.status).toBe('needs_second_factor');
});

it('replaces sign up and sign in identity when fromJSON receives new ids', () => {
const user = createUser({ first_name: 'John', last_name: 'Doe', id: 'user_1' });
const session = createSession({ id: 'session_1' }, user);
const initialClientJSON: ClientJSON = {
object: 'client',
id: 'test_id',
status: 'active',
last_active_session_id: 'test_session_id',
sign_in: createSignIn({ id: 'test_sign_in_id', status: 'needs_first_factor' }, user),
sign_up: createSignUp({ id: 'test_sign_up_id', status: 'missing_requirements' }),
sessions: [session],
created_at: Date.now() - 1000,
updated_at: Date.now(),
} as any;

// @ts-expect-error We cannot mess with the singleton when tests are running in parallel
const client = new Client(initialClientJSON);
const initialSignUp = client.signUp;
const initialSignIn = client.signIn;

client.fromJSON({
...initialClientJSON,
sign_in: createSignIn({ id: 'test_sign_in_id_v2', status: 'needs_first_factor' }, user),
sign_up: createSignUp({ id: 'test_sign_up_id_v2', status: 'missing_requirements' }),
updated_at: Date.now() + 1000,
});

expect(client.signUp).not.toBe(initialSignUp);
expect(client.signIn).not.toBe(initialSignIn);
expect(client.signUp.id).toBe('test_sign_up_id_v2');
expect(client.signIn.id).toBe('test_sign_in_id_v2');
});

it('has the same initial properties', () => {
const clientJSON = {
object: 'client',
Expand Down
Loading