From 3310ebc4a0c99d10c7fa13fef269db549a479dcd Mon Sep 17 00:00:00 2001 From: Gautam Manchandani Date: Fri, 12 Jun 2026 05:31:24 +0530 Subject: [PATCH] fix(open-api): mark model ids as required (#9704) --- .../open-api/__snapshots__/open-api.test.ts.snap | 9 +++++++++ .../better-auth/src/plugins/open-api/generator.ts | 10 +++++----- .../src/plugins/open-api/open-api.test.ts | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/better-auth/src/plugins/open-api/__snapshots__/open-api.test.ts.snap b/packages/better-auth/src/plugins/open-api/__snapshots__/open-api.test.ts.snap index e3b444abee..c9d19f0c40 100644 --- a/packages/better-auth/src/plugins/open-api/__snapshots__/open-api.test.ts.snap +++ b/packages/better-auth/src/plugins/open-api/__snapshots__/open-api.test.ts.snap @@ -22,6 +22,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` "type": "string", }, "id": { + "readOnly": true, "type": "string", }, "idToken": { @@ -52,6 +53,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` }, }, "required": [ + "id", "accountId", "providerId", "userId", @@ -72,6 +74,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` "type": "string", }, "id": { + "readOnly": true, "type": "string", }, "ipAddress": { @@ -92,6 +95,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` }, }, "required": [ + "id", "expiresAt", "token", "createdAt", @@ -116,6 +120,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` "type": "boolean", }, "id": { + "readOnly": true, "type": "string", }, "image": { @@ -138,8 +143,10 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` }, }, "required": [ + "id", "name", "email", + "emailVerified", "createdAt", "updatedAt", "role", @@ -158,6 +165,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` "type": "string", }, "id": { + "readOnly": true, "type": "string", }, "identifier": { @@ -173,6 +181,7 @@ exports[`open-api > should generate OpenAPI schema > openAPISchema 1`] = ` }, }, "required": [ + "id", "identifier", "value", "expiresAt", diff --git a/packages/better-auth/src/plugins/open-api/generator.ts b/packages/better-auth/src/plugins/open-api/generator.ts index e7c44a2e96..0743990c16 100644 --- a/packages/better-auth/src/plugins/open-api/generator.ts +++ b/packages/better-auth/src/plugins/open-api/generator.ts @@ -387,15 +387,15 @@ export async function generator(ctx: AuthContext, options: BetterAuthOptions) { >((acc, [key, value]) => { const modelName = key.charAt(0).toUpperCase() + key.slice(1); const fields = value.fields; - const required: string[] = []; + const required = new Set(["id"]); const properties: Record = { - id: { type: "string" }, + id: { type: "string", readOnly: true }, }; Object.entries(fields).forEach(([fieldKey, fieldValue]) => { if (!fieldValue) return; properties[fieldKey] = getFieldSchema(fieldValue); - if (fieldValue.required && fieldValue.input !== false) { - required.push(fieldKey); + if (fieldValue.required && fieldValue.returned !== false) { + required.add(fieldKey); } }); @@ -408,7 +408,7 @@ export async function generator(ctx: AuthContext, options: BetterAuthOptions) { acc[modelName] = { type: "object", properties, - required, + required: Array.from(required), }; return acc; }, {}); diff --git a/packages/better-auth/src/plugins/open-api/open-api.test.ts b/packages/better-auth/src/plugins/open-api/open-api.test.ts index 3455dd423b..6080449589 100644 --- a/packages/better-auth/src/plugins/open-api/open-api.test.ts +++ b/packages/better-auth/src/plugins/open-api/open-api.test.ts @@ -26,15 +26,28 @@ describe("open-api", async () => { expect(schema).toMatchSnapshot("openAPISchema"); }); - it("should have an id field in the User schema", async () => { + it("should mark model id fields as required and read-only", async () => { const schema = await auth.api.generateOpenAPISchema(); const schemas = schema.components.schemas as Record< string, Record >; expect(schemas["User"]!.properties.id).toEqual({ + readOnly: true, type: "string", }); + expect(schemas["User"]!.required).toContain("id"); + expect(schemas["User"]!.properties.emailVerified).toEqual({ + default: false, + readOnly: true, + type: "boolean", + }); + expect(schemas["User"]!.required).toContain("emailVerified"); + expect(schemas["Session"]!.properties.id).toEqual({ + readOnly: true, + type: "string", + }); + expect(schemas["Session"]!.required).toContain("id"); }); it("should include additionalFields in the User schema", async () => {