ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

drizzle-typebox 0.3.2 发布解析:getColumns、handleColumns 与 handleEnum 的内部工具函数正式导出

2026/9/19 20:49:22 拓冰建站 浏览量
drizzle-typebox 0.3.2 发布解析:getColumns、handleColumns 与 handleEnum 的内部工具函数正式导出 drizzle-typebox 0.3.2 发布解析getColumns、handleColumns 与 handleEnum 的内部工具函数正式导出【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm本篇技术指南以drizzle-typebox0.3.2 的版本说明为核心展开讲解该版本将getColumns、handleColumns、handleEnum三个内部工具函数从模块内部暴露为公共 API 的意义与用法。读者阅读后将理解这三个函数在 schema 生成流水线中的职责、各参数含义与调用约束并掌握如何基于它们实现自定义的 schema 生成逻辑如接入typeboxInstance自定义 TypeBox 实例同时了解其与createSelectSchema、createInsertSchema、createUpdateSchema的协作关系。一、版本背景从内部实现到公开 APIdrizzle-typebox是 Drizzle ORM 生态中用于将 Drizzle 的表定义Table、视图View与 PostgreSQL 枚举PgEnum自动转换为 TypeBox中已经具备导出全部类型的能力。0.3.2 版本的变更只有一条但意义明确FunctionsgetColumns,handleColumnsandhandleEnumwere exported fromdrizzle-typebox即getColumns、handleColumns、handleEnum这三个函数被正式从drizzle-typebox包导出。在此之前它们是 schema.ts 中仅供内部使用的模块级函数导出后使用者可以直接import { getColumns, handleColumns, handleEnum } from drizzle-typebox从而绕过三个create*Schema高层入口基于底层原语构建自定义的 schema 生成流程。二、三个导出函数的职责与签名1.getColumns统一获取列集合export function getColumns(tableLike: Table | View) { return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike); }作用屏蔽「表」与「视图」在列获取方式上的差异。传入 DrizzleTable时调用getTableColumns传入View时调用getViewSelectedFields返回Recordstring, Column形式的列集合。依赖内部通过drizzle-orm的isTable、getTableColumns、getViewSelectedFields完成判别与取值见 schema.ts。注意isTable与isView是运行时判别函数getColumns本身不处理 PgEnum枚举需走handleEnum。2.handleColumns列集合 → TypeBox TSchema 的核心流水线export function handleColumns( columns: Recordstring, any, refinements: Recordstring, any, conditions: Conditions, factory?: CreateSchemaFactoryOptions, ): TSchema这是整个包的「心脏」负责把Recordstring, Column逐列转换为 TypeBox schema并应用可空nullable、可选optional、排除never三类条件。其内部逻辑schema.ts可以拆解为嵌套对象递归当某个字段既不是Column也不是SQL/SQL.Aliased而是一个普通对象或内嵌的 Table / View时会对它递归调用handleColumns从而支持将关联对象、子查询选择集等结构展开为嵌套的t.Object。refinement 优先级如果refinements[key]已定义且不是函数则直接以该 schema 覆盖该列跳过列类型推断。列类型映射对于Column调用columnToSchema见下文生成基础 schema非列字段如普通 SQL 表达式回退为t.Any()。函数式 refinement若refinements[key]是函数则将其应用于基础 schemarefinement(schema)返回新的 schema。条件过滤与包装按conditions.never决定是否丢弃该列按conditions.nullable用t.Union([schema, t.Null()])包装按conditions.optional用t.Optional(...)包装。最终返回t.Object(columnSchemas)一个描述整个表结构的 TypeBoxTObject。3.handleEnumPgEnum → TypeBox 枚举export function handleEnum(enum_: PgEnumany, factory?: CreateSchemaFactoryOptions) { const typebox: typeof t factory?.typeboxInstance ?? t; return typebox.Enum(mapEnumValues(enum_.enumValues)); }作用将 PostgreSQL 枚举转换为 TypeBox 的TEnum。实现细节mapEnumValues定义于 column.ts将枚举值数组映射为{ value: value }形式的键值对象TypeBox 的Type.Enum恰好接收这种形式。重要限制handleEnum只接受PgEnum。在createSelectSchema中入口会先用isPgEnum见 utils.ts判别实体类型再决定走handleEnum还是handleColumns。MySQL / SQLite 的枚举在 0.3.2 的这条变更范围内并不适用此函数MySQL 枚举列在columnToSchema中通过isWithEnum分支直接处理见 column.ts。三、底层支撑columnToSchema的列类型映射规则handleColumns的核心依赖是columnToSchemacolumn.ts它把 Drizzle 列类型映射为对应的 TypeBox schema。理解它有助于正确使用导出函数Drizzle 列特征生成的 TypeBox schema带enumValues的列t.Enum(mapEnumValues(...))无值时回退t.String()PgGeometry/PgPointTuplet.Tuple([t.Number(), t.Number()])PgGeometryObject/PgPointObjectt.Object({ x: t.Number(), y: t.Number() })PgHalfVector/PgVectort.Array(t.Number())有dimensions时附加minItems/maxItemsPgLinetuple 形式t.Tuple([t.Number(), t.Number(), t.Number()])PgLineABCt.Object({ a, b, c })均为t.Number()PgArrayt.Array(columnToSchema(baseColumn))有size时附加长度约束dataType numbert.Integer/t.Number并按列类型收紧minimum/maximum如MySqlTinyInt带 unsigned 时范围 0~255dataType bigintt.BigInt范围为INT64_MIN~INT64_UNSIGNED_MAXdataType booleant.Boolean()dataType datet.Date()dataType stringt.String()PgUUID加format: uuidPgVarchar/MySQL文本按length/textType收紧maxLength等dataType jsonjsonSchemaliteralSchema与t.Record/t.Array的联合dataType bufferbufferSchema自定义Kind: Buffer类型其他 / 未知t.Any()数值范围常量INT8_MIN等集中定义在 constants.ts。bufferSchema还通过TypeRegistry.Set(Buffer, ...)注册了自定义类型守卫详见 column.ts。四、三个create*Schema入口如何调用导出函数导出的三个函数并非独立存在它们正是createSelectSchema、createInsertSchema、createUpdateSchema与createSchemaFactory的实现基石schema.ts入口实体类型条件集调用链createSelectSchemaTable / View / PgEnumselectConditionsPgEnum →handleEnum否则getColumns→handleColumnscreateInsertSchemaTableinsertConditionsgetColumns→handleColumnscreateUpdateSchemaTableupdateConditionsgetColumns→handleColumnscreateSchemaFactory(options)同 create*同对应入口内部按同样路径调用并透传options.typeboxInstance三种条件集的差异schema.ts值得留意selectnever恒为 false所有列保留optional恒为 falsenullable为!column.notNull。insertnever排除generated.type always与generatedIdentity.type always的列optional为「可空或带默认值」nullable为!column.notNull。updatenever与 insert 相同optional恒为 truenullable为!column.notNull。也就是说导出handleColumns后你可以传入自定义的Conditions对象其类型定义见 schema.types.internal.ts来定义全新的「哪些列排除 / 哪些列可选 / 哪些列可空」策略这是该版本导出最有价值的扩展点。五、实战基于导出函数定制 schema 生成示例 1直接导出单列 schema跳过createSelectSchema对某个具体列例如users.email单独生成并应用 refinementimport { getColumns, handleColumns } from drizzle-typebox; import { Type as t } from sinclair/typebox; import { users } from ./schema; // Drizzle Table const columns getColumns(users); const schema handleColumns( columns, { email: (s) t.String({ ...s, format: email }), }, { never: () false, optional: () false, nullable: (column) !column.notNull, }, ); // 生成结果等价于 createSelectSchema(users, { email: (s) t.String({ ...s, format: email }) })示例 2自定义条件集生成「仅必填字段」schema模拟一种「只要必填列且全部可空」的策略import { handleColumns } from drizzle-typebox; import { getTableColumns } from drizzle-orm; import { users } from ./schema; const requiredOnly { never: (column) Boolean(column?.notNull), // 跳过非空列 optional: () false, nullable: () false, }; const schema handleColumns(getTableColumns(users), {}, requiredOnly);示例 3搭配typeboxInstance使用自定义 TypeBox 实例三个底层函数都接受可选的factory?: CreateSchemaFactoryOptions其唯一字段是typeboxInstanceschema.types.ts。当你引入 TypeBox 的 ESM/自定义构建或需要替换默认Type时import { handleEnum, handleColumns } from drizzle-typebox; import { customType } from ./my-typebox; // 自定义 TypeBox 实例 import { myPgEnum, users } from ./schema; const enumSchema handleEnum(myPgEnum, { typeboxInstance: customType }); const selectSchema handleColumns(getColumns(users), {}, { never: () false, optional: () false, nullable: (column) !column.notNull, }, { typeboxInstance: customType });示例 4直接对 PgEnum 生成 TypeBox 枚举import { handleEnum } from drizzle-typebox; import { roleEnum } from ./schema; // pgEnum(role, [admin, user]) // 等价于 createSelectSchema(roleEnum) const RoleSchema handleEnum(roleEnum); // TypeBox 枚举成员admin | user六、类型层面的配合导出函数在运行时是纯函数但drizzle-typebox的类型层同样完整BuildSchema、BuildRefine、NoUnknownKeys等类型定义schema.types.internal.ts会在编译期校验 refinement 的 key 是否存在于表中——NoUnknownKeys会对未知 key 抛出DrizzleTypeError。因此在使用handleColumns时refinement 对象的键名仍应严格对齐列名类型校验行为与create*Schema保持一致。若需要提取 schema 的静态类型可使用StaticT包的index.ts还导出了bufferSchema、jsonSchema、literalSchema以及全部 schema.types / utils 类型index.ts。七、版本迭代与后续0.3.1导出全部类型含内部类型以规避类型问题并正确处理自定义 JSON 列类型中的无限递归类型见 0.3.1 版本说明。0.3.2本次变更——getColumns、handleColumns、handleEnum从内部函数转为公共导出为高级用户提供底层组装能力。0.3.3随后的版本说明提到 TypeScript 语言服务性能优化说明包的类型计算仍在持续打磨。八、适用前提与限制三个导出函数面向「需要对 schema 生成流程做精细控制」的高级场景绝大多数用户仍应使用createSelectSchema/createInsertSchema/createUpdateSchema/createSchemaFactory作为首选 API。handleEnum仅适用于drizzle-orm/pg-core的PgEnumMySQL / SQLite 的枚举列请走handleColumns由columnToSchema内部处理。getColumns仅接受Table或View传入其他实体如 PgEnum需要先自行判别。若修改conditions自定义策略请参照 Conditions 的签名never/optional/nullable三个谓词保证返回类型为boolean。文中涉及的源码均可直接在仓库中查阅schema.ts、column.ts、utils.ts、constants.ts。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考