Skip to content

Commit

Permalink
refactor(elements): Create sign-up actors
Browse files Browse the repository at this point in the history
  • Loading branch information
tmilewski committed Oct 4, 2024
1 parent 300168c commit 4e0f396
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { FormFields } from '../../form';
export type StartAttemptInput = { clerk: LoadedClerk; fields: FormFields };
export type StartAttemptOutput = SignInResource;

export const startAttempt = fromPromise<SignInResource, StartAttemptInput>(({ input }) => {
export const startAttempt = fromPromise<StartAttemptOutput, StartAttemptInput>(({ input }) => {
const { clerk, fields } = input;

const password = fields.get('password');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { LoadedClerk, SignUpResource, Web3Strategy } from '@clerk/types';
import { fromPromise } from 'xstate';

import { ClerkElementsRuntimeError } from '~/internals/errors';

export type StartAttemptWeb3Input = { clerk: LoadedClerk; strategy: Web3Strategy };
export type StartAttemptWeb3Output = SignUpResource;

export const startAttempt = fromPromise<StartAttemptWeb3Output, StartAttemptWeb3Input>(({ input }) => {
const { clerk, strategy } = input;

if (strategy === 'web3_metamask_signature') {
return clerk.client.signUp.authenticateWithMetamask();
}

if (strategy === 'web3_coinbase_wallet_signature') {
return clerk.client.signUp.authenticateWithCoinbaseWallet();
}

throw new ClerkElementsRuntimeError(`Unsupported Web3 strategy: ${strategy}`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { LoadedClerk, SignUpResource } from '@clerk/types';
import { fromPromise } from 'xstate';

import { fieldsToSignUpParams } from '~/internals/machines/sign-up/utils/fields-to-params';

import type { FormFields } from '../../form';

export type StartAttemptParams = { strategy: 'ticket'; ticket: string } | { strategy?: never; ticket?: never };
export type StartAttemptInput = { clerk: LoadedClerk; fields: FormFields; params?: StartAttemptParams };
export type StartAttemptOutput = SignUpResource;

// TODO: Also used for continueAttempt
export const startAttempt = fromPromise<StartAttemptOutput, StartAttemptInput>(({ input }) => {
const { clerk, fields, params } = input;
return clerk.client.signUp.create({ ...fieldsToSignUpParams(fields), ...params });
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Poller } from '@clerk/shared/poller';
import type { LoadedClerk } from '@clerk/types';
import { fromCallback } from 'xstate';

import { ClerkElementsError, ClerkElementsRuntimeError } from '~/internals/errors';

export type VerificationAttemptEmailLinkInput = { clerk: LoadedClerk };
export type VerificationAttemptEmailLinkEvents = { type: 'STOP' };

export const verificationAttemptEmailLink = fromCallback<
VerificationAttemptEmailLinkEvents,
VerificationAttemptEmailLinkInput
>(({ receive, sendBack, input: { clerk } }) => {
const { run, stop } = Poller();

void run(async () =>
clerk.client.signUp
.reload()
.then(resource => {
const signInStatus = resource.status;
const verificationStatus = resource.verifications.emailAddress.status;

// Short-circuit if the sign-up resource is already complete
if (signInStatus === 'complete') {
return sendBack({ type: 'EMAIL_LINK.VERIFIED', resource });
}

switch (verificationStatus) {
case 'verified':
case 'transferable':
case 'expired': {
sendBack({ type: `EMAIL_LINK.${verificationStatus.toUpperCase()}`, resource });
break;
}
case 'failed': {
sendBack({
type: 'EMAIL_LINK.FAILED',
error: new ClerkElementsError('email-link-verification-failed', 'Email verification failed'),
resource,
});
break;
}
// case 'unverified':
default:
return;
}

stop();
})
.catch(error => {
stop();
new ClerkElementsRuntimeError(error);
}),
);

receive(event => {
if (event.type === 'STOP') {
stop();
}
});

return () => stop();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { AttemptVerificationParams, LoadedClerk, SignUpResource } from '@clerk/types';
import { fromPromise } from 'xstate';

export type VerificationAttemptInput = { clerk: LoadedClerk; params: AttemptVerificationParams };
export type VerificationAttemptOutput = SignUpResource;

export const verificationAttempt = fromPromise<VerificationAttemptOutput, VerificationAttemptInput>(({ input }) => {
const { clerk, params } = input;
return clerk.client.signUp.attemptVerification(params);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { LoadedClerk, PrepareVerificationParams, SignUpResource } from '@clerk/types';
import { fromPromise } from 'xstate';

export type VerificationPrepareInput = { clerk: LoadedClerk; params: PrepareVerificationParams };
export type VerificationPrepareOutput = SignUpResource;

export const verificationPrepare = fromPromise<VerificationPrepareOutput, VerificationPrepareInput>(({ input }) => {
const { clerk, params } = input;

if (params.strategy === 'email_link' && params.redirectUrl) {
params.redirectUrl = clerk.buildUrlWithAuth(params.redirectUrl);
}

return clerk.client.signUp.prepareVerification(params);
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { ClerkElementsRuntimeError } from '~/internals/errors';
import type { FormFields } from '~/internals/machines/form';
import { sendToLoading } from '~/internals/machines/shared';
import { fieldsToSignUpParams } from '~/internals/machines/sign-up/utils';
import { ThirdPartyMachine } from '~/internals/machines/third-party';
import { assertActorEventError } from '~/internals/machines/utils/assert';

import type { SignInRouterMachineActorRef } from './router.types';
Expand Down Expand Up @@ -45,7 +44,6 @@ export const SignUpStartMachine = setup({
throw new ClerkElementsRuntimeError(`Unsupported Web3 strategy: ${strategy}`);
},
),
thirdParty: ThirdPartyMachine,
},
actions: {
sendToNext: ({ context }) => context.parent.send({ type: 'NEXT' }),
Expand Down

0 comments on commit 4e0f396

Please sign in to comment.