diff --git a/docs/content/docs/plugins/organization.mdx b/docs/content/docs/plugins/organization.mdx index fd648fbaae..def8f64689 100644 --- a/docs/content/docs/plugins/organization.mdx +++ b/docs/content/docs/plugins/organization.mdx @@ -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 diff --git a/packages/better-auth/src/plugins/organization/client.ts b/packages/better-auth/src/plugins/organization/client.ts index c81b8a5f4f..735ae68b35 100644 --- a/packages/better-auth/src/plugins/organization/client.ts +++ b/packages/better-auth/src/plugins/organization/client.ts @@ -25,7 +25,9 @@ interface OrganizationClientOptions { teams?: { enabled: boolean; }; - $inferAuth?: { options: { plugins: BetterAuthPlugin[] } }; + $inferAuth?: + | { options: { plugins: BetterAuthPlugin[] } } + | OrganizationOptions["schema"]; } export const organizationClient = ( @@ -90,10 +92,14 @@ export const organizationClient = ( 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 + ? CO["$inferAuth"] + : OrganizationPlugin extends { options: { schema: infer S } } + ? S extends OrganizationOptions["schema"] + ? S + : undefined + : undefined : undefined; return { diff --git a/packages/better-auth/src/plugins/organization/organization.test.ts b/packages/better-auth/src/plugins/organization/organization.test.ts index 352a69fcbd..c8b510f4e6 100644 --- a/packages/better-auth/src/plugins/organization/organization.test.ts +++ b/packages/better-auth/src/plugins/organization/organization.test.ts @@ -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().not.toEqualTypeOf(); @@ -1429,16 +1445,28 @@ describe("Additional Fields", async () => { it("Should infer the organization schema", async () => { const org = client.organization.create; - type Params = Parameters[0]; + const org2 = client2.organization.create; + type Params = Omit[0], "fetchOptions">; + type Params2 = Omit[0], "fetchOptions">; expect(org).toBeDefined(); - expectTypeOf>().toEqualTypeOf<{ + expectTypeOf().toEqualTypeOf<{ name: string; slug: string; + logo?: string | undefined; + userId?: string | undefined; + metadata?: Record | undefined; someRequiredField: string; someOptionalField?: string | undefined; - metadata?: Record | undefined; - userId?: string | undefined; + keepCurrentActiveOrganization?: boolean | undefined; + }>(); + expectTypeOf().toEqualTypeOf<{ + name: string; + slug: string; logo?: string | undefined; + userId?: string | undefined; + metadata?: Record | undefined; + someRequiredField: string; + someOptionalField?: string | undefined; keepCurrentActiveOrganization?: boolean | undefined; }>(); });