Skip to content

Commit ee0671f

Browse files
authored
Merge branch 'main' into rob/expo-passkeys-shared-types
2 parents 2480c9f + c6d73ad commit ee0671f

File tree

4 files changed

+61
-52
lines changed

4 files changed

+61
-52
lines changed

.changeset/deep-wombats-retire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
[Experimental] Type method returns using ClerkError

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

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { inBrowser } from '@clerk/shared/browser';
2-
import { ClerkWebAuthnError } from '@clerk/shared/error';
2+
import { type ClerkError, ClerkRuntimeError, ClerkWebAuthnError } from '@clerk/shared/error';
33
import { Poller } from '@clerk/shared/poller';
44
import type {
55
AttemptFirstFactorParams,
@@ -686,18 +686,19 @@ class SignInFuture implements SignInFutureResource {
686686
return this.resource.secondFactorVerification;
687687
}
688688

689-
async sendResetPasswordEmailCode(): Promise<{ error: unknown }> {
689+
async sendResetPasswordEmailCode(): Promise<{ error: ClerkError | null }> {
690+
if (!this.resource.id) {
691+
throw new Error('Cannot reset password without a sign in.');
692+
}
690693
return runAsyncResourceTask(this.resource, async () => {
691-
if (!this.resource.id) {
692-
throw new Error('Cannot reset password without a sign in.');
693-
}
694-
695694
const resetPasswordEmailCodeFactor = this.resource.supportedFirstFactors?.find(
696695
f => f.strategy === 'reset_password_email_code',
697696
);
698697

699698
if (!resetPasswordEmailCodeFactor) {
700-
throw new Error('Reset password email code factor not found');
699+
throw new ClerkRuntimeError('Reset password email code factor not found', {
700+
code: 'factor_not_found',
701+
});
701702
}
702703

703704
const { emailAddressId } = resetPasswordEmailCodeFactor;
@@ -708,7 +709,7 @@ class SignInFuture implements SignInFutureResource {
708709
});
709710
}
710711

711-
async verifyResetPasswordEmailCode(params: SignInFutureEmailCodeVerifyParams): Promise<{ error: unknown }> {
712+
async verifyResetPasswordEmailCode(params: SignInFutureEmailCodeVerifyParams): Promise<{ error: ClerkError | null }> {
712713
const { code } = params;
713714
return runAsyncResourceTask(this.resource, async () => {
714715
await this.resource.__internal_basePost({
@@ -718,7 +719,7 @@ class SignInFuture implements SignInFutureResource {
718719
});
719720
}
720721

721-
async submitResetPassword(params: SignInFutureResetPasswordSubmitParams): Promise<{ error: unknown }> {
722+
async submitResetPassword(params: SignInFutureResetPasswordSubmitParams): Promise<{ error: ClerkError | null }> {
722723
const { password, signOutOfOtherSessions = true } = params;
723724
return runAsyncResourceTask(this.resource, async () => {
724725
await this.resource.__internal_basePost({
@@ -736,13 +737,13 @@ class SignInFuture implements SignInFutureResource {
736737
});
737738
}
738739

739-
async create(params: SignInFutureCreateParams): Promise<{ error: unknown }> {
740+
async create(params: SignInFutureCreateParams): Promise<{ error: ClerkError | null }> {
740741
return runAsyncResourceTask(this.resource, async () => {
741742
await this._create(params);
742743
});
743744
}
744745

745-
async password(params: SignInFuturePasswordParams): Promise<{ error: unknown }> {
746+
async password(params: SignInFuturePasswordParams): Promise<{ error: ClerkError | null }> {
746747
if ([params.identifier, params.emailAddress, params.phoneNumber].filter(Boolean).length > 1) {
747748
throw new Error('Only one of identifier, emailAddress, or phoneNumber can be provided');
748749
}
@@ -763,7 +764,7 @@ class SignInFuture implements SignInFutureResource {
763764
});
764765
}
765766

766-
async sendEmailCode(params: SignInFutureEmailCodeSendParams = {}): Promise<{ error: unknown }> {
767+
async sendEmailCode(params: SignInFutureEmailCodeSendParams = {}): Promise<{ error: ClerkError | null }> {
767768
const { emailAddress, emailAddressId } = params;
768769
if (!this.resource.id && emailAddressId) {
769770
throw new Error(
@@ -784,7 +785,7 @@ class SignInFuture implements SignInFutureResource {
784785

785786
const emailCodeFactor = this.selectFirstFactor({ strategy: 'email_code', emailAddressId });
786787
if (!emailCodeFactor) {
787-
throw new Error('Email code factor not found');
788+
throw new ClerkRuntimeError('Email code factor not found', { code: 'factor_not_found' });
788789
}
789790

790791
await this.resource.__internal_basePost({
@@ -794,7 +795,7 @@ class SignInFuture implements SignInFutureResource {
794795
});
795796
}
796797

797-
async verifyEmailCode(params: SignInFutureEmailCodeVerifyParams): Promise<{ error: unknown }> {
798+
async verifyEmailCode(params: SignInFutureEmailCodeVerifyParams): Promise<{ error: ClerkError | null }> {
798799
const { code } = params;
799800
return runAsyncResourceTask(this.resource, async () => {
800801
await this.resource.__internal_basePost({
@@ -804,7 +805,7 @@ class SignInFuture implements SignInFutureResource {
804805
});
805806
}
806807

807-
async sendEmailLink(params: SignInFutureEmailLinkSendParams): Promise<{ error: unknown }> {
808+
async sendEmailLink(params: SignInFutureEmailLinkSendParams): Promise<{ error: ClerkError | null }> {
808809
const { emailAddress, verificationUrl, emailAddressId } = params;
809810
if (!this.resource.id && emailAddressId) {
810811
throw new Error(
@@ -825,7 +826,7 @@ class SignInFuture implements SignInFutureResource {
825826

826827
const emailLinkFactor = this.selectFirstFactor({ strategy: 'email_link', emailAddressId });
827828
if (!emailLinkFactor) {
828-
throw new Error('Email link factor not found');
829+
throw new ClerkRuntimeError('Email link factor not found', { code: 'factor_not_found' });
829830
}
830831

831832
let absoluteVerificationUrl = verificationUrl;
@@ -846,7 +847,7 @@ class SignInFuture implements SignInFutureResource {
846847
});
847848
}
848849

849-
async waitForEmailLinkVerification(): Promise<{ error: unknown }> {
850+
async waitForEmailLinkVerification(): Promise<{ error: ClerkError | null }> {
850851
return runAsyncResourceTask(this.resource, async () => {
851852
const { run, stop } = Poller();
852853
await new Promise((resolve, reject) => {
@@ -867,7 +868,7 @@ class SignInFuture implements SignInFutureResource {
867868
});
868869
}
869870

870-
async sendPhoneCode(params: SignInFuturePhoneCodeSendParams = {}): Promise<{ error: unknown }> {
871+
async sendPhoneCode(params: SignInFuturePhoneCodeSendParams = {}): Promise<{ error: ClerkError | null }> {
871872
const { phoneNumber, phoneNumberId, channel = 'sms' } = params;
872873
if (!this.resource.id && phoneNumberId) {
873874
throw new Error(
@@ -888,7 +889,7 @@ class SignInFuture implements SignInFutureResource {
888889

889890
const phoneCodeFactor = this.selectFirstFactor({ strategy: 'phone_code', phoneNumberId });
890891
if (!phoneCodeFactor) {
891-
throw new Error('Phone code factor not found');
892+
throw new ClerkRuntimeError('Phone code factor not found', { code: 'factor_not_found' });
892893
}
893894

894895
await this.resource.__internal_basePost({
@@ -898,7 +899,7 @@ class SignInFuture implements SignInFutureResource {
898899
});
899900
}
900901

901-
async verifyPhoneCode(params: SignInFuturePhoneCodeVerifyParams): Promise<{ error: unknown }> {
902+
async verifyPhoneCode(params: SignInFuturePhoneCodeVerifyParams): Promise<{ error: ClerkError | null }> {
902903
const { code } = params;
903904
return runAsyncResourceTask(this.resource, async () => {
904905
await this.resource.__internal_basePost({
@@ -908,7 +909,7 @@ class SignInFuture implements SignInFutureResource {
908909
});
909910
}
910911

911-
async sso(params: SignInFutureSSOParams): Promise<{ error: unknown }> {
912+
async sso(params: SignInFutureSSOParams): Promise<{ error: ClerkError | null }> {
912913
const { strategy, redirectUrl, redirectCallbackUrl, popup, oidcPrompt, enterpriseConnectionId } = params;
913914
return runAsyncResourceTask(this.resource, async () => {
914915
let actionCompleteRedirectUrl = redirectUrl;
@@ -959,7 +960,7 @@ class SignInFuture implements SignInFutureResource {
959960
});
960961
}
961962

962-
async web3(params: SignInFutureWeb3Params): Promise<{ error: unknown }> {
963+
async web3(params: SignInFutureWeb3Params): Promise<{ error: ClerkError | null }> {
963964
const { strategy } = params;
964965
const provider = strategy.replace('web3_', '').replace('_signature', '') as Web3Provider;
965966

@@ -993,7 +994,7 @@ class SignInFuture implements SignInFutureResource {
993994
f => f.strategy === strategy,
994995
) as Web3SignatureFactor;
995996
if (!web3FirstFactor) {
996-
throw new Error('Web3 first factor not found');
997+
throw new ClerkRuntimeError('Web3 first factor not found', { code: 'factor_not_found' });
997998
}
998999

9991000
await this.resource.__internal_basePost({
@@ -1003,7 +1004,7 @@ class SignInFuture implements SignInFutureResource {
10031004

10041005
const { message } = this.firstFactorVerification;
10051006
if (!message) {
1006-
throw new Error('Web3 nonce not found');
1007+
throw new ClerkRuntimeError('Web3 nonce not found', { code: 'web3_nonce_not_found' });
10071008
}
10081009

10091010
let signature: string;
@@ -1030,7 +1031,7 @@ class SignInFuture implements SignInFutureResource {
10301031
});
10311032
}
10321033

1033-
async passkey(params?: SignInFuturePasskeyParams): Promise<{ error: unknown }> {
1034+
async passkey(params?: SignInFuturePasskeyParams): Promise<{ error: ClerkError | null }> {
10341035
const { flow } = params || {};
10351036

10361037
/**
@@ -1056,7 +1057,7 @@ class SignInFuture implements SignInFutureResource {
10561057
const passKeyFactor = this.supportedFirstFactors.find(f => f.strategy === 'passkey') as PasskeyFactor;
10571058

10581059
if (!passKeyFactor) {
1059-
clerkVerifyPasskeyCalledBeforeCreate();
1060+
throw new ClerkRuntimeError('Passkey factor not found', { code: 'factor_not_found' });
10601061
}
10611062
await this.resource.__internal_basePost({
10621063
body: { strategy: 'passkey' },
@@ -1068,7 +1069,7 @@ class SignInFuture implements SignInFutureResource {
10681069
const publicKeyOptions = nonce ? convertJSONToPublicKeyRequestOptions(JSON.parse(nonce)) : null;
10691070

10701071
if (!publicKeyOptions) {
1071-
clerkMissingWebAuthnPublicKeyOptions('get');
1072+
throw new ClerkRuntimeError('Missing public key options', { code: 'missing_public_key_options' });
10721073
}
10731074

10741075
let canUseConditionalUI = false;
@@ -1088,7 +1089,7 @@ class SignInFuture implements SignInFutureResource {
10881089
});
10891090

10901091
if (!publicKeyCredential) {
1091-
throw error;
1092+
throw new ClerkWebAuthnError(error.message, { code: 'passkey_retrieval_failed' });
10921093
}
10931094

10941095
await this.resource.__internal_basePost({
@@ -1101,12 +1102,12 @@ class SignInFuture implements SignInFutureResource {
11011102
});
11021103
}
11031104

1104-
async sendMFAPhoneCode(): Promise<{ error: unknown }> {
1105+
async sendMFAPhoneCode(): Promise<{ error: ClerkError | null }> {
11051106
return runAsyncResourceTask(this.resource, async () => {
11061107
const phoneCodeFactor = this.resource.supportedSecondFactors?.find(f => f.strategy === 'phone_code');
11071108

11081109
if (!phoneCodeFactor) {
1109-
throw new Error('Phone code factor not found');
1110+
throw new ClerkRuntimeError('Phone code factor not found', { code: 'factor_not_found' });
11101111
}
11111112

11121113
const { phoneNumberId } = phoneCodeFactor;
@@ -1117,7 +1118,7 @@ class SignInFuture implements SignInFutureResource {
11171118
});
11181119
}
11191120

1120-
async verifyMFAPhoneCode(params: SignInFutureMFAPhoneCodeVerifyParams): Promise<{ error: unknown }> {
1121+
async verifyMFAPhoneCode(params: SignInFutureMFAPhoneCodeVerifyParams): Promise<{ error: ClerkError | null }> {
11211122
const { code } = params;
11221123
return runAsyncResourceTask(this.resource, async () => {
11231124
await this.resource.__internal_basePost({
@@ -1127,7 +1128,7 @@ class SignInFuture implements SignInFutureResource {
11271128
});
11281129
}
11291130

1130-
async verifyTOTP(params: SignInFutureTOTPVerifyParams): Promise<{ error: unknown }> {
1131+
async verifyTOTP(params: SignInFutureTOTPVerifyParams): Promise<{ error: ClerkError | null }> {
11311132
const { code } = params;
11321133
return runAsyncResourceTask(this.resource, async () => {
11331134
await this.resource.__internal_basePost({
@@ -1137,7 +1138,7 @@ class SignInFuture implements SignInFutureResource {
11371138
});
11381139
}
11391140

1140-
async verifyBackupCode(params: SignInFutureBackupCodeVerifyParams): Promise<{ error: unknown }> {
1141+
async verifyBackupCode(params: SignInFutureBackupCodeVerifyParams): Promise<{ error: ClerkError | null }> {
11411142
const { code } = params;
11421143
return runAsyncResourceTask(this.resource, async () => {
11431144
await this.resource.__internal_basePost({
@@ -1147,18 +1148,19 @@ class SignInFuture implements SignInFutureResource {
11471148
});
11481149
}
11491150

1150-
async ticket(params?: SignInFutureTicketParams): Promise<{ error: unknown }> {
1151+
async ticket(params?: SignInFutureTicketParams): Promise<{ error: ClerkError | null }> {
11511152
const ticket = params?.ticket ?? getClerkQueryParam('__clerk_ticket');
11521153
return this.create({ ticket: ticket ?? undefined });
11531154
}
11541155

1155-
async finalize(params?: SignInFutureFinalizeParams): Promise<{ error: unknown }> {
1156+
async finalize(params?: SignInFutureFinalizeParams): Promise<{ error: ClerkError | null }> {
11561157
const { navigate } = params || {};
1157-
return runAsyncResourceTask(this.resource, async () => {
1158-
if (!this.resource.createdSessionId) {
1159-
throw new Error('Cannot finalize sign-in without a created session.');
1160-
}
11611158

1159+
if (!this.resource.createdSessionId) {
1160+
throw new Error('Cannot finalize sign-in without a created session.');
1161+
}
1162+
1163+
return runAsyncResourceTask(this.resource, async () => {
11621164
// Reload the client to prevent an issue where the created session is not picked up.
11631165
await SignIn.clerk.client?.reload();
11641166

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ClerkRuntimeError, isCaptchaError, isClerkAPIResponseError } from '@clerk/shared/error';
1+
import { type ClerkError, ClerkRuntimeError, isCaptchaError, isClerkAPIResponseError } from '@clerk/shared/error';
22
import { Poller } from '@clerk/shared/poller';
33
import type {
44
AttemptEmailAddressVerificationParams,
@@ -707,13 +707,13 @@ class SignUpFuture implements SignUpFutureResource {
707707
await this.resource.__internal_basePost({ path: this.resource.pathRoot, body });
708708
}
709709

710-
async create(params: SignUpFutureCreateParams): Promise<{ error: unknown }> {
710+
async create(params: SignUpFutureCreateParams): Promise<{ error: ClerkError | null }> {
711711
return runAsyncResourceTask(this.resource, async () => {
712712
await this._create(params);
713713
});
714714
}
715715

716-
async update(params: SignUpFutureUpdateParams): Promise<{ error: unknown }> {
716+
async update(params: SignUpFutureUpdateParams): Promise<{ error: ClerkError | null }> {
717717
return runAsyncResourceTask(this.resource, async () => {
718718
const body: Record<string, unknown> = {
719719
...params,
@@ -724,7 +724,7 @@ class SignUpFuture implements SignUpFutureResource {
724724
});
725725
}
726726

727-
async password(params: SignUpFuturePasswordParams): Promise<{ error: unknown }> {
727+
async password(params: SignUpFuturePasswordParams): Promise<{ error: ClerkError | null }> {
728728
return runAsyncResourceTask(this.resource, async () => {
729729
const { captchaToken, captchaWidgetType, captchaError } = await this.getCaptchaToken();
730730

@@ -741,7 +741,7 @@ class SignUpFuture implements SignUpFutureResource {
741741
});
742742
}
743743

744-
async sendEmailCode(): Promise<{ error: unknown }> {
744+
async sendEmailCode(): Promise<{ error: ClerkError | null }> {
745745
return runAsyncResourceTask(this.resource, async () => {
746746
await this.resource.__internal_basePost({
747747
body: { strategy: 'email_code' },
@@ -750,7 +750,7 @@ class SignUpFuture implements SignUpFutureResource {
750750
});
751751
}
752752

753-
async verifyEmailCode(params: SignUpFutureEmailCodeVerifyParams): Promise<{ error: unknown }> {
753+
async verifyEmailCode(params: SignUpFutureEmailCodeVerifyParams): Promise<{ error: ClerkError | null }> {
754754
const { code } = params;
755755
return runAsyncResourceTask(this.resource, async () => {
756756
await this.resource.__internal_basePost({
@@ -760,7 +760,7 @@ class SignUpFuture implements SignUpFutureResource {
760760
});
761761
}
762762

763-
async sendPhoneCode(params: SignUpFuturePhoneCodeSendParams): Promise<{ error: unknown }> {
763+
async sendPhoneCode(params: SignUpFuturePhoneCodeSendParams): Promise<{ error: ClerkError | null }> {
764764
const { phoneNumber, channel = 'sms' } = params;
765765
return runAsyncResourceTask(this.resource, async () => {
766766
if (!this.resource.id) {
@@ -778,7 +778,7 @@ class SignUpFuture implements SignUpFutureResource {
778778
});
779779
}
780780

781-
async verifyPhoneCode(params: SignUpFuturePhoneCodeVerifyParams): Promise<{ error: unknown }> {
781+
async verifyPhoneCode(params: SignUpFuturePhoneCodeVerifyParams): Promise<{ error: ClerkError | null }> {
782782
const { code } = params;
783783
return runAsyncResourceTask(this.resource, async () => {
784784
await this.resource.__internal_basePost({
@@ -788,7 +788,7 @@ class SignUpFuture implements SignUpFutureResource {
788788
});
789789
}
790790

791-
async sso(params: SignUpFutureSSOParams): Promise<{ error: unknown }> {
791+
async sso(params: SignUpFutureSSOParams): Promise<{ error: ClerkError | null }> {
792792
const { strategy, redirectUrl, redirectCallbackUrl } = params;
793793
return runAsyncResourceTask(this.resource, async () => {
794794
const { captchaToken, captchaWidgetType, captchaError } = await this.getCaptchaToken();
@@ -822,7 +822,7 @@ class SignUpFuture implements SignUpFutureResource {
822822
});
823823
}
824824

825-
async web3(params: SignUpFutureWeb3Params): Promise<{ error: unknown }> {
825+
async web3(params: SignUpFutureWeb3Params): Promise<{ error: ClerkError | null }> {
826826
const { strategy, unsafeMetadata, legalAccepted } = params;
827827
const provider = strategy.replace('web3_', '').replace('_signature', '') as Web3Provider;
828828

@@ -888,12 +888,12 @@ class SignUpFuture implements SignUpFutureResource {
888888
});
889889
}
890890

891-
async ticket(params?: SignUpFutureTicketParams): Promise<{ error: unknown }> {
891+
async ticket(params?: SignUpFutureTicketParams): Promise<{ error: ClerkError | null }> {
892892
const ticket = params?.ticket ?? getClerkQueryParam('__clerk_ticket');
893893
return this.create({ ...params, ticket: ticket ?? undefined });
894894
}
895895

896-
async finalize(params?: SignUpFutureFinalizeParams): Promise<{ error: unknown }> {
896+
async finalize(params?: SignUpFutureFinalizeParams): Promise<{ error: ClerkError | null }> {
897897
const { navigate } = params || {};
898898
return runAsyncResourceTask(this.resource, async () => {
899899
if (!this.resource.createdSessionId) {

0 commit comments

Comments
 (0)