npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wordrhyme/auto-crud

v1.0.1

Published

Schema-first CRUD components with auto-generated tables and forms

Readme

@wordrhyme/auto-crud

Schema-first CRUD components with auto-generated tables and forms

基于 Zod Schema 自动生成完整 CRUD 界面的低代码 React 组件库。

npm version License: MIT


✨ 特性

  • 🚀 零配置 CRUD: 从 Zod Schema 自动生成表格和表单
  • 🎨 高级数据表格: 基于 TanStack Table,支持排序、过滤、分页
  • 📝 智能表单: 集成 Formily,支持复杂表单联动
  • 🔌 灵活集成: 支持 tRPC、REST API 或内存数据源
  • 🎯 类型安全: 完整的 TypeScript 类型推断
  • 🌐 URL 状态同步: 使用 nuqs 实现 URL 状态管理
  • 🎭 三种过滤模式: Simple / Advanced / Command
  • 🔄 批量操作: 支持批量更新和删除

📦 安装

# pnpm
pnpm add @wordrhyme/auto-crud zod sonner

# npm
npm install @wordrhyme/auto-crud zod sonner

# yarn
yarn add @wordrhyme/auto-crud zod sonner

Peer Dependencies

{
  "react": "^18.0.0 || ^19.0.0",
  "react-dom": "^18.0.0 || ^19.0.0",
  "sonner": "^2.0.0",
  "zod": "^3.0.0 || ^4.0.0"
}

🚀 快速开始

基础示例

import { AutoCrudTable, useAutoCrudResource, createMemoryDataSource } from "@wordrhyme/auto-crud";
import { z } from "zod";

// 1. 定义 Zod Schema
const taskSchema = z.object({
  id: z.string(),
  title: z.string(),
  status: z.enum(["todo", "in-progress", "done"]),
  priority: z.enum(["low", "medium", "high"]),
  createdAt: z.date(),
});

type Task = z.infer<typeof taskSchema>;

// 2. 创建数据源
const dataSource = createMemoryDataSource<Task>({
  data: [
    { id: "1", title: "Task 1", status: "todo", priority: "high", createdAt: new Date() },
    { id: "2", title: "Task 2", status: "done", priority: "low", createdAt: new Date() },
  ],
  onCreate: async (data) => { /* 创建逻辑 */ },
  onUpdate: async (id, data) => { /* 更新逻辑 */ },
  onDelete: async (id) => { /* 删除逻辑 */ },
});

// 3. 使用组件
function TasksPage() {
  const resource = useAutoCrudResource({
    dataSource,
    schema: taskSchema,
  });

  return (
    <AutoCrudTable
      title="任务管理"
      schema={taskSchema}
      resource={resource}
    />
  );
}

与 tRPC 集成

import { AutoCrudTable, useAutoCrudResource, createTRPCDataSource } from "@wordrhyme/auto-crud";
import { trpc } from "@/lib/trpc/client";
import { createSelectSchema } from "drizzle-zod";
import { tasks } from "@/db/schema";

const taskSchema = createSelectSchema(tasks);

function TasksPage() {
  // URL 状态管理
  const [queryParams] = useQueryStates({
    page: parseAsInteger.withDefault(1),
    perPage: parseAsInteger.withDefault(10),
    sort: getSortingStateParser().withDefault([]),
    filters: getFiltersStateParser().withDefault([]),
  });

  // 创建 tRPC 数据源
  const dataSource = createTRPCDataSource({
    router: trpc.tasks,
    queryInput: queryParams,
  });

  const resource = useAutoCrudResource({
    dataSource,
    schema: taskSchema,
  });

  return (
    <AutoCrudTable
      title="任务管理"
      schema={taskSchema}
      resource={resource}
      fields={{
        id: { hidden: true },
        status: { label: "状态" },
        priority: { label: "优先级" },
      }}
      table={{
        filterModes: ["simple", "advanced", "command"],
        batchFields: ["status", "priority"],
      }}
    />
  );
}

📖 核心概念

Schema First 理念

Zod Schema → 自动推断字段类型 → 生成表格列 + 表单字段

优势

  • ✅ 单一数据源(SSOT)
  • ✅ 类型安全
  • ✅ 零手动配置
  • ✅ Schema 变更自动同步

数据源(Data Source)

@wordrhyme/auto-crud 支持三种数据源:

1. 内存数据源(Memory Data Source)

适合:原型开发、演示、测试

import { createMemoryDataSource } from "@wordrhyme/auto-crud";

