feat(organization): additional fields support separate client-server projects (#3564)

This commit is contained in:
Maxwell
2025-07-24 15:14:26 +10:00
committed by GitHub
parent e11c51e210
commit a71c10d5cc
3 changed files with 61 additions and 10 deletions

View File

@@ -1645,6 +1645,23 @@ createAuthClient({
})
```
For separate client-server projects, we support providing the schema object directly:
```ts title="auth-client.ts"
const schema = {
organization: {
additionalFields: {
myCustomField: {
type: "string",
},
},
},
};
createAuthClient({
plugins: [organizationClient({ $inferAuth: {} as typeof schema })]
})
```
## Options

View File

@@ -25,7 +25,9 @@ interface OrganizationClientOptions {
teams?: {
enabled: boolean;
};
$inferAuth?: { options: { plugins: BetterAuthPlugin[] } };
$inferAuth?:
| { options: { plugins: BetterAuthPlugin[] } }
| OrganizationOptions["schema"];
}
export const organizationClient = <CO extends OrganizationClientOptions>(
@@ -90,10 +92,14 @@ export const organizationClient = <CO extends OrganizationClientOptions>(
Auth["options"]["plugins"],
"organization"
>;
type Schema = OrganizationPlugin extends { options: { schema: infer S } }
? S extends OrganizationOptions["schema"]
? S
: undefined
type Schema = CO["$inferAuth"] extends Object
? CO["$inferAuth"] extends Exclude<OrganizationOptions["schema"], undefined>
? CO["$inferAuth"]
: OrganizationPlugin extends { options: { schema: infer S } }
? S extends OrganizationOptions["schema"]
? S
: undefined
: undefined
: undefined;
return {

View File

@@ -1421,7 +1421,23 @@ describe("Additional Fields", async () => {
},
});
it("Expect team endpoints to still be defined on authClient", async () => {
const client2 = createAuthClient({
plugins: [
organizationClient({
// We also support passing the schema directly
$inferAuth: {} as typeof orgOptions.schema,
teams: { enabled: true },
}),
],
baseURL: "http://localhost:3000/api/auth",
fetchOptions: {
customFetchImpl: async (url, init) => {
return auth.handler(new Request(url, init));
},
},
});
it("Expect team endpoints to still be defined", async () => {
const teams = client.organization.createTeam;
expect(teams).toBeDefined();
expectTypeOf<typeof teams>().not.toEqualTypeOf<undefined>();
@@ -1429,16 +1445,28 @@ describe("Additional Fields", async () => {
it("Should infer the organization schema", async () => {
const org = client.organization.create;
type Params = Parameters<typeof org>[0];
const org2 = client2.organization.create;
type Params = Omit<Parameters<typeof org>[0], "fetchOptions">;
type Params2 = Omit<Parameters<typeof org2>[0], "fetchOptions">;
expect(org).toBeDefined();
expectTypeOf<Omit<Params, "fetchOptions">>().toEqualTypeOf<{
expectTypeOf<Params>().toEqualTypeOf<{
name: string;
slug: string;
logo?: string | undefined;
userId?: string | undefined;
metadata?: Record<string, any> | undefined;
someRequiredField: string;
someOptionalField?: string | undefined;
metadata?: Record<string, any> | undefined;
userId?: string | undefined;
keepCurrentActiveOrganization?: boolean | undefined;
}>();
expectTypeOf<Params2>().toEqualTypeOf<{
name: string;
slug: string;
logo?: string | undefined;
userId?: string | undefined;
metadata?: Record<string, any> | undefined;
someRequiredField: string;
someOptionalField?: string | undefined;
keepCurrentActiveOrganization?: boolean | undefined;
}>();
});