fix(db): use static zod lookup in toZodSchema so locales tree-shake (#10866)

Co-authored-by: Taesu <166604494+bytaesu@users.noreply.github.com>
Co-authored-by: Taesu <bytaesu@gmail.com>
This commit is contained in:
Svend
2026-10-03 02:33:10 +00:00
committed by GitHub
co-authored by Taesu Taesu
parent 352d04c8eb
commit 3d1f008ae3
5 changed files with 84 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"better-auth": patch
---
The organization plugin no longer pulls every zod locale into server bundles.
+45
View File
@@ -68,6 +68,51 @@ it("build minimal without unexpected imports", async () => {
);
});
/**
* @see https://github.com/better-auth/better-auth/issues/10865
*/
it("build organization plugin without unused zod locales", async () => {
const esbuildDir = join(fixturesDir, "esbuild");
const buildProcess = spawn(
"pnpm",
[
"exec",
"esbuild",
"src/organization.ts",
"--bundle",
"--outfile=dist/organization.js",
],
{
cwd: esbuildDir,
stdio: ["ignore", "inherit", "inherit"],
},
);
await new Promise<void>((resolve, reject) => {
buildProcess.once("error", reject);
buildProcess.once("close", (code) => {
if (code === 0) {
resolve();
} else {
reject(
new Error(`esbuild organization build failed with code ${code}`),
);
}
});
});
const outputFile = join(esbuildDir, "dist", "organization.js");
const outputContent = await readFile(outputFile, "utf-8");
const locales = outputContent.match(/zod\/v4\/locales\/[\w-]+\.js/g) ?? [];
const unusedLocales = locales.filter(
(locale) =>
locale !== "zod/v4/locales/en.js" && locale !== "zod/v4/locales/index.js",
);
assert.deepStrictEqual(
unusedLocales,
[],
"Built output should not contain unused zod locales",
);
});
/**
* @see https://github.com/better-auth/better-auth/issues/10366
*/
+4
View File
@@ -0,0 +1,4 @@
import { betterAuth } from "better-auth/minimal";
import { organization } from "better-auth/plugins";
export const auth = betterAuth({ plugins: [organization()] });
@@ -33,6 +33,24 @@ describe("toZodSchema", () => {
});
});
describe("scalar field types", () => {
it("should map each scalar type to its zod schema", () => {
const schema = toZodSchema({
fields: {
name: { type: "string" },
age: { type: "number" },
active: { type: "boolean" },
createdAt: { type: "date" },
},
isClientSide: true,
});
const valid = { name: "a", age: 1, active: true, createdAt: new Date() };
expect(schema.parse(valid)).toEqual(valid);
expect(schema.safeParse({ ...valid, age: "1" }).success).toBe(false);
});
});
describe("required: false field nullability", () => {
it("should accept null, undefined, and a value for an optional field", () => {
const schema = toZodSchema({
+12 -1
View File
@@ -2,6 +2,17 @@ import type { DBFieldAttribute } from "@better-auth/core/db";
import type { ZodType } from "zod";
import * as z from "zod";
/**
* Static lookup keeps `zod` tree-shakeable. `z[field.type]()` forces bundlers
* to retain every `zod` export, including all locales.
*/
const scalarSchemas = {
string: z.string,
number: z.number,
boolean: z.boolean,
date: z.date,
};
export function toZodSchema<
Fields extends Record<string, DBFieldAttribute | never>,
IsClientSide extends boolean,
@@ -32,7 +43,7 @@ export function toZodSchema<
} else if (Array.isArray(field.type)) {
schema = z.any();
} else {
schema = z[field.type]();
schema = scalarSchemas[field.type]();
}
if (field?.required === false) {