const dataSource = createMemoryDataSource({
  data: initialData,
  onCreate: async (data) => { /* ... */ },
  onUpdate: async (id, data) => { /* ... */ },
  onDelete: async (id) => { /* ... */ },
});

2. tRPC 数据源(tRPC Data Source)

适合:全栈 TypeScript 项目

import { createTRPCDataSource } from "@wordrhyme/auto-crud";

const dataSource = createTRPCDataSource({
  router: trpc.tasks,
  queryInput: { page: 1, perPage: 10 },
});

要求:后端需要使用 @wordrhyme/auto-crud-server 创建 CRUD 路由。

3. 自定义数据源(Custom Data Source)

适合:REST API、GraphQL 等

const dataSource: DataSource<Task> = {
  list: async (params) => {
    const response = await fetch(`/api/tasks?${new URLSearchParams(params)}`);
    return response.json();
  },
  get: async (id) => {
    const response = await fetch(`/api/tasks/${id}`);
    return response.json();
  },
  create: async (data) => {
    const response = await fetch("/api/tasks", {
      method: "POST",
      body: JSON.stringify(data),
    });
    return response.json();
  },
  update: async (id, data) => {
    const response = await fetch(`/api/tasks/${id}`, {
      method: "PATCH",
      body: JSON.stringify(data),
    });
    return response.json();
  },
  delete: async (id) => {
    await fetch(`/api/tasks/${id}`, { method: "DELETE" });
  },
  deleteMany: async (ids) => {
    await fetch("/api/tasks/batch", {
      method: "DELETE",
      body: JSON.stringify({ ids }),
    });
  },
};

🎨 组件 API

<AutoCrudTable />

完整的 CRUD 表格组件。

Props

interface AutoCrudTableProps<TSchema> {
  // 必需
  schema: TSchema;                              // Zod Schema
  resource: UseAutoCrudResourceReturn<TSchema>; // useAutoCrudResource 返回值

  // 可选
  title?: string;
  description?: string;
  fields?: Fields;                              // 统一字段配置
  table?: {
    hidden?: string[];                          // 隐藏的列
    overrides?: Record<string, any>;            // 列覆盖配置
    filterModes?: FilterMode | FilterMode[];    // 过滤模式
    batchFields?: (string | BatchUpdateField)[]; // 批量更新字段
    defaultSort?: any[];                        // 默认排序
  };
  form?: {
    overrides?: Record<string, any>;            // 表单覆盖配置
    columns?: number;                           // 表单列数
  };
  slots?: {
    toolbarStart?: React.ReactNode;             // 工具栏左侧插槽
    toolbarEnd?: React.ReactNode;               // 工具栏右侧插槽
    rowActions?: (row) => Array<{ label: string; onClick: () => void }>;
  };
}

useAutoCrudResource()

连接数据源到组件的 Hook。

参数

interface UseAutoCrudResourceConfig<TData> {
  dataSource: DataSource<TData>;  // 数据源
  schema: z.ZodType<TData>;       // Zod Schema
}

返回值

interface UseAutoCrudResourceReturn<TSchema, TData> {
  // 表格数据
  tableData: {
    data: TData[];
    pageCount: number;
  };

  // 模态框状态
  modal: {
    variant: "dialog" | "sheet";
    createOpen: boolean;
    editOpen: boolean;
    viewOpen: boolean;
    deleteOpen: boolean;
    selected: TData | null;
    copySource: TData | null;
  };

  // 操作方法
  handlers: {
    openCreate: () => void;
    openEdit: (item: TData) => void;
    openView: (item: TData) => void;
    openDelete: (item: TData) => void;
    copyRow: (item: TData) => void;
    closeModals: () => void;
    submitCreate: (data: TData) => Promise<void>;
    submitUpdate: (data: TData) => Promise<void>;
    confirmDelete: () => Promise<void>;
    deleteMany: (rows: TData[]) => Promise<void>;
    updateMany: (rows: TData[], data: Record<string, unknown>) => Promise<void>;
  };

  // 加载状态
  mutations: {
    isCreating: boolean;
    isUpdating: boolean;
    isDeleting: boolean;
  };
}

🔧 字段配置

Field 类型

interface Field {
  /** 字段标签(表格和表单共用) */
  label?: string;
  /** 是否隐藏(表格和表单都隐藏) */
  hidden?: boolean;
  /** 表格特定配置 */
  table?: {
    hidden?: boolean;                    // 仅表格隐藏
    meta?: Record<string, unknown>;      // 筛选器配置
    [key: string]: unknown;
  };
  /** 表单特定配置 */
  form?: {
    "x-hidden"?: boolean;                // 仅表单隐藏
    "x-component"?: string;              // 组件类型
    "x-component-props"?: Record<string, unknown>;  // 组件属性
    "x-reactions"?: object;              // 字段联动
    [key: string]: unknown;
  };
}

