diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 0f1b0c4..43e4803 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Added +- Extended `UserFrom` to support type inference from `ArkType` and `Valibot` schemas. User types are now inferred correctly for `Zod`, `ArkType`, and `Valibot` schema definitions. [#191](https://github.com/aura-stack-ts/auth/pull/191) + - Added `InferSignUp`, a utility type for inferring the sign-up payload from `createAuth().signUp.schema`. This type can be reused as the second generic parameter of `createAuthClient()` to ensure consistent typing between server and client authentication configurations. [#190](https://github.com/aura-stack-ts/auth/pull/190) - Added a `signUp` client function accessible via `createAuthClient`, allowing interaction with the mounted `POST /signUp` endpoint. [#184](https://github.com/aura-stack-ts/auth/pull/184) diff --git a/packages/core/src/@types/utility.ts b/packages/core/src/@types/utility.ts index ae204b7..92a1bd3 100644 --- a/packages/core/src/@types/utility.ts +++ b/packages/core/src/@types/utility.ts @@ -3,7 +3,7 @@ import type { TProperties, TObject, TSchema } from "typebox" import type { AuthInstance } from "@/@types/config.ts" import type { Session, User } from "@/@types/session.ts" import type { ZodObject, ZodRawShape, ZodTypeAny, infer as Infer, ZodOptional } from "zod/v4" -import type { Identities, IsArkType, IsZod, UserShapeTypeBox, UserShapeValibot } from "@/shared/identity.ts" +import type { Identities, IsArkType, IsZod, SchemaTypes, UserShapeTypeBox, UserShapeValibot } from "@/shared/identity.ts" import type { ObjectSchema, BaseSchema, AnySchema as AnyValibotSchema, ObjectEntries, InferOutput } from "valibot" import type { InferSchema } from "@aura-stack/router" @@ -161,7 +161,7 @@ export type InferZodShape = T["shape"] * * type User = UserFrom */ -export type UserFrom = Prettify>> +export type UserFrom = Prettify>> /** * Infers the session type from a Zod identity schema. @@ -174,7 +174,7 @@ export type UserFrom = Prettify */ -export type SessionFrom = Wrap>>> +export type SessionFrom = Wrap, User>>> /** * Infers the sign-up data type from an {@link AuthInstance} config's `signUp.schema`. It supports diff --git a/packages/core/test/client/client.test-d.ts b/packages/core/test/client/client.test-d.ts index db808ae..942d663 100644 --- a/packages/core/test/client/client.test-d.ts +++ b/packages/core/test/client/client.test-d.ts @@ -17,6 +17,7 @@ import type { UpdateSessionReturn, InferUser, InferSignUp, + UserFrom, } from "@/@types/index.ts" import { createAuth } from "@/createAuth.ts" import { z } from "zod/v4" @@ -46,26 +47,30 @@ describe("Client Types", () => { }) test("with custom zod identity schema", () => { + const schema = UserIdentity.extend({ + isAdmin: z.boolean(), + role: z.enum(["admin", "user"]), + }) + const auth = createAuth({ oauth: [], identity: { - schema: UserIdentity.extend({ - isAdmin: z.boolean(), - role: z.enum(["admin", "user"]), - }), + schema, }, }) - type User = InferUser - - expectTypeOf().toEqualTypeOf<{ + type Expected = { sub: string name?: string | null | undefined image?: string | null | undefined email?: string | null | undefined isAdmin: boolean role: "admin" | "user" - }>() + } + type User = InferUser + + expectTypeOf().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() const authClient = createAuthClient({}) expectTypeOf(authClient).toEqualTypeOf<{ @@ -86,27 +91,31 @@ describe("Client Types", () => { }) test("with custom valibot identity schema", () => { + const schema = valibot.object({ + ...UserIdentityValibot.entries, + isAdmin: valibot.boolean(), + role: valibot.union([valibot.literal("admin"), valibot.literal("user")]), + }) + const auth = createAuth({ oauth: [], identity: { - schema: valibot.object({ - ...UserIdentityValibot.entries, - isAdmin: valibot.boolean(), - role: valibot.union([valibot.literal("admin"), valibot.literal("user")]), - }), + schema, }, }) - type User = InferUser - - expectTypeOf().toEqualTypeOf<{ + type Expected = { sub: string name?: string | null | undefined image?: string | null | undefined email?: string | null | undefined isAdmin: boolean role: "admin" | "user" - }>() + } + type User = InferUser + + expectTypeOf().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() const authClient = createAuthClient({}) expectTypeOf(authClient).toEqualTypeOf<{ @@ -127,26 +136,30 @@ describe("Client Types", () => { }) test("with custom arktype identity schema", () => { + const schema = UserIdentityArkType.and({ + isAdmin: "boolean", + role: type.enumerated("admin", "user"), + }) + const auth = createAuth({ oauth: [], identity: { - schema: UserIdentityArkType.and({ - isAdmin: "boolean", - role: type.enumerated("admin", "user"), - }), + schema, }, }) - type User = InferUser - - expectTypeOf().toEqualTypeOf<{ + type Expected = { sub: string name?: string | null | undefined image?: string | null | undefined email?: string | null | undefined isAdmin: boolean role: "admin" | "user" - }>() + } + type User = InferUser + + expectTypeOf().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() const authClient = createAuthClient({}) expectTypeOf(authClient).toEqualTypeOf<{ diff --git a/packages/core/test/identity.test.ts b/packages/core/test/identity.test.ts index 639f1e1..6af8a52 100644 --- a/packages/core/test/identity.test.ts +++ b/packages/core/test/identity.test.ts @@ -6,6 +6,7 @@ import { UserIdentityTypeBox, UserIdentityValibot, type InferUser, + type UserFrom, } from "@/shared/identity.ts" import { z } from "zod/v4" import * as valibot from "valibot" @@ -59,6 +60,7 @@ describe("createIdentity", () => { }) type ExpectedIdentity = z.infer expectTypeOf().toEqualTypeOf>() + expectTypeOf().toEqualTypeOf>() }) test("createIdentity with Valibot schema", () => { @@ -100,6 +102,7 @@ describe("createIdentity", () => { }) type ExpectedIdentity = valibot.InferOutput expectTypeOf().toEqualTypeOf>() + expectTypeOf().toEqualTypeOf>() }) test("createIdentity with Arktype schema", () => { @@ -151,6 +154,7 @@ describe("createIdentity", () => { }) type ExpectedIdentity = Exclude, ArkErrors> expectTypeOf().toEqualTypeOf>() + expectTypeOf().toEqualTypeOf>() }) test("createIdentity with TypeBox schema", () => {