30 lines · 1.1 KB
import { createPasskey, getPasskey } from "~/lib/passkey-client";
import { useAction } from "./use-action";

type RequestOptions = Parameters<typeof getPasskey>[0];
type Assertion = Awaited<ReturnType<typeof getPasskey>>;
type CreationOptions = Parameters<typeof createPasskey>[0];
type Registration = Awaited<ReturnType<typeof createPasskey>>;

/** Server challenge, browser ceremony and server verification as one tracked action. */
export function usePasskeyAssertion<TResult>(
  start: () => Promise<RequestOptions>,
  finish: (input: { data: Assertion }) => Promise<TResult>,
) {
  return useAction(async () => finish({ data: await getPasskey(await start()) }), { invalidate: false });
}

export function usePasskeyRegistration<TResult>(
  start: (input: { data: { password: string } }) => Promise<CreationOptions>,
  finish: (input: { data: Registration & { name: string } }) => Promise<TResult>,
) {
  return useAction(async ({ name, password }: { name: string; password: string }) =>
    finish({
      data: {
        ...(await createPasskey(await start({ data: { password } }))),
        name,
      },
    }),
  );
}