|
| 1 | +import { isClerkAPIResponseError } from '@clerk/shared/error'; |
| 2 | +import type { Errors } from '@clerk/types'; |
1 | 3 | import { computed, signal } from 'alien-signals';
|
2 | 4 |
|
3 | 5 | import type { SignIn } from './resources/SignIn';
|
4 | 6 |
|
5 | 7 | export const signInSignal = signal<{ resource: SignIn | null }>({ resource: null });
|
6 |
| -export const signInErrorSignal = signal<{ errors: unknown }>({ errors: null }); |
| 8 | +export const signInErrorSignal = signal<{ error: unknown }>({ error: null }); |
7 | 9 |
|
8 | 10 | export const signInComputedSignal = computed(() => {
|
9 | 11 | const signIn = signInSignal().resource;
|
10 |
| - const errors = signInErrorSignal().errors; |
| 12 | + const error = signInErrorSignal().error; |
| 13 | + |
| 14 | + const errors = errorsToParsedErrors(error); |
11 | 15 |
|
12 | 16 | if (!signIn) {
|
13 |
| - return { errors: null, signIn: null }; |
| 17 | + return { errors, signIn: null }; |
14 | 18 | }
|
15 | 19 |
|
16 | 20 | return { errors, signIn: signIn.__internal_future };
|
17 | 21 | });
|
| 22 | + |
| 23 | +/** |
| 24 | + * Converts an error to a parsed errors object that reports the specific fields that the error pertains to. Will put |
| 25 | + * generic non-API errors into the global array. |
| 26 | + */ |
| 27 | +function errorsToParsedErrors(error: unknown): Errors { |
| 28 | + const parsedErrors: Errors = { |
| 29 | + fields: { |
| 30 | + firstName: null, |
| 31 | + lastName: null, |
| 32 | + emailAddress: null, |
| 33 | + identifier: null, |
| 34 | + phoneNumber: null, |
| 35 | + password: null, |
| 36 | + username: null, |
| 37 | + code: null, |
| 38 | + captcha: null, |
| 39 | + legalAccepted: null, |
| 40 | + }, |
| 41 | + raw: [], |
| 42 | + global: [], |
| 43 | + }; |
| 44 | + |
| 45 | + if (!isClerkAPIResponseError(error)) { |
| 46 | + parsedErrors.raw.push(error); |
| 47 | + parsedErrors.global.push(error); |
| 48 | + return parsedErrors; |
| 49 | + } |
| 50 | + |
| 51 | + parsedErrors.raw.push(...error.errors); |
| 52 | + |
| 53 | + error.errors.forEach(error => { |
| 54 | + if ('meta' in error && error.meta && 'paramName' in error.meta) { |
| 55 | + switch (error.meta.paramName) { |
| 56 | + case 'first_name': |
| 57 | + parsedErrors.fields.firstName = error; |
| 58 | + break; |
| 59 | + case 'last_name': |
| 60 | + parsedErrors.fields.lastName = error; |
| 61 | + break; |
| 62 | + case 'email_address': |
| 63 | + parsedErrors.fields.emailAddress = error; |
| 64 | + break; |
| 65 | + case 'identifier': |
| 66 | + parsedErrors.fields.identifier = error; |
| 67 | + break; |
| 68 | + case 'phone_number': |
| 69 | + parsedErrors.fields.phoneNumber = error; |
| 70 | + break; |
| 71 | + case 'password': |
| 72 | + parsedErrors.fields.password = error; |
| 73 | + break; |
| 74 | + case 'username': |
| 75 | + parsedErrors.fields.username = error; |
| 76 | + break; |
| 77 | + case 'code': |
| 78 | + parsedErrors.fields.code = error; |
| 79 | + break; |
| 80 | + case 'captcha': |
| 81 | + parsedErrors.fields.captcha = error; |
| 82 | + break; |
| 83 | + case 'legal_accepted': |
| 84 | + parsedErrors.fields.legalAccepted = error; |
| 85 | + break; |
| 86 | + default: |
| 87 | + parsedErrors.global.push(error); |
| 88 | + break; |
| 89 | + } |
| 90 | + } else { |
| 91 | + parsedErrors.global.push(error); |
| 92 | + } |
| 93 | + }); |
| 94 | + |
| 95 | + return parsedErrors; |
| 96 | +} |
0 commit comments