Skip to content

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/v4
  • zod/v4/classic
  • zod/v4/core
  • zod/v4/mini
  • zod/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 序列化失败,函数会:

  1. 输出警告到控制台
  2. 生成 z.unknown() 作为占位符
  3. 继续处理其他 schema
typescript
// 输出
console.warn(`[zod-decoupling] Failed to serialize 'BrokenSchema':`, error);

// 生成的代码
export const BrokenSchema = z.unknown(); // Serialization failed

zodDecoupling 错误 ​

如果 schemaEntry 导入失败:

  1. 输出错误到控制台
  2. 抛出错误,构建停止
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"
  }
}

Released under the MPL 2.0 License.