From 9db0faa07484340854ded23ccf054487e11ea47a Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 29 Aug 2025 10:26:45 -0500 Subject: [PATCH 1/5] feat(clerk-js): SignIn and SignUp debug logs --- .../clerk-js/src/core/resources/SignIn.ts | 61 +++++++++++-------- .../clerk-js/src/core/resources/SignUp.ts | 19 +++++- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index c7a066494bc..9acbbdbd092 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -50,6 +50,8 @@ import type { Web3SignatureFactor, } from '@clerk/types'; +import { debugLogger } from '@/utils/debug'; + import { generateSignatureWithBase, generateSignatureWithCoinbaseWallet, @@ -115,7 +117,8 @@ export class SignIn extends BaseResource implements SignInResource { this.fromJSON(data); } - create = (params: SignInCreateParams): Promise => { + create = (params: SignInCreateParams): Promise => { + debugLogger.debug('SignIn.create', { id: this.id, strategy: 'strategy' in params ? params.strategy : undefined }); return this._basePost({ path: this.pathRoot, body: params, @@ -129,76 +132,78 @@ export class SignIn extends BaseResource implements SignInResource { }); }; - prepareFirstFactor = (factor: PrepareFirstFactorParams): Promise => { + prepareFirstFactor = (params: PrepareFirstFactorParams): Promise => { + debugLogger.debug('SignIn.prepareFirstFactor', { id: this.id, strategy: params.strategy }); let config; - switch (factor.strategy) { + switch (params.strategy) { case 'passkey': config = {} as PassKeyConfig; break; case 'email_link': config = { - emailAddressId: factor.emailAddressId, - redirectUrl: factor.redirectUrl, + emailAddressId: params.emailAddressId, + redirectUrl: params.redirectUrl, } as EmailLinkConfig; break; case 'email_code': - config = { emailAddressId: factor.emailAddressId } as EmailCodeConfig; + config = { emailAddressId: params.emailAddressId } as EmailCodeConfig; break; case 'phone_code': config = { - phoneNumberId: factor.phoneNumberId, - default: factor.default, - channel: factor.channel, + phoneNumberId: params.phoneNumberId, + default: params.default, + channel: params.channel, } as PhoneCodeConfig; break; case 'web3_metamask_signature': case 'web3_base_signature': case 'web3_coinbase_wallet_signature': case 'web3_okx_wallet_signature': - config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig; + config = { web3WalletId: params.web3WalletId } as Web3SignatureConfig; break; case 'reset_password_phone_code': - config = { phoneNumberId: factor.phoneNumberId } as ResetPasswordPhoneCodeFactorConfig; + config = { phoneNumberId: params.phoneNumberId } as ResetPasswordPhoneCodeFactorConfig; break; case 'reset_password_email_code': - config = { emailAddressId: factor.emailAddressId } as ResetPasswordEmailCodeFactorConfig; + config = { emailAddressId: params.emailAddressId } as ResetPasswordEmailCodeFactorConfig; break; case 'saml': config = { - redirectUrl: factor.redirectUrl, - actionCompleteRedirectUrl: factor.actionCompleteRedirectUrl, + redirectUrl: params.redirectUrl, + actionCompleteRedirectUrl: params.actionCompleteRedirectUrl, } as SamlConfig; break; case 'enterprise_sso': config = { - redirectUrl: factor.redirectUrl, - actionCompleteRedirectUrl: factor.actionCompleteRedirectUrl, - oidcPrompt: factor.oidcPrompt, + redirectUrl: params.redirectUrl, + actionCompleteRedirectUrl: params.actionCompleteRedirectUrl, + oidcPrompt: params.oidcPrompt, } as EnterpriseSSOConfig; break; default: - clerkInvalidStrategy('SignIn.prepareFirstFactor', factor.strategy); + clerkInvalidStrategy('SignIn.prepareFirstFactor', params.strategy); } return this._basePost({ - body: { ...config, strategy: factor.strategy }, + body: { ...config, strategy: params.strategy }, action: 'prepare_first_factor', }); }; - attemptFirstFactor = (attemptFactor: AttemptFirstFactorParams): Promise => { + attemptFirstFactor = (params: AttemptFirstFactorParams): Promise => { + debugLogger.debug('SignIn.attemptFirstFactor', { id: this.id, strategy: params.strategy }); let config; - switch (attemptFactor.strategy) { + switch (params.strategy) { case 'passkey': config = { - publicKeyCredential: JSON.stringify(serializePublicKeyCredentialAssertion(attemptFactor.publicKeyCredential)), + publicKeyCredential: JSON.stringify(serializePublicKeyCredentialAssertion(params.publicKeyCredential)), }; break; default: - config = { ...attemptFactor }; + config = { ...params }; } return this._basePost({ - body: { ...config, strategy: attemptFactor.strategy }, + body: { ...config, strategy: params.strategy }, action: 'attempt_first_factor', }); }; @@ -240,6 +245,7 @@ export class SignIn extends BaseResource implements SignInResource { }; prepareSecondFactor = (params: PrepareSecondFactorParams): Promise => { + debugLogger.debug('SignIn.prepareSecondFactor', { id: this.id, strategy: params.strategy }); return this._basePost({ body: params, action: 'prepare_second_factor', @@ -247,6 +253,7 @@ export class SignIn extends BaseResource implements SignInResource { }; attemptSecondFactor = (params: AttemptSecondFactorParams): Promise => { + debugLogger.debug('SignIn.attemptSecondFactor', { id: this.id, strategy: params.strategy }); return this._basePost({ body: params, action: 'attempt_second_factor', @@ -465,6 +472,7 @@ export class SignIn extends BaseResource implements SignInResource { protected fromJSON(data: SignInJSON | SignInJSONSnapshot | null): this { if (data) { + const previousStatus = this.status; this.id = data.id; this.status = data.status; this.supportedIdentifiers = data.supported_identifiers; @@ -475,6 +483,11 @@ export class SignIn extends BaseResource implements SignInResource { this.secondFactorVerification = new Verification(data.second_factor_verification); this.createdSessionId = data.created_session_id; this.userData = new UserData(data.user_data); + + // Log status transitions + if (previousStatus && this.status && previousStatus !== this.status) { + debugLogger.info('SignIn.status', { id: this.id, from: previousStatus, to: this.status }); + } } eventBus.emit('resource:update', { resource: this }); diff --git a/packages/clerk-js/src/core/resources/SignUp.ts b/packages/clerk-js/src/core/resources/SignUp.ts index 685f35e6c04..9a08cadb5da 100644 --- a/packages/clerk-js/src/core/resources/SignUp.ts +++ b/packages/clerk-js/src/core/resources/SignUp.ts @@ -35,6 +35,8 @@ import type { Web3Provider, } from '@clerk/types'; +import { debugLogger } from '@/utils/debug'; + import { generateSignatureWithBase, generateSignatureWithCoinbaseWallet, @@ -110,8 +112,8 @@ export class SignUp extends BaseResource implements SignUpResource { this.fromJSON(data); } - create = async (_params: SignUpCreateParams): Promise => { - let params: Record = _params; + create = async (params: SignUpCreateParams): Promise => { + debugLogger.debug('SignUp.create', { id: this.id, strategy: params.strategy }); if (!__BUILD_DISABLE_RHC__ && !this.clientBypass() && !this.shouldBypassCaptchaForAttempt(params)) { const captchaChallenge = new CaptchaChallenge(SignUp.clerk); @@ -123,7 +125,10 @@ export class SignUp extends BaseResource implements SignUpResource { } if (params.transfer && this.shouldBypassCaptchaForAttempt(params)) { - params.strategy = SignUp.clerk.client?.signIn.firstFactorVerification.strategy; + const strategy = SignUp.clerk.client?.signIn.firstFactorVerification.strategy; + if (strategy) { + params.strategy = strategy as SignUpCreateParams['strategy']; + } } return this._basePost({ @@ -133,6 +138,7 @@ export class SignUp extends BaseResource implements SignUpResource { }; prepareVerification = (params: PrepareVerificationParams): Promise => { + debugLogger.debug('SignUp.prepareVerification', { id: this.id, strategy: params.strategy }); return this._basePost({ body: params, action: 'prepare_verification', @@ -140,6 +146,7 @@ export class SignUp extends BaseResource implements SignUpResource { }; attemptVerification = (params: AttemptVerificationParams): Promise => { + debugLogger.debug('SignUp.attemptVerification', { id: this.id, strategy: params.strategy }); return this._basePost({ body: params, action: 'attempt_verification', @@ -412,6 +419,7 @@ export class SignUp extends BaseResource implements SignUpResource { protected fromJSON(data: SignUpJSON | SignUpJSONSnapshot | null): this { if (data) { + const previousStatus = this.status; this.id = data.id; this.status = data.status; this.requiredFields = data.required_fields; @@ -431,6 +439,11 @@ export class SignUp extends BaseResource implements SignUpResource { this.abandonAt = data.abandon_at; this.web3wallet = data.web3_wallet; this.legalAcceptedAt = data.legal_accepted_at; + + // Log status transitions + if (previousStatus && this.status && previousStatus !== this.status) { + debugLogger.info('SignUp.status', { id: this.id, from: previousStatus, to: this.status }); + } } eventBus.emit('resource:update', { resource: this }); From 5d64955041e0e0cc94a605f7536c4ecc8a5d1999 Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 29 Aug 2025 10:31:53 -0500 Subject: [PATCH 2/5] refactor status change logging --- .../clerk-js/src/core/resources/SignIn.ts | 21 +++++++++++------ .../clerk-js/src/core/resources/SignUp.ts | 23 ++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 9acbbdbd092..5a87a658582 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -87,7 +87,7 @@ export class SignIn extends BaseResource implements SignInResource { pathRoot = '/client/sign_ins'; id?: string; - status: SignInStatus | null = null; + private _status: SignInStatus | null = null; supportedIdentifiers: SignInIdentifier[] = []; supportedFirstFactors: SignInFirstFactor[] | null = []; supportedSecondFactors: SignInSecondFactor[] | null = null; @@ -97,6 +97,19 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); + get status(): SignInStatus | null { + return this._status; + } + + set status(value: SignInStatus | null) { + const previousStatus = this._status; + this._status = value; + + if (value && previousStatus !== value) { + debugLogger.info('SignIn.status', { id: this.id, from: previousStatus, to: value }); + } + } + /** * @experimental This experimental API is subject to change. * @@ -472,7 +485,6 @@ export class SignIn extends BaseResource implements SignInResource { protected fromJSON(data: SignInJSON | SignInJSONSnapshot | null): this { if (data) { - const previousStatus = this.status; this.id = data.id; this.status = data.status; this.supportedIdentifiers = data.supported_identifiers; @@ -483,11 +495,6 @@ export class SignIn extends BaseResource implements SignInResource { this.secondFactorVerification = new Verification(data.second_factor_verification); this.createdSessionId = data.created_session_id; this.userData = new UserData(data.user_data); - - // Log status transitions - if (previousStatus && this.status && previousStatus !== this.status) { - debugLogger.info('SignIn.status', { id: this.id, from: previousStatus, to: this.status }); - } } eventBus.emit('resource:update', { resource: this }); diff --git a/packages/clerk-js/src/core/resources/SignUp.ts b/packages/clerk-js/src/core/resources/SignUp.ts index 9a08cadb5da..cc853574fbe 100644 --- a/packages/clerk-js/src/core/resources/SignUp.ts +++ b/packages/clerk-js/src/core/resources/SignUp.ts @@ -72,10 +72,10 @@ export class SignUp extends BaseResource implements SignUpResource { pathRoot = '/client/sign_ups'; id: string | undefined; - status: SignUpStatus | null = null; + private _status: SignUpStatus | null = null; requiredFields: SignUpField[] = []; - optionalFields: SignUpField[] = []; missingFields: SignUpField[] = []; + optionalFields: SignUpField[] = []; unverifiedFields: SignUpIdentificationField[] = []; verifications: SignUpVerifications = new SignUpVerifications(null); username: string | null = null; @@ -92,6 +92,19 @@ export class SignUp extends BaseResource implements SignUpResource { abandonAt: number | null = null; legalAcceptedAt: number | null = null; + get status(): SignUpStatus | null { + return this._status; + } + + set status(value: SignUpStatus | null) { + const previousStatus = this._status; + this._status = value; + + if (value && previousStatus !== value) { + debugLogger.info('SignUp.status', { id: this.id, from: previousStatus, to: value }); + } + } + /** * @experimental This experimental API is subject to change. * @@ -419,7 +432,6 @@ export class SignUp extends BaseResource implements SignUpResource { protected fromJSON(data: SignUpJSON | SignUpJSONSnapshot | null): this { if (data) { - const previousStatus = this.status; this.id = data.id; this.status = data.status; this.requiredFields = data.required_fields; @@ -439,11 +451,6 @@ export class SignUp extends BaseResource implements SignUpResource { this.abandonAt = data.abandon_at; this.web3wallet = data.web3_wallet; this.legalAcceptedAt = data.legal_accepted_at; - - // Log status transitions - if (previousStatus && this.status && previousStatus !== this.status) { - debugLogger.info('SignUp.status', { id: this.id, from: previousStatus, to: this.status }); - } } eventBus.emit('resource:update', { resource: this }); From 24ffe103d7a0c6d82d48b1b0b0ab777237c61d36 Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 29 Aug 2025 10:35:33 -0500 Subject: [PATCH 3/5] changeset --- .changeset/thirty-knives-refuse.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thirty-knives-refuse.md diff --git a/.changeset/thirty-knives-refuse.md b/.changeset/thirty-knives-refuse.md new file mode 100644 index 00000000000..75220cd061a --- /dev/null +++ b/.changeset/thirty-knives-refuse.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Adding baseline debug logging to SignIn and SignUp components From 92029344cbbdb9aad83c88ddd78262ecf17fb92b Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 29 Aug 2025 12:23:21 -0500 Subject: [PATCH 4/5] do not mutate params --- packages/clerk-js/src/core/resources/SignUp.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignUp.ts b/packages/clerk-js/src/core/resources/SignUp.ts index cc853574fbe..4defed82a60 100644 --- a/packages/clerk-js/src/core/resources/SignUp.ts +++ b/packages/clerk-js/src/core/resources/SignUp.ts @@ -128,25 +128,27 @@ export class SignUp extends BaseResource implements SignUpResource { create = async (params: SignUpCreateParams): Promise => { debugLogger.debug('SignUp.create', { id: this.id, strategy: params.strategy }); + let finalParams = { ...params }; + if (!__BUILD_DISABLE_RHC__ && !this.clientBypass() && !this.shouldBypassCaptchaForAttempt(params)) { const captchaChallenge = new CaptchaChallenge(SignUp.clerk); const captchaParams = await captchaChallenge.managedOrInvisible({ action: 'signup' }); if (!captchaParams) { throw new ClerkRuntimeError('', { code: 'captcha_unavailable' }); } - params = { ...params, ...captchaParams }; + finalParams = { ...finalParams, ...captchaParams }; } - if (params.transfer && this.shouldBypassCaptchaForAttempt(params)) { + if (finalParams.transfer && this.shouldBypassCaptchaForAttempt(finalParams)) { const strategy = SignUp.clerk.client?.signIn.firstFactorVerification.strategy; if (strategy) { - params.strategy = strategy as SignUpCreateParams['strategy']; + finalParams = { ...finalParams, strategy: strategy as SignUpCreateParams['strategy'] }; } } return this._basePost({ path: this.pathRoot, - body: normalizeUnsafeMetadata(params), + body: normalizeUnsafeMetadata(finalParams), }); }; From 180635df5f60d03c54a55585772f67f37ea7a1e4 Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 29 Aug 2025 12:53:16 -0500 Subject: [PATCH 5/5] small refactor --- packages/clerk-js/src/core/resources/SignIn.ts | 14 +++++++++++++- packages/clerk-js/src/core/resources/SignUp.ts | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 7e4e74f25fd..68c96023628 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -100,16 +100,28 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); + /** + * The current status of the sign-in process. + * + * @returns The current sign-in status, or null if no status has been set + */ get status(): SignInStatus | null { return this._status; } + /** + * Sets the sign-in status and logs the transition at debug level. + * + * @param value - The new status to set. Can be null to clear the status. + * @remarks When setting a new status that differs from the previous one, + * a debug log entry is created showing the transition from the old to new status. + */ set status(value: SignInStatus | null) { const previousStatus = this._status; this._status = value; if (value && previousStatus !== value) { - debugLogger.info('SignIn.status', { id: this.id, from: previousStatus, to: value }); + debugLogger.debug('SignIn.status', { id: this.id, from: previousStatus, to: value }); } } diff --git a/packages/clerk-js/src/core/resources/SignUp.ts b/packages/clerk-js/src/core/resources/SignUp.ts index 4defed82a60..25fb9484639 100644 --- a/packages/clerk-js/src/core/resources/SignUp.ts +++ b/packages/clerk-js/src/core/resources/SignUp.ts @@ -92,16 +92,28 @@ export class SignUp extends BaseResource implements SignUpResource { abandonAt: number | null = null; legalAcceptedAt: number | null = null; + /** + * The current status of the sign-up process. + * + * @returns The current sign-up status, or null if no status has been set + */ get status(): SignUpStatus | null { return this._status; } + /** + * Sets the sign-up status and logs the transition at debug level. + * + * @param value - The new status to set. Can be null to clear the status. + * @remarks When setting a new status that differs from the previous one, + * a debug log entry is created showing the transition from the old to new status. + */ set status(value: SignUpStatus | null) { const previousStatus = this._status; this._status = value; if (value && previousStatus !== value) { - debugLogger.info('SignUp.status', { id: this.id, from: previousStatus, to: value }); + debugLogger.debug('SignUp.status', { id: this.id, from: previousStatus, to: value }); } }