type Fields = Record<string, Field>;

基础配置

<AutoCrudTable
  schema={taskSchema}
  resource={resource}
  fields={{
    id: { hidden: true },           // 表格和表单都隐藏
    title: { label: "标题" },        // 自定义标签
    createdAt: {
      label: "创建时间",
      form: { "x-hidden": true },    // 仅表单隐藏
    },
  }}
/>

表格筛选器配置

<AutoCrudTable
  schema={taskSchema}
  resource={resource}
  fields={{
    status: {
      label: "状态",
      table: {
        meta: {
          variant: "select",  // "text" | "select" | "multiSelect" | "date" | "dateRange" | "range"
          options: [
            { label: "待处理", value: "pending" },
            { label: "已完成", value: "completed" },
          ],
        },
      },
    },
    amount: {
      label: "金额",
      table: {
        meta: {
          variant: "range",
          range: [0, 10000],
          unit: "¥",
        },
      },
    },
  }}
/>

表单组件配置

<AutoCrudTable
  schema={taskSchema}
  resource={resource}
  fields={{
    description: {
      label: "描述",
      form: {
        "x-component": "Textarea",
        "x-component-props": { rows: 5 },
      },
    },
    assignee: {
      label: "负责人",
      form: {
        "x-component": "Combobox",
        "x-component-props": { placeholder: "选择负责人" },
      },
    },
  }}
/>

字段联动

<AutoCrudTable
  schema={taskSchema}
  resource={resource}
  fields={{
    endDate: {
      label: "结束日期",
      form: {
        "x-reactions": {
          dependencies: ["startDate"],
          when: "{{$deps[0] !== undefined}}",
          fulfill: {
            state: {
              visible: true,
              disabled: false,
            },
          },
        },
      },
    },
  }}
/>

🎯 过滤模式

Simple 模式(默认)

  • 适合:快速筛选常用字段
  • 特点:下拉选择框,一键清除
  • 示例:状态筛选、优先级筛选
table={{
  filterModes: "simple",
}}

Advanced 模式(高级筛选)

  • 适合:复杂多条件查询
  • 特点:Notion 风格,支持 AND/OR 逻辑
  • 示例:status = "done" AND priority = "high"
table={{
  filterModes: "advanced",
}}

Command 模式(命令面板)

  • 适合:键盘流用户
  • 特点:Linear 风格,快捷键 Cmd+K
  • 示例:快速搜索并添加筛选条件
table={{
  filterModes: "command",
}}

多模式切换

table={{
  filterModes: ["simple", "advanced", "command"],  // 第一个为默认模式
}}

🔄 批量操作

批量更新

<AutoCrudTable
  schema={taskSchema}
  resource={resource}
  table={{
    batchFields: ["status", "priority"],
  }}
/>

功能

  • 选择多行
  • 点击批量更新按钮
  • 选择字段和新值
  • 一键更新所有选中行

批量删除

// 自动启用,无需配置
<AutoCrudTable schema={taskSchema} resource={resource} />

功能

  • 选择多行
  • 点击批量删除按钮
  • 确认删除
  • 一次性删除所有选中行

🔌 与其他库集成

与 Drizzle ORM 集成

import { createSelectSchema } from "drizzle-zod";
import { tasks } from "@/db/schema";

const taskSchema = createSelectSchema(tasks);

<AutoCrudTable schema={taskSchema} resource={resource} />

与 Next.js 集成

// app/tasks/page.tsx
"use client";

import { AutoCrudTable } from "@wordrhyme/auto-crud";

export default function TasksPage() {
  return <AutoCrudTable schema={taskSchema} resource={resource} />;
}

🧰 工具函数

Schema Bridge - 核心转换函数

import {
  parseZodField,        // 解析 Zod 字段类型
  createTableSchema,        // Zod Schema → TanStack Table 列定义
  createSelectColumn,   // 创建选择列
  createActionsColumn,  // 创建操作列
  createFormSchema,     // Zod Schema → Formily Schema
  createEditFormSchema, // 创建编辑表单 Schema(排除 id, createdAt, updatedAt)
} from "@wordrhyme/auto-crud";

自定义列渲染

使用 createTableSchemaoverrides 参数自定义列渲染:

import { createTableSchema } from "@wordrhyme/auto-crud";
import { Badge } from "@shadcn/ui";

