vite-plugin API
@zod-codepen/vite-plugin 的完整 API 参考。
导出
typescript
import {
generateSchemas,
generateSchemasFromSource,
zodDecouplingAlias,
zodDecouplingStatic,
zodDecoupling,
createZodV3Adapter,
createZodV4Adapter,
defaultFilter,
} from "@zod-codepen/vite-plugin";
// 默认导出等同于 zodDecoupling
import zodDecoupling from "@zod-codepen/vite-plugin";
// 类型导出
import type {
GenerateSchemaOptions,
ZodDecouplingAliasOptions,
ZodAdapter,
SerializeOptions,
} from "@zod-codepen/vite-plugin";generateSchemas()
独立生成函数,将 Zod Schema 对象序列化为纯 TypeScript 代码文件。
签名
typescript
function generateSchemas(options: GenerateSchemaOptions): Promise<void>;参数
GenerateSchemaOptions
typescript
interface GenerateSchemaOptions {
/**
* Schema 映射对象
* 键为导出名称,值为 Zod schema
*/
schemas: Record<string, unknown>;
/**
* 输出文件路径
*/
outputPath: string;
/**
* Zod 版本
* @default 'v4'
*/
zodVersion?: "v3" | "v4";
/**
* 过滤函数,决定哪些 schema 被包含
* @default defaultFilter
*/
filter?: (name: string, schema: unknown) => boolean;
/**
* 是否生成类型导出
* @default true
*/
includeTypes?: boolean;
/**
* 自定义文件头(替换默认的 AUTO-GENERATED 注释)
*/
header?: string;
/**
* 序列化选项,传递给 @zod-codepen/core
*/
serializeOptions?: SerializeOptions;
/**
* 是否输出详细日志
* @default false
*/
verbose?: boolean;
}示例
typescript
import { generateSchemas } from "@zod-codepen/vite-plugin";
import * as schemas from "./src/runtime/schema.js";
// 基本用法
await generateSchemas({
schemas,
outputPath: "./src/generated/schemas.ts",
});
// 完整配置
await generateSchemas({
schemas,
outputPath: "./src/generated/schemas.ts",
zodVersion: "v4",
filter: (name) => name.startsWith("Api"),
includeTypes: true,
header: "// Custom header",
serializeOptions: { format: true },
verbose: true,
});输出格式
typescript
/**
* AUTO-GENERATED FILE - DO NOT EDIT
*
* Generated by @zod-codepen/vite-plugin at 2025-12-11T00:00:00.000Z
*/
import { z } from "zod/v4";
export const User = z.object({
id: z.number(),
name: z.string(),
});
// Type exports
export type User = z.infer<typeof User>;zodDecouplingAlias()
轻量级 Vite 插件,仅设置模块别名。
签名
typescript
function zodDecouplingAlias(options: ZodDecouplingAliasOptions): Plugin;参数
ZodDecouplingAliasOptions
typescript
interface ZodDecouplingAliasOptions {
/**
* 要替换的导入路径(代码中使用的相对路径)
* @example '../runtime/schema.js'
*/
aliasFrom: string;
/**
* 目标文件路径(相对于项目根目录)
* @example './src/generated/api-schemas.ts'
*/
aliasTo: string;
}返回值
返回 Vite 插件对象:
typescript
{
name: 'zod-decoupling-alias',
enforce: 'pre',
config(userConfig) { /* 设置 resolve.alias */ }
}示例
typescript
import { defineConfig } from "vite";
import { zodDecouplingAlias } from "@zod-codepen/vite-plugin";
export default defineConfig({
plugins: [
zodDecouplingAlias({
aliasFrom: "../runtime/schema.js",
aliasTo: "./src/generated/api-schemas.ts",
}),
],
});工作原理
构建时,Vite 会将所有对 aliasFrom 的导入替换为 aliasTo 指向的文件:
typescript
// 源代码
import { User } from "../runtime/schema.js";
// 构建后实际解析为
import { User } from "/absolute/path/to/src/generated/api-schemas.ts";zodDecoupling()
完整的 Vite 插件,在 buildStart 时自动生成 Schema 并设置别名。
签名
typescript
function zodDecoupling(options: ZodDecouplingOptions): Plugin;参数
typescript
interface ZodDecouplingOptions {
/**
* Schema 入口文件路径(相对于项目根目录)
*/
schemaEntry: string;
/**
* 输出文件路径
*/
outputPath: string;
/**
* 要替换的导入路径
*/
aliasFrom: string;
/**
* Zod 版本
* @default 'v4'
*/
zodVersion?: "v3" | "v4";
/**
* 过滤函数
* @default defaultFilter
*/
filter?: (name: string, schema: unknown) => boolean;
/**
* 是否生成类型导出
* @default true
*/
includeTypes?: boolean;
/**
* 自定义文件头
*/
header?: string;
/**
* 序列化选项
*/
serializeOptions?: SerializeOptions;
/**
* 是否输出详细日志
* @default false
*/
verbose?: boolean;
}返回值
返回 Vite 插件对象:
typescript
{
name: 'zod-decoupling',
enforce: 'pre',
configResolved(config) { /* 保存 root */ },
buildStart() { /* 生成 schema 文件 */ },
config(userConfig) { /* 设置 resolve.alias */ }
}示例
typescript
import { defineConfig } from "vite";
import { zodDecoupling } from "@zod-codepen/vite-plugin";
export default defineConfig({
plugins: [
zodDecoupling({
schemaEntry: "./src/runtime/schema.ts",
outputPath: "./src/generated/api-schemas.ts",
aliasFrom: "../runtime/schema.js",
zodVersion: "v4",
verbose: true,
}),
],
});限制
此插件在 buildStart 时动态导入 schemaEntry。如果该文件依赖服务端库(如 drizzle-orm),导入可能失败。这种情况下,请使用独立脚本模式 + zodDecouplingAlias。
zodDecouplingStatic
静态提取插件。不执行用户代码,通过 TypeScript compiler API 将源码 AST 转成 IR 再 codegen 为纯 Zod 代码。适合 schema 依赖 drizzle-orm 等重运行时的场景。详见 静态提取指南。
generateSchemasFromSource
静态生成函数。接收 TypeScript 源码字符串,使用 castAllFromAst 提取所有 schema 并写入文件。不执行用户代码。
createZodV3Adapter()
创建 Zod v3 适配器实例。
签名
typescript
function createZodV3Adapter(): ZodAdapter;返回值
typescript
interface ZodAdapter {
version: "v3" | "v4";
getType(schema: unknown): string | undefined;
getDef(schema: unknown): Record<string, unknown> | undefined;
isZodSchema(value: unknown): boolean;
}示例
typescript
import { createZodV3Adapter } from "@zod-codepen/vite-plugin";
import { z } from "zod";
const adapter = createZodV3Adapter();
console.log(adapter.version); // 'v3'
console.log(adapter.isZodSchema(z.string())); // true
console.log(adapter.getType(z.string())); // 'string'createZodV4Adapter()
创建 Zod v4 适配器实例。
签名
typescript
function createZodV4Adapter(): ZodAdapter;示例
typescript
import { createZodV4Adapter } from "@zod-codepen/vite-plugin";
import { z } from "zod/v4"; // zod v4
const adapter = createZodV4Adapter();
console.log(adapter.version); // 'v4'
console.log(adapter.isZodSchema(z.string())); // true
console.log(adapter.getType(z.string())); // 'string'Zod v4 变体兼容性
适配器支持所有 Zod v4 变体的内部结构:
zod(默认)zod/v4zod/v4/classiczod/v4/corezod/v4/minizod/mini
defaultFilter()
默认的 schema 过滤函数。
签名
typescript
function defaultFilter(name: string): boolean;行为
- 排除以
$开头的名称(内部变量)
示例
typescript
import { defaultFilter } from "@zod-codepen/vite-plugin";
defaultFilter("User"); // true
defaultFilter("$internal"); // false
defaultFilter("UserType"); // true自定义过滤器
typescript
const customFilter = (name: string) => {
// 先应用默认过滤
if (!defaultFilter(name)) return false;
// 额外过滤:只包含 Api 前缀
return name.startsWith("Api");
};
await generateSchemas({
schemas,
outputPath: "./output.ts",
filter: customFilter,
});类型定义
SerializeOptions
从 @zod-codepen/core 重导出,用于控制序列化行为:
typescript
interface SerializeOptions {
/**
* 是否格式化输出(添加缩进和换行)
* @default true
*/
format?: boolean;
/**
* 缩进字符串
* @default ' '(两个空格)
*/
indent?: string;
}ZodAdapter
适配器接口,用于处理不同版本的 Zod:
typescript
interface ZodAdapter {
version: "v3" | "v4";
getType(schema: unknown): string | undefined;
getDef(schema: unknown): Record<string, unknown> | undefined;
isZodSchema(value: unknown): boolean;
}错误处理
generateSchemas 错误
如果单个 schema 序列化失败,函数会:
- 输出警告到控制台
- 生成
z.unknown()作为占位符 - 继续处理其他 schema
typescript
// 输出
console.warn(`[zod-decoupling] Failed to serialize 'BrokenSchema':`, error);
// 生成的代码
export const BrokenSchema = z.unknown(); // Serialization failedzodDecoupling 错误
如果 schemaEntry 导入失败:
- 输出错误到控制台
- 抛出错误,构建停止
typescript
console.error(`[zod-decoupling] Failed to import schemas:`, error);完整示例
独立脚本
typescript
// scripts/generate.ts
import { generateSchemas, defaultFilter } from "@zod-codepen/vite-plugin";
const schemas = await import("../src/runtime/schema.js");
await generateSchemas({
schemas,
outputPath: "./src/generated/api-schemas.ts",
zodVersion: "v4",
filter: (name, schema) => {
if (!defaultFilter(name)) return false;
// 额外逻辑
return true;
},
includeTypes: true,
serializeOptions: { format: true },
verbose: true,
});
console.log("Done!");Vite 配置
typescript
// vite.config.ts
import { defineConfig } from "vite";
import { zodDecouplingAlias } from "@zod-codepen/vite-plugin";
export default defineConfig(({ mode }) => ({
plugins: [
mode === "production" &&
zodDecouplingAlias({
aliasFrom: "../runtime/schema.js",
aliasTo: "./src/generated/api-schemas.ts",
}),
].filter(Boolean),
}));package.json
json
{
"scripts": {
"generate:schemas": "tsx scripts/generate.ts",
"build": "pnpm generate:schemas && vite build",
"dev": "vite"
}
}