Type Issue When Extending Core Auth Schema Via Plugin

by ADMIN 54 views

Introduction

When creating custom plugins for authentication, it's common to extend the core schema to accommodate additional features. However, this can lead to type errors when using the extended schema with existing components. In this article, we'll explore a type issue that arises when extending the core auth schema via a plugin and provide a solution to resolve the error.

The Issue

Let's take a closer look at the code snippet provided:

providers.tsx

<AuthUIProvider
  authClient={authClient}
  additionalField={{
    publicKey: {
      label: "Public Key",
      placeholder: "Your public key",
      description: "Enter your public key",
      required: true,
      type: "string",
    },
  }}
  navigate={router.push}
  replace={router.replace}
  onSessionChange={() => router.refresh()}
  LinkComponent={Link}
>
  {props.children}
</AuthUIProvider>

The code snippet above attempts to add a publicKey field to the core user schema using the additionalField prop of the AuthUIProvider component. However, this results in a type error:

Type error:

Property 'publicKey' is missing in type 'Prettify<{ email: string; name: string; password: string; image?: string | undefined; callbackURL?: string | undefined; fetchOptions?: any; }>' but required in type 'Prettify<InferSignUpEmailCtx<{ plugins: ({ id: "sign-in-with-ethereum"; $InferServerPlugin: { id: "sign-in-with-ethereum"; schema: { user: { fields: { publicKey: { type: "string"; unique: true; }; }; }; };

The expected type comes from property 'authClient'

Understanding the Error

The error message indicates that the publicKey field is missing in the type of the additionalField prop, but it's required in the type of the authClient property. This suggests that the type of the authClient property is not compatible with the extended schema.

The Plugin Code

Let's take a look at the plugin code:

export const siwe = (options: SIWEPluginOptions) =>
  ({
    id: "sign-in-with-ethereum",
    schema: {
      user: {
        fields: {
          publicKey: {
            type: "string",
            unique: true,
          },
        },
      },
    },
  }) satisfies BetterAuthPlugin;

The plugin code defines a custom plugin that adds a publicKey field to the core user schema. However, the type of the authClient property is not updated to reflect the extended schema.

Resolving the Error

To resolve the error, we need to update the type of the authClient property to include the publicKey field. We can do this by creating a new type that extends the original type with the additional field:

type ExtendedAuthClient = Prettify<{
  email: string;
  name: string;
  password: string;
  image?: string | undefined;
  callbackURL?: string | undefined;
  fetchOptions?: any;
  publicKey: string;
}>;

const authClient: ExtendedAuthClient = {
  // ...
};

We can then update the AuthUIProvider component to use the new type:

<AuthUIProvider
  authClient={authClient}
  additionalField={{
    publicKey: {
      label: "Public Key",
      placeholder: "Your public key",
      description: "Enter your public key",
      required: true,
      type: "string",
    },
  }}
  navigate={router.push}
  replace={router.replace}
  onSessionChange={() => router.refresh()}
  LinkComponent={Link}
>
  {props.children}
</AuthUIProvider>

By updating the type of the authClient property, we can resolve the type error and use the extended schema with the AuthUIProvider component.

Conclusion

Introduction

In our previous article, we explored a type issue that arises when extending the core auth schema via a plugin. We identified the error and provided a solution to resolve it by updating the type of the authClient property to include the publicKey field. In this article, we'll answer some frequently asked questions related to this topic.

Q: What is the cause of the type error?

A: The type error occurs because the type of the authClient property is not updated to reflect the extended schema. When you add a new field to the core user schema, the type of the authClient property must also be updated to include the new field.

Q: How do I update the type of the authClient property?

A: To update the type of the authClient property, you can create a new type that extends the original type with the additional field. For example:

type ExtendedAuthClient = Prettify<{
  email: string;
  name: string;
  password: string;
  image?: string | undefined;
  callbackURL?: string | undefined;
  fetchOptions?: any;
  publicKey: string;
}>;

const authClient: ExtendedAuthClient = {
  // ...
};

Q: What if I have multiple plugins that extend the core schema?

A: If you have multiple plugins that extend the core schema, you'll need to update the type of the authClient property to include all the additional fields. You can do this by creating a new type that extends the original type with all the additional fields.

type ExtendedAuthClient = Prettify<{
  email: string;
  name: string;
  password: string;
  image?: string | undefined;
  callbackURL?: string | undefined;
  fetchOptions?: any;
  publicKey: string;
  anotherField: string;
  yetAnotherField: string;
}>;

const authClient: ExtendedAuthClient = {
  // ...
};

Q: Can I use a library or tool to generate the updated type?

A: Yes, you can use a library or tool to generate the updated type. For example, you can use the ts-morph library to generate the updated type based on the schema definition.

import { generateType } from 'ts-morph';

const schema = {
  // ...
};

const type = generateType(schema);

Q: What if I'm using a framework that doesn't support type extensions?

A: If you're using a framework that doesn't support type extensions, you may need to use a different approach to resolve the type error. For example, you can use a library or tool that generates the updated type based on the schema definition.

Q: Can I use a custom type guard to resolve the type error?

A: Yes, you can use a custom type guard to resolve the type error. A type guard is a function that takes an object as an argument and returns a boolean indicating whether the object conforms to a certain type. You can use a type guard to check whether the authClient property conforms to the updated type.

function isExtendedAuthClient(authClient: any): authClient is ExtendedAuthClient {
  // ...
}

if (isExtendedAuthClient(authClient)) {
  // ...
}

Conclusion

In this article, we answered some frequently asked questions related to the type issue that arises when extending the core auth schema via a plugin. We provided solutions to resolve the type error, including updating the type of the authClient property, using a library or tool to generate the updated type, and using a custom type guard. By following these steps, you can resolve similar type errors and use the extended schema with existing components.