const columns = createTableSchema(taskSchema, {
  overrides: {
    status: {
      label: "状态",
      // 自定义 cell 渲染
      cell: ({ row }) => {
        const status = row.getValue("status");
        return (
          <Badge variant={status === "done" ? "success" : "secondary"}>
            {status}
          </Badge>
        );
      },
    },
    priority: {
      label: "优先级",
      // 自定义列配置
      size: 100,
      enableSorting: false,
    },
  },
  exclude: ["id", "createdAt"],  // 排除字段
});

自定义表单渲染

使用 createFormSchemaoverrides 参数自定义表单组件:

import { createFormSchema } from "@wordrhyme/auto-crud";

const formSchema = createFormSchema(taskSchema, {
  overrides: {
    description: {
      "x-component": "Textarea",
      "x-component-props": { rows: 5 },
    },
    status: {
      "x-component": "Select",
      "x-component-props": {
        options: [
          { label: "待办", value: "todo" },
          { label: "完成", value: "done" },
        ],
      },
    },
    dueDate: {
      "x-component": "DatePicker",
      "x-component-props": { format: "YYYY-MM-DD" },
    },
  },
  layout: "grid",
  gridColumns: 2,
  exclude: ["id", "createdAt"],
});

🔀 三种 Schema 类型

@wordrhyme/auto-crud 支持三种 Schema 输入格式,通过 SchemaAdapter 统一处理:

1. Zod Schema(推荐)

import { z } from "zod";

const taskSchema = z.object({
  id: z.string(),
  title: z.string(),
  status: z.enum(["todo", "in-progress", "done"]),
  priority: z.enum(["low", "medium", "high"]),
  createdAt: z.date(),
});

2. JSON Schema

import type { JSONSchema } from "@wordrhyme/auto-crud";

const taskSchema: JSONSchema = {
  type: "object",
  properties: {
    id: { type: "string" },
    title: { type: "string", title: "标题" },
    status: {
      type: "string",
      enum: ["todo", "in-progress", "done"],
      title: "状态",
    },
    createdAt: { type: "string", format: "date-time" },
  },
  required: ["id", "title"],
};

3. 简化配置(Simple Config)

import type { SimpleFieldsConfig } from "@wordrhyme/auto-crud";

const taskSchema: SimpleFieldsConfig = {
  id: { type: "string", required: true },
  title: { type: "string", label: "标题", required: true },
  status: {
    type: "select",
    label: "状态",
    options: ["todo", "in-progress", "done"],
  },
  description: { type: "textarea", label: "描述" },
  createdAt: { type: "datetime" },
};

SchemaAdapter 使用

import { SchemaAdapter } from "@wordrhyme/auto-crud";

// 自动检测 Schema 类型
const type = SchemaAdapter.detectType(schema);  // "zod" | "json" | "simple"

// 转换为统一的字段定义
const fields = SchemaAdapter.toUnified(schema);

// 转换为 Formily Schema
const formilySchema = SchemaAdapter.toFormily(fields);

🧩 基础组件(自定义组合)

如果 AutoCrudTable 不能满足需求,可以使用基础组件自行组合:

组件层级

AutoCrudTable         ← 高级封装,一站式 CRUD
  ├── AutoTable       ← 表格 + 工具栏 + 筛选器
  │   ├── DataTable   ← 纯表格组件(TanStack Table)
  │   ├── AutoTableActionBar    ← 批量操作栏
  │   └── AutoTableSimpleFilters ← 简单筛选器
  ├── AutoForm        ← 表单组件(Formily)
  └── CrudFormModal   ← 表单弹窗(创建/编辑/查看)

使用 DataTable 组件

import { DataTable, createTableSchema, createSelectColumn, createActionsColumn } from "@wordrhyme/auto-crud";

function CustomTable({ data }) {
  const columns = [
    createSelectColumn(),
    ...createTableSchema(taskSchema, { exclude: ["id"] }),
    createActionsColumn({
      onEdit: (row) => console.log("Edit", row),
      onDelete: (row) => console.log("Delete", row),
      onView: (row) => console.log("View", row),
      onCopy: (row) => console.log("Copy", row),
    }),
  ];

  return (
    <DataTable
      columns={columns}
      data={data}
      pageCount={10}
    />
  );
}

使用 AutoForm 组件

import { AutoForm, createFormSchema } from "@wordrhyme/auto-crud";
import { createForm } from "@formily/core";

function CustomForm() {
  const form = createForm();
  const formSchema = createFormSchema(taskSchema, {
    exclude: ["id", "createdAt"],
    layout: "grid",
    gridColumns: 2,
  });

  return (
    <AutoForm
      form={form}
      schema={formSchema}
      onSubmit={(values) => console.log(values)}
    />
  );
}

使用 useDataTable Hook

import { useDataTable, DataTable, DataTablePagination } from "@wordrhyme/auto-crud";

function CustomDataTable({ data, pageCount }) {
  const { table } = useDataTable({
    data,
    columns,
    pageCount,
    initialState: {
      pagination: { pageIndex: 0, pageSize: 10 },
      sorting: [{ id: "createdAt", desc: true }],
    },
  });

  return (
    <div>
      <DataTable table={table} />
      <DataTablePagination table={table} />
    </div>
  );
}

组件组合示例

import {
  AutoTable,
  AutoForm,
  CrudFormModal,
  useAutoCrudResource,
  createTableSchema,
  createFormSchema,
} from "@wordrhyme/auto-crud";

function CustomCrudPage() {
  const resource = useAutoCrudResource({ dataSource, schema: taskSchema });

  const columns = createTableSchema(taskSchema, {
    overrides: {
      status: {
        cell: ({ row }) => <StatusBadge status={row.getValue("status")} />,
      },
    },
  });

  const formSchema = createFormSchema(taskSchema, {
    exclude: ["id", "createdAt", "updatedAt"],
  });

  return (
    <div>
      {/* 自定义表格 */}
      <AutoTable
        columns={columns}
        data={resource.tableData.data}
        pageCount={resource.tableData.pageCount}
        filterMode="simple"
      />

      {/* 自定义表单弹窗 */}
      <CrudFormModal
        mode={resource.modal.editOpen ? "edit" : "create"}
        open={resource.modal.createOpen || resource.modal.editOpen}
        onClose={resource.handlers.closeModals}
        schema={formSchema}
        initialValues={resource.modal.selected}
        onSubmit={resource.modal.editOpen
          ? resource.handlers.submitUpdate
          : resource.handlers.submitCreate}
      />
    </div>
  );
}

📦 导出的类型

// Auto-CRUD 组件
export { AutoCrudTable } from "./components/auto-crud/auto-crud-table";
export type { Field, Fields, AutoCrudTableProps } from "./components/auto-crud/auto-crud-table";
export { AutoForm } from "./components/auto-crud/auto-form";
export { AutoTable } from "./components/auto-crud/auto-table";
export { AutoTableActionBar } from "./components/auto-crud/auto-table-action-bar";
export { AutoTableSimpleFilters } from "./components/auto-crud/auto-table-simple-filters";
export { CrudFormModal } from "./components/auto-crud/crud-form-modal";

// 数据表格组件
export { DataTable } from "./components/data-table/data-table";
export { DataTableAdvancedToolbar } from "./components/data-table/data-table-advanced-toolbar";
export { DataTableColumnHeader } from "./components/data-table/data-table-column-header";
export { DataTableFacetedFilter } from "./components/data-table/data-table-faceted-filter";
export { DataTablePagination } from "./components/data-table/data-table-pagination";
export { DataTableToolbar } from "./components/data-table/data-table-toolbar";
export { DataTableViewOptions } from "./components/data-table/data-table-view-options";

// Hooks
export { useAutoCrudResource, noopToastAdapter } from "./hooks/use-auto-crud-resource";
export type { ToastAdapter, CrudHooks, UseAutoCrudResourceOptions } from "./hooks/use-auto-crud-resource";
export { useDataTable } from "./hooks/use-data-table";
export { useReadableFilters } from "./hooks/use-readable-filters";
export { useUrlState, useQueryState, useQueryStates } from "./hooks/use-url-state";

// Schema Bridge - 核心工具
export { parseZodField, createTableSchema, createSelectColumn, createActionsColumn } from "./lib/schema-bridge/zod-to-columns";
export { createFormSchema, createEditFormSchema } from "./lib/schema-bridge/zod-to-formily";
export { SchemaAdapter } from "./lib/schema-bridge/schema-adapter";
export type {
  ColumnOverrides, FormSchemaOverrides,
  CreateTableSchemaOptions, CreateFormSchemaOptions,
  UnifiedSchema, JSONSchema, SimpleFieldsConfig, UnifiedField,
} from "./lib/schema-bridge";

// 数据源
export { createTRPCDataSource, createMemoryDataSource } from "./lib/data-source";
export type { DataSource, ListParams, ListResult } from "./lib/data-source";

// 工具函数
export { cn } from "./lib/utils";
export { formatDate } from "./lib/format";
export { humanize } from "./lib/humanize";

🤝 贡献

欢迎贡献代码!请查看 CONTRIBUTING.md


📄 许可证

MIT © wordrhyme


🔗 相关链接


💡 灵